新增企业微信、微博、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
130 lines
3.9 KiB
Python
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
|