新增元宝(Yuanbao)渠道的完整适配器实现,包含以下核心模块: - 基础适配器与导出入口 - 协议编解码与WebSocket帧处理 - 会话管理与路由逻辑 - 事件队列与出站消息队列 - 消息格式转换与发送重试 - 安全审计与权限校验 - 配置映射与账户管理 - 视觉分析与工具函数 - 文档生成与设置向导
105 lines
3.0 KiB
Python
105 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
from yuxi.channels.models import ChannelMessage
|
|
|
|
|
|
def _resolve_dm_policy(config: dict) -> str:
|
|
if "dm_policy" in config:
|
|
return config["dm_policy"]
|
|
dm = config.get("dm", {})
|
|
if isinstance(dm, dict) and "policy" in dm:
|
|
return dm["policy"]
|
|
return "pairing"
|
|
|
|
|
|
def _resolve_dm_allow_from(config: dict) -> list[str]:
|
|
if "allow_from" in config:
|
|
return config["allow_from"]
|
|
dm = config.get("dm", {})
|
|
if isinstance(dm, dict) and "allowFrom" in dm:
|
|
return dm["allowFrom"]
|
|
return []
|
|
|
|
|
|
async def check_dm_policy(user_id: str, config: dict) -> bool:
|
|
dm_policy = _resolve_dm_policy(config)
|
|
|
|
match dm_policy:
|
|
case "open":
|
|
return True
|
|
case "disabled":
|
|
return False
|
|
case "pairing":
|
|
return _is_user_paired(user_id, config)
|
|
case "allowlist":
|
|
allow_from = _resolve_dm_allow_from(config)
|
|
return "*" in allow_from or user_id in allow_from
|
|
case _:
|
|
return False
|
|
|
|
|
|
async def check_group_policy(group_open_id: str, user_id: str, config: dict) -> bool:
|
|
groups_config = config.get("groups", {})
|
|
group_cfg = groups_config.get(group_open_id, {})
|
|
|
|
if isinstance(group_cfg, dict) and "enabled" in group_cfg and not group_cfg["enabled"]:
|
|
return False
|
|
|
|
group_policy = config.get("group_policy", "allowlist")
|
|
|
|
match group_policy:
|
|
case "open":
|
|
return True
|
|
case "disabled":
|
|
return False
|
|
case "allowlist":
|
|
group_allow = config.get("group_allow_from", [])
|
|
if "*" in group_allow or user_id in group_allow:
|
|
return True
|
|
per_group_allow = group_cfg.get("allow_from", [])
|
|
return "*" in per_group_allow or user_id in per_group_allow
|
|
case _:
|
|
return False
|
|
|
|
|
|
async def check_mention_required(
|
|
group_open_id: str,
|
|
msg: ChannelMessage,
|
|
config: dict,
|
|
bot_names: list[str] | None = None,
|
|
bot_message_ids: set[str] | None = None,
|
|
) -> bool:
|
|
groups_config = config.get("groups", {})
|
|
group_cfg = groups_config.get(group_open_id, {})
|
|
|
|
require_mention = group_cfg.get("require_mention")
|
|
if require_mention is None:
|
|
if "group_require_mention" in config:
|
|
require_mention = config["group_require_mention"]
|
|
elif "requireMention" in config:
|
|
require_mention = config["requireMention"]
|
|
else:
|
|
require_mention = True
|
|
|
|
if not require_mention:
|
|
return True
|
|
|
|
if msg.mentions and msg.mentions.is_bot_mentioned:
|
|
return True
|
|
|
|
content = msg.content or ""
|
|
for name in bot_names or []:
|
|
if f"@{name}" in content:
|
|
return True
|
|
|
|
reply_to_msg_id = (msg.metadata or {}).get("reply_to_msg_id")
|
|
if reply_to_msg_id and bot_message_ids and reply_to_msg_id in bot_message_ids:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def _is_user_paired(user_id: str, config: dict) -> bool:
|
|
paired_users = config.get("paired_users", [])
|
|
return user_id in paired_users
|