ForcePilot/backend/package/yuxi/channel/extensions/weibo/message.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

130 lines
3.9 KiB
Python

import logging
from datetime import datetime
from yuxi.channel.extensions.weibo.types import InboundWeiboMessage
logger = logging.getLogger(__name__)
def parse_weibo_message(body: dict, app_key: str) -> InboundWeiboMessage:
broad_type = body.get("type", "message")
if broad_type == "event":
msg_type = "event"
sub_type = body.get("sub_type", "")
event_key = body.get("event_key", "")
else:
msg_type = body.get("sub_type", "text")
sub_type = ""
event_key = ""
sender_id = str(body.get("sender_id", ""))
receiver_id = str(body.get("receiver_id", ""))
text_content = body.get("text", "")
msg_id = str(body.get("id", ""))
create_time = _parse_created_at(body.get("created_at", ""))
if not create_time:
from datetime import datetime, timezone
create_time = int(datetime.now(timezone.utc).timestamp())
pic_url = ""
media_id = ""
longitude = ""
latitude = ""
attachment = body.get("attachment", [])
if attachment and isinstance(attachment, list):
att = attachment[0] if attachment else {}
if att.get("type") == "image":
pic_url = att.get("url", "")
media_id = att.get("tovfid", "")
elif att.get("type") == "voice":
media_id = att.get("tovfid", "")
elif att.get("type") == "position":
longitude = att.get("longitude", "")
latitude = att.get("latitude", "")
return InboundWeiboMessage(
msg_id=msg_id,
msg_type=msg_type,
sender_id=sender_id,
receiver_id=receiver_id,
sub_type=sub_type,
event_key=event_key,
create_time=create_time,
content=text_content,
pic_url=pic_url,
media_id=media_id,
longitude=longitude,
latitude=latitude,
raw_json=body,
)
def extract_content(raw_msg: InboundWeiboMessage) -> str:
msg_type = raw_msg.msg_type
if msg_type == "text":
return raw_msg.content or ""
if msg_type == "image":
return "[图片消息]"
if msg_type == "voice":
return "[语音消息]"
if msg_type == "position":
lon = raw_msg.longitude or "未知"
lat = raw_msg.latitude or "未知"
return f"[位置消息] 经度:{lon} 纬度:{lat}"
if msg_type == "event":
sub = raw_msg.sub_type
if sub == "follow":
return "[关注事件]"
if sub == "unfollow":
return "[取关事件]"
if sub == "subscribe":
return "[订阅事件]"
if sub == "unsubscribe":
return "[取消订阅事件]"
if sub == "click":
key = raw_msg.event_key or "未指定"
return f"[菜单点击: {key}]"
if sub == "scan":
key = raw_msg.event_key or "未指定"
ticket = raw_msg.raw_json.get("ticket", "")
return f"[扫码事件] key={key}" + (f" ticket={ticket}" if ticket else "")
if sub == "scan_follow":
key = raw_msg.event_key or "未指定"
return f"[扫码关注] key={key}"
if sub == "masssend":
status = raw_msg.raw_json.get("status", "")
msg_id = raw_msg.raw_json.get("msg_id", "")
return f"[群发结果] status={status} msg_id={msg_id}"
return f"[事件: {sub}]"
if msg_type == "mention":
mention_text = raw_msg.raw_json.get("text", "")
return f"[@消息] {mention_text}"
return raw_msg.content or ""
def _parse_created_at(created_at: str) -> int:
if not created_at:
return 0
try:
dt = datetime.strptime(created_at, "%a %b %d %H:%M:%S %z %Y")
return int(dt.timestamp())
except ValueError:
pass
try:
dt = datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%S%z")
return int(dt.timestamp())
except ValueError:
logger.warning("Failed to parse created_at: %s", created_at)
return 0