落地陆运群内协同:按填写样例拉群并只列本单协同项,进群把私聊已抽到的字段带上。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -67,6 +67,21 @@ class WeComAppClient:
|
||||
副作用:出站 HTTP 调企微;失败返回 ok=False,由 outbox 重试。
|
||||
"""
|
||||
extra = dict(payload or {})
|
||||
if extra.get("msgtype") == "image":
|
||||
image_result = self.send_image(
|
||||
touser=touser,
|
||||
filename=str(extra.get("filename") or "image.png"),
|
||||
filepath=str(extra.get("filepath") or ""),
|
||||
file_b64=str(extra.get("file_b64") or extra.get("fileBase64") or ""),
|
||||
)
|
||||
if image_result.ok:
|
||||
return image_result
|
||||
logger.warning(
|
||||
"图片发送失败,回退文本 err=%s:%s",
|
||||
image_result.errcode,
|
||||
image_result.errmsg,
|
||||
)
|
||||
return self.send_text(touser=touser, content=content)
|
||||
if extra.get("msgtype") == "file":
|
||||
file_result = self.send_file(
|
||||
touser=touser,
|
||||
@@ -213,7 +228,9 @@ class WeComAppClient:
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg=f"b64:{exc}")
|
||||
if not raw:
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg="file_empty")
|
||||
media_id, up = self._upload_media(filename=filename or "quote.xlsx", content=raw)
|
||||
media_id, up = self._upload_media(
|
||||
filename=filename or "quote.xlsx", content=raw, media_type="file"
|
||||
)
|
||||
if not media_id:
|
||||
return up
|
||||
return self._post_message(
|
||||
@@ -226,8 +243,64 @@ class WeComAppClient:
|
||||
preview=f"[file]{filename}",
|
||||
)
|
||||
|
||||
def _upload_media(self, *, filename: str, content: bytes) -> tuple[str, WeComSendResult]:
|
||||
"""cgi-bin/media/upload;密钥不写日志。"""
|
||||
def send_image(
|
||||
self,
|
||||
*,
|
||||
touser: str,
|
||||
filename: str,
|
||||
filepath: str = "",
|
||||
file_b64: str = "",
|
||||
) -> WeComSendResult:
|
||||
"""
|
||||
先上传 image 素材再发图片消息,聊天里直接看图。
|
||||
|
||||
字节来自本机路径或 Base64。禁止在回调线程调用。
|
||||
"""
|
||||
if not touser:
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg="touser 为空")
|
||||
raw = b""
|
||||
if filepath:
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
raw = Path(filepath).read_bytes()
|
||||
except OSError as exc:
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg=f"read_file:{exc}")
|
||||
elif file_b64:
|
||||
import base64
|
||||
|
||||
try:
|
||||
raw = base64.b64decode(file_b64)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg=f"b64:{exc}")
|
||||
if not raw:
|
||||
return WeComSendResult(ok=False, errcode=-1, errmsg="image_empty")
|
||||
name = filename or "image.png"
|
||||
media_id, up = self._upload_media(
|
||||
filename=name, content=raw, media_type="image"
|
||||
)
|
||||
if not media_id:
|
||||
return up
|
||||
return self._post_message(
|
||||
{
|
||||
"touser": touser,
|
||||
"msgtype": "image",
|
||||
"agentid": self._agent_id,
|
||||
"image": {"media_id": media_id},
|
||||
},
|
||||
preview=f"[image]{name}",
|
||||
)
|
||||
|
||||
def _upload_media(
|
||||
self,
|
||||
*,
|
||||
filename: str,
|
||||
content: bytes,
|
||||
media_type: str = "file",
|
||||
) -> tuple[str, WeComSendResult]:
|
||||
"""cgi-bin/media/upload;type=file 或 image。密钥不写日志。"""
|
||||
kind = (media_type or "file").strip() or "file"
|
||||
mime = "image/png" if kind == "image" else "application/octet-stream"
|
||||
if not self._corp_id or not self._secret:
|
||||
return "", WeComSendResult(ok=False, errcode=-1, errmsg="WECOM_CORP_ID/SECRET 未配置")
|
||||
try:
|
||||
@@ -240,8 +313,8 @@ class WeComAppClient:
|
||||
with httpx.Client(timeout=max(self._timeout, 30.0)) as client:
|
||||
resp = client.post(
|
||||
url,
|
||||
params={"access_token": token, "type": "file"},
|
||||
files={"media": (filename, content, "application/octet-stream")},
|
||||
params={"access_token": token, "type": kind},
|
||||
files={"media": (filename, content, mime)},
|
||||
)
|
||||
data = resp.json()
|
||||
except Exception as exc: # noqa: BLE001
|
||||
@@ -250,7 +323,7 @@ class WeComAppClient:
|
||||
errcode = int(data.get("errcode") or 0)
|
||||
media_id = str(data.get("media_id") or "")
|
||||
if errcode != 0 or not media_id:
|
||||
logger.warning("企微上传文件失败 errcode=%s", errcode)
|
||||
logger.warning("企微上传素材失败 type=%s errcode=%s", kind, errcode)
|
||||
return "", WeComSendResult(
|
||||
ok=False, errcode=errcode, errmsg=str(data.get("errmsg") or "upload_fail"), raw=data
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user