新增元宝(Yuanbao)渠道的完整适配器实现,包含以下核心模块: - 基础适配器与导出入口 - 协议编解码与WebSocket帧处理 - 会话管理与路由逻辑 - 事件队列与出站消息队列 - 消息格式转换与发送重试 - 安全审计与权限校验 - 配置映射与账户管理 - 视觉分析与工具函数 - 文档生成与设置向导
69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
from yuxi.channels.models import ChannelResponse, MessageType
|
|
|
|
|
|
def format_outbound(response: ChannelResponse) -> dict:
|
|
chat_id = response.identity.channel_chat_id
|
|
if not chat_id:
|
|
raise ValueError(
|
|
"channel_chat_id is empty, cannot format outbound message. "
|
|
"Ensure the ChannelIdentity has a valid channel_chat_id."
|
|
)
|
|
metadata = response.metadata or {}
|
|
|
|
payload: dict = {
|
|
"msg_type": _map_message_type(response.message_type, response.content),
|
|
}
|
|
|
|
if metadata.get("group_open_id"):
|
|
payload["group_open_id"] = metadata["group_open_id"]
|
|
elif metadata.get("channel_id"):
|
|
payload["channel_id"] = metadata["channel_id"]
|
|
else:
|
|
payload["open_id"] = chat_id
|
|
|
|
if response.reply_to_message_id:
|
|
payload["reply_to_msg_id"] = response.reply_to_message_id
|
|
|
|
if response.message_type == MessageType.IMAGE or response.message_type == MessageType.STICKER:
|
|
if response.attachments:
|
|
payload["media_url"] = response.attachments[0].url
|
|
payload["content"] = response.content or ""
|
|
else:
|
|
payload["content"] = response.content
|
|
elif response.message_type == MessageType.FILE:
|
|
if response.attachments:
|
|
payload["media_url"] = response.attachments[0].url
|
|
payload["filename"] = response.attachments[0].filename or "file"
|
|
payload["content"] = response.content or ""
|
|
else:
|
|
payload["content"] = response.content
|
|
|
|
if metadata.get("extra"):
|
|
payload["extra"] = metadata["extra"]
|
|
|
|
buttons = metadata.get("buttons")
|
|
if buttons and isinstance(buttons, list):
|
|
payload["buttons"] = buttons
|
|
|
|
card = metadata.get("card")
|
|
if card and isinstance(card, dict):
|
|
payload["card"] = card
|
|
|
|
return payload
|
|
|
|
|
|
def _map_message_type(message_type: MessageType, content: str) -> str:
|
|
_type_map = {
|
|
MessageType.TEXT: "text",
|
|
MessageType.IMAGE: "image",
|
|
MessageType.FILE: "file",
|
|
MessageType.AUDIO: "audio",
|
|
MessageType.VIDEO: "video",
|
|
MessageType.STICKER: "sticker",
|
|
MessageType.CARD: "card",
|
|
MessageType.COMMAND: "text",
|
|
}
|
|
return _type_map.get(message_type, "text")
|