ForcePilot/backend/package/yuxi/channels/plugins/wechat_ilink/entry.py
Kris 2a2385bacc refactor(wechat-ilink): 重构微信iLink插件代码,统一常量与缓存键格式
本次重构对微信iLink渠道插件进行了全面整理:
1.  新增共享常量模块`_constants.py`,集中管理所有跨模块共享配置与标识,对齐manifest单真相源
2.  统一缓存键格式为`wechat_ilink:{account_id}:{key}`,修复白名单存储键顺序错误
3.  重构登录适配器,移除不必要的account_id参数,简化接口调用
4.  重构生命周期相关代码,新增缓存清理逻辑,支持按账户清理孤儿缓存
5.  移除冗余重复定义的常量与配置默认值,统一从常量模块导入
6.  更新manifest配置,补充传输模式与能力要求声明
7.  优化出站适配器,新增续传支持与分片发送逻辑
2026-07-08 22:56:45 +08:00

158 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""微信 iLinkClawBot渠道插件入口。
实现 ``CHANNEL_ENTRY`` 契约,注册 11 个适配器与生命周期钩子,返回
``PluginManifest``。由宿主在 loaded 阶段通过 ``importlib`` 导入并调用。
调用顺序(严格):
1. ``getXxxPort`` 获取被驱动端口实例(宿主已从 manifest.accessible_ports
加载权限,无需运行时 declareXxx
2. 实例化 ``WeChatILinkLifecycleHandler`` 与 ``ILinkClient``。
3. 实例化并注册 11 个适配器puller / inbound / outbound / session /
status / login / lifecycle / probeable / doctor / wizard / whitelist
4. ``registerLifecycleHandler`` 注册生命周期钩子(鸭子类型调用)。
5. 返回 ``PluginManifest``。
F-03 单真相源:本入口仅承接 discover 阶段解析的 ``ChannelManifest``
不再重复构造声明性字段capabilities / config_schema / accessible_ports /
injectable_pipelines / resource_quota / env_vars / credential_strategy 等),
所有声明性字段以 ``manifest.json`` 为唯一真相源。本函数仅负责适配器实例化、
client 实例化、LifecycleHandler 构造与 ``registerAdapter`` 调用。
适配器 DI 说明:
- ``puller`` / ``outbound`` 适配器接收 ``(client, config_port, logger_port)``
适配器直接持有 ConfigPort 读取渠道级配置(对齐 wechat_woc 模式)。
- 4 个适配器inbound / login / doctor / wizard接收
``(client, logger_port)``。
- ``lifecycle`` / ``whitelist`` 适配器接收 ``(cache_port, logger_port)``
仅做账户级缓存清理与白名单数据存储,不调用渠道侧 API无需 ILinkClient
(对齐 wechat_woc 模式)。
- ``probeable`` 适配器接收 ``(client, persistence_port, logger_port)``
需动态发现 account_id 调用 getconfig 探活。
- ``session`` / ``status`` 适配器无状态INV-5无 ``__init__`` 参数,
仅做协议转换,所有数据从 raw_event.payload 提取。
长轮询传输管理iLink 通过 ``PullerAdapter`` 长轮询 ``getupdates`` 拉取
消息,``PullerWorker`` 由传输引擎通过 ``ChannelAccountOnline`` /
``ChannelAccountOffline`` 领域事件触发启停,``LifecycleAdapter`` 与
``LifecycleHandler`` 不自管理轮询任务。
依赖方向:仅 import ``yuxi.channels.contract.*`` + 标准库 + 同插件内部模块,
不污染框架层。
"""
from __future__ import annotations
from yuxi.channels.contract.plugin.entry import PluginHost
from yuxi.channels.contract.plugin.manifest import (
ChannelManifest,
PluginManifest,
)
from .adapters.doctor_adapter import WeChatILinkDoctorAdapter
from .adapters.inbound_adapter import WeChatILinkInboundAdapter
from .adapters.lifecycle_adapter import WeChatILinkLifecycleAdapter
from .adapters.login_adapter import WeChatILinkLoginAdapter
from .adapters.outbound_adapter import WeChatILinkOutboundAdapter
from .adapters.probeable_adapter import WeChatILinkProbeableAdapter
from .adapters.puller_adapter import WeChatILinkPullerAdapter
from .adapters.session_adapter import WeChatILinkSessionAdapter
from .adapters.status_adapter import WeChatILinkStatusAdapter
from .adapters.whitelist_adapter import WeChatILinkWhitelistAdapter
from .adapters.wizard_adapter import WeChatILinkWizardAdapter
from .ilink_client import ILinkClient
from .lifecycle import WeChatILinkLifecycleHandler
# 已注册适配器类型列表(与 registerAdapter 调用顺序一致)。
# 此处为运行时适配器清单,非声明性字段,需与下方 registerAdapter 调用保持一致。
_ADAPTER_TYPES: tuple[str, ...] = (
"puller",
"inbound",
"outbound",
"session",
"status",
"login",
"lifecycle",
"probeable",
"doctor",
"wizard",
"whitelist",
)
def channel_entry(host: PluginHost, manifest: ChannelManifest) -> PluginManifest:
"""微信 iLink 渠道插件入口。
由宿主在 loaded 阶段调用,完成适配器注册、生命周期钩子注册,
返回 ``PluginManifest``。
能力边界accessible_ports / injectable_pipelines / resource_quota /
config_schema / env_vars / credential_strategy 等)由 discover 阶段
解析的 ``manifest`` 静态字段承载,宿主在加载期通过
``PluginCapabilityChecker.check`` 校验,运行时通过
``PluginHostImpl._checkPortAccess`` 从 manifest 读取并强制约束。本函数
不重复构造声明性字段F-03 单真相源)。
参数:
host: 插件宿主,提供端口获取与扩展点注册 API。
manifest: 渠道清单,由 discover 阶段从 ``manifest.json`` 解析得到,
承载所有声明性字段。本函数复用其 ``config_schema`` 注入
``LifecycleHandler``,并直接作为返回 ``PluginManifest.manifest``。
"""
# 1. 获取端口实例(宿主已从 manifest.accessible_ports 加载权限)
# ILinkClient 仅依赖 ConfigPort/CachePort/LoggerPort凭证由
# CredentialService 通过 ConfigPort→CachePort 管理);
# PersistencePort 供 ProbeableAdapter 动态发现 account_id。
config_port = host.getConfigPort()
logger_port = host.getLoggerPort()
cache_port = host.getCachePort()
persistence_port = host.getPersistencePort()
# 2. 实例化 ILinkClient 与 LifecycleHandler
# 依赖关系为单向handler 在 onInit 调 client.attach_http_client 注入连接池,
# client 不引用 handler。先创建 client再创建 handler 并通过构造器注入。
# config_schema / max_connections 取自 manifestF-03 单真相源)。
client = ILinkClient(config_port, cache_port, logger_port)
handler = WeChatILinkLifecycleHandler(
config_port,
logger_port,
cache_port,
manifest.config_schema,
client,
max_connections=(manifest.resource_quota.max_connections if manifest.resource_quota is not None else 10),
)
# 3. 实例化并注册 11 个适配器
# puller / outbound 接收 (client, config_port, logger_port)
# 适配器直接持有 ConfigPort 读取渠道级配置(对齐 wechat_woc 模式)。
# inbound / login / doctor / wizard 接收 (client, logger_port)
# lifecycle / whitelist 接收 (cache_port, logger_port)(账户级缓存清理,
# 不调用渠道侧 API对齐 wechat_woc 模式);
# probeable 接收 (client, persistence_port, logger_port)
# session / status 无状态。
host.registerAdapter("puller", WeChatILinkPullerAdapter(client, config_port, logger_port))
host.registerAdapter("inbound", WeChatILinkInboundAdapter(client, logger_port))
host.registerAdapter("outbound", WeChatILinkOutboundAdapter(client, config_port, logger_port))
host.registerAdapter("session", WeChatILinkSessionAdapter())
host.registerAdapter("status", WeChatILinkStatusAdapter())
host.registerAdapter("login", WeChatILinkLoginAdapter(client, logger_port))
host.registerAdapter("lifecycle", WeChatILinkLifecycleAdapter(cache_port, logger_port))
host.registerAdapter("probeable", WeChatILinkProbeableAdapter(client, persistence_port, logger_port))
host.registerAdapter("doctor", WeChatILinkDoctorAdapter(client, logger_port))
host.registerAdapter("wizard", WeChatILinkWizardAdapter(client, logger_port))
host.registerAdapter("whitelist", WeChatILinkWhitelistAdapter(cache_port, logger_port))
# 4. 注册生命周期钩子
# PluginHost Protocol 未声明 registerLifecycleHandler但 PluginHostImpl
# 已实现,运行时通过鸭子类型调用。
host.registerLifecycleHandler(handler)
# 5. 返回 PluginManifestmanifest 直接复用入参adapters 为运行时清单)
return PluginManifest(
manifest=manifest,
adapters=_ADAPTER_TYPES,
)
CHANNEL_ENTRY = channel_entry