新增 Webex、微信 iLink、微信小程序三个渠道扩展。 Webex 渠道扩展功能模块: - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - webhook: Webhook 事件处理 - outbound: 外发消息管理 - streaming: 流式消息处理 - pairing: 用户配对与绑定 - security: 安全校验 - dedupe: 消息去重 - monitor: 渠道状态监控 - status: 会话状态管理 - media: 媒体资源处理 微信 iLink 渠道扩展功能模块: - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - outbound: 外发消息管理 - streaming: 流式消息处理 - pairing: 用户配对与绑定 - security: 安全校验 - dedupe: 消息去重 - monitor: 渠道状态监控 - status: 会话状态管理 - context_store: 上下文存储 - aes_ecb: AES-ECB 加解密 - media: 媒体资源处理 - typing: 输入状态 微信小程序渠道扩展功能模块: - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - webhook: Webhook 事件处理 - outbound: 外发消息管理 - streaming: 流式消息处理 - pairing: 用户配对与绑定 - security: 安全校验 - crypto: 加解密处理 - dedupe: 消息去重 - message: 消息处理 - passive_reply: 被动回复 - media: 媒体资源处理 - status: 会话状态管理
130 lines
5.4 KiB
Python
130 lines
5.4 KiB
Python
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from yuxi.channel.extensions.wechat_ilink.types import ILinkAccount
|
||
|
||
|
||
def resolve_account(config: dict[str, Any], account_id: str | None = None) -> ILinkAccount | None:
|
||
accounts: list[dict[str, Any]] = config.get("accounts", [])
|
||
if not accounts:
|
||
return None
|
||
|
||
if account_id:
|
||
for acct in accounts:
|
||
if acct.get("account_id") == account_id:
|
||
return _parse_account(acct)
|
||
else:
|
||
return _parse_account(accounts[0])
|
||
|
||
return None
|
||
|
||
|
||
def list_accounts(config: dict[str, Any]) -> list[ILinkAccount]:
|
||
accounts: list[dict[str, Any]] = config.get("accounts", [])
|
||
return [_parse_account(acct) for acct in accounts]
|
||
|
||
|
||
def _parse_account(data: dict[str, Any]) -> ILinkAccount:
|
||
return ILinkAccount(
|
||
account_id=data.get("account_id", "default"),
|
||
bot_token=data.get("bot_token", ""),
|
||
refresh_token=data.get("refresh_token", ""),
|
||
bot_user_id=data.get("bot_user_id", ""),
|
||
bot_nickname=data.get("bot_nickname", ""),
|
||
token_expires_at=data.get("token_expires_at", 0.0),
|
||
dm_policy=data.get("dm_policy", "open"),
|
||
group_policy=data.get("group_policy", "open"),
|
||
allow_from=data.get("allow_from", []),
|
||
enabled=data.get("enabled", True),
|
||
proxy=data.get("proxy"),
|
||
poll_timeout=data.get("poll_timeout", 25),
|
||
poll_interval=data.get("poll_interval", 0.25),
|
||
max_retries=data.get("max_retries", 100),
|
||
ilink_bot_id=data.get("ilink_bot_id", ""),
|
||
ilink_user_id=data.get("ilink_user_id", ""),
|
||
base_url=data.get("base_url", "https://ilinkai.weixin.qq.com"),
|
||
)
|
||
|
||
|
||
def serialize_account(account: ILinkAccount) -> dict[str, Any]:
|
||
return {
|
||
"account_id": account.account_id,
|
||
"bot_token": account.bot_token,
|
||
"refresh_token": account.refresh_token,
|
||
"bot_user_id": account.bot_user_id,
|
||
"bot_nickname": account.bot_nickname,
|
||
"token_expires_at": account.token_expires_at,
|
||
"dm_policy": account.dm_policy,
|
||
"group_policy": account.group_policy,
|
||
"allow_from": account.allow_from,
|
||
"enabled": account.enabled,
|
||
"proxy": account.proxy,
|
||
"poll_timeout": account.poll_timeout,
|
||
"poll_interval": account.poll_interval,
|
||
"max_retries": account.max_retries,
|
||
"ilink_bot_id": account.ilink_bot_id,
|
||
"ilink_user_id": account.ilink_user_id,
|
||
"base_url": account.base_url,
|
||
}
|
||
|
||
|
||
def config_schema() -> dict:
|
||
return {
|
||
"type": "object",
|
||
"title": "微信个人号 (iLink) 渠道配置",
|
||
"properties": {
|
||
"enabled": {"type": "boolean", "default": True},
|
||
"dm_policy": {
|
||
"type": "string",
|
||
"enum": ["open", "allowlist", "pairing", "disabled"],
|
||
"default": "open",
|
||
"description": "私聊策略:open=无限制, allowlist=白名单, pairing=配对验证, disabled=禁用",
|
||
},
|
||
"group_policy": {
|
||
"type": "string",
|
||
"enum": ["open", "allowlist", "disabled"],
|
||
"default": "open",
|
||
"description": "群聊策略",
|
||
},
|
||
"allow_from": {
|
||
"type": "array",
|
||
"items": {"type": "string"},
|
||
"description": "白名单用户/群组 ID 列表",
|
||
},
|
||
"poll_timeout": {"type": "integer", "default": 25, "description": "长轮询超时(秒)"},
|
||
"poll_interval": {"type": "number", "default": 0.25, "description": "轮询间隔(秒)"},
|
||
"max_retries": {"type": "integer", "default": 100, "description": "最大重试次数"},
|
||
"proxy": {"type": "string", "description": "HTTP 代理地址"},
|
||
"base_url": {
|
||
"type": "string",
|
||
"default": "https://ilinkai.weixin.qq.com",
|
||
"description": "iLink API 基础地址",
|
||
},
|
||
"accounts": {
|
||
"type": "object",
|
||
"additionalProperties": {
|
||
"type": "object",
|
||
"properties": {
|
||
"bot_token": {"type": "string", "description": "Bot Token"},
|
||
"refresh_token": {"type": "string"},
|
||
"bot_user_id": {"type": "string"},
|
||
"bot_nickname": {"type": "string"},
|
||
"token_expires_at": {"type": "number"},
|
||
"dm_policy": {"type": "string", "enum": ["open", "allowlist", "pairing", "disabled"]},
|
||
"group_policy": {"type": "string", "enum": ["open", "allowlist", "disabled"]},
|
||
"allow_from": {"type": "array", "items": {"type": "string"}},
|
||
"enabled": {"type": "boolean", "default": True},
|
||
"proxy": {"type": "string"},
|
||
"poll_timeout": {"type": "integer", "default": 25},
|
||
"poll_interval": {"type": "number", "default": 0.25},
|
||
"max_retries": {"type": "integer", "default": 100},
|
||
"ilink_bot_id": {"type": "string"},
|
||
"ilink_user_id": {"type": "string"},
|
||
"base_url": {"type": "string", "default": "https://ilinkai.weixin.qq.com"},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|