ForcePilot/backend/package/yuxi/channel/extensions/wecom/webhook_bot.py
Kris 7215418610 feat(channel): 添加企业微信、微博、WhatsApp 和 Workplace 渠道扩展
新增企业微信、微博、WhatsApp、Workplace 四个渠道扩展。

企业微信渠道扩展主要模块:config, gateway, webhook, webhook_bot, outbound, streaming, pairing, security, crypto, dedupe, persistent_dedupe, card, directory, events, externalcontact, media, mentions, menu, message, oauth, status

微博渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, passive_reply, broadcast, message, menu, media, subscription, template, status

WhatsApp 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, actions, monitor, status

Workplace 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, actions, challenge, groups, media, mentions, menu, monitor, persona, quick_reply, signature, subscriptions, template, threading, users, status
2026-05-21 12:01:56 +08:00

96 lines
3.0 KiB
Python

import logging
import httpx
logger = logging.getLogger(__name__)
WEBHOOK_SEND_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send"
async def send_webhook_text(
key: str,
content: str,
mentioned_list: list[str] | None = None,
mentioned_mobile_list: list[str] | None = None,
) -> bool:
url = f"{WEBHOOK_SEND_URL}?key={key}"
text_payload: dict = {"content": content}
if mentioned_list:
text_payload["mentioned_list"] = mentioned_list
if mentioned_mobile_list:
text_payload["mentioned_mobile_list"] = mentioned_mobile_list
payload: dict = {
"msgtype": "text",
"text": text_payload,
}
async with httpx.AsyncClient(timeout=10.0) as client:
try:
resp = await client.post(url, json=payload)
data = resp.json()
ok = data.get("errcode") == 0
if not ok:
logger.warning("WeCom webhook text send failed: %s", data)
return ok
except Exception:
logger.exception("WeCom webhook text send error")
return False
async def send_webhook_markdown(content: str, key: str) -> bool:
url = f"{WEBHOOK_SEND_URL}?key={key}"
payload = {
"msgtype": "markdown",
"markdown": {"content": content},
}
async with httpx.AsyncClient(timeout=10.0) as client:
try:
resp = await client.post(url, json=payload)
data = resp.json()
ok = data.get("errcode") == 0
if not ok:
logger.warning("WeCom webhook markdown send failed: %s", data)
return ok
except Exception:
logger.exception("WeCom webhook markdown send error")
return False
async def send_webhook_image(key: str, base64_content: str, md5_hash: str) -> bool:
url = f"{WEBHOOK_SEND_URL}?key={key}"
payload = {
"msgtype": "image",
"image": {"base64": base64_content, "md5": md5_hash},
}
async with httpx.AsyncClient(timeout=10.0) as client:
try:
resp = await client.post(url, json=payload)
data = resp.json()
ok = data.get("errcode") == 0
if not ok:
logger.warning("WeCom webhook image send failed: %s", data)
return ok
except Exception:
logger.exception("WeCom webhook image send error")
return False
async def send_webhook_news(key: str, articles: list[dict]) -> bool:
url = f"{WEBHOOK_SEND_URL}?key={key}"
payload = {
"msgtype": "news",
"news": {"articles": articles[:8]},
}
async with httpx.AsyncClient(timeout=10.0) as client:
try:
resp = await client.post(url, json=payload)
data = resp.json()
ok = data.get("errcode") == 0
if not ok:
logger.warning("WeCom webhook news send failed: %s", data)
return ok
except Exception:
logger.exception("WeCom webhook news send error")
return False