refactor(architecture): 修复模块依赖违规并强化架构守护

- 字幕编排上移 DownloadChain.download_site_subtitles,SubtitleModule 仅保留站点链接解析
- TransferChain.recommend_name 上移 TV episodes_info 获取,filemanager 模块不再导入 TmdbChain
- endpoint 穿透修复:WXBizMsgCrypt3 迁至 adapters/external/wechat_crypt.py;
  music/tmdb 缓存管理、listenbrainz 常量、TMDbException、WechatClawBot 辅助统一经 chain 包装
- RuleParser 与 builtin_rules 合并为 application/filter_rules.py;
  fsproxy/fsworker 迁至 adapters/system/
- chain/__init__.py 删除 qbittorrentapi/transmission_rpc 导入,消除后端协议类型泄漏
- 架构守护测试新增三项检查:模块间隔离、入口层穿透、下载器 SDK 泄漏
- 文档同步:05-architecture.md 记录 DB/Oper 聚合例外与迁移文件位置,AGENTS.md 更新所有权表
This commit is contained in:
jxxghp
2026-08-16 04:59:17 +08:00
parent f7e39a47c6
commit 02f0dd0b9a
37 changed files with 630 additions and 450 deletions
+6 -78
View File
@@ -4,84 +4,12 @@ from fastapi import Depends
from app import schemas
from app.api.response import ResponseAPIRouter
from app.runtime.extensions.module_manager import ModuleManager
from app.chain.message import MessageChain
from app.db.models import User
from app.api.deps import get_current_active_superuser
from app.modules.wechatclawbot.wechatclawbot import WechatClawBot
router = ResponseAPIRouter()
def _build_wechatclawbot_temp_client(
source: Optional[str] = None,
WECHATCLAWBOT_BASE_URL: Optional[str] = None,
WECHATCLAWBOT_DEFAULT_TARGET: Optional[str] = None,
WECHATCLAWBOT_ADMINS: Optional[str] = None,
WECHATCLAWBOT_POLL_TIMEOUT: Optional[int] = None,
):
"""基于当前表单配置创建一个临时客户端,用于未保存时的扫码状态预览。"""
source_name = str(source or "").strip()
if not source_name:
return None
return WechatClawBot(
name=source_name,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
WECHATCLAWBOT_DEFAULT_TARGET=WECHATCLAWBOT_DEFAULT_TARGET,
WECHATCLAWBOT_ADMINS=WECHATCLAWBOT_ADMINS,
WECHATCLAWBOT_POLL_TIMEOUT=WECHATCLAWBOT_POLL_TIMEOUT,
auto_start_polling=False,
)
def _get_wechatclawbot_client(
source: Optional[str] = None,
fallback_source: Optional[str] = None,
WECHATCLAWBOT_BASE_URL: Optional[str] = None,
WECHATCLAWBOT_DEFAULT_TARGET: Optional[str] = None,
WECHATCLAWBOT_ADMINS: Optional[str] = None,
WECHATCLAWBOT_POLL_TIMEOUT: Optional[int] = None,
allow_temporary: bool = False,
):
"""获取已加载的微信 ClawBot 客户端,必要时退回到临时客户端。"""
module = ModuleManager().get_running_module("WechatClawBotModule")
source_name = str(source or "").strip() or None
fallback_name = str(fallback_source or "").strip() or None
if module:
candidate_names = []
for candidate in (fallback_name, source_name):
if candidate and candidate not in candidate_names:
candidate_names.append(candidate)
if candidate_names:
for candidate in candidate_names:
config = module.get_config(candidate)
if not config:
continue
client = module.get_instance(config.name)
if client:
return client, None
else:
client = module.get_instance()
if client:
return client, None
if allow_temporary:
temp_client = _build_wechatclawbot_temp_client(
source=source_name or fallback_name,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
WECHATCLAWBOT_DEFAULT_TARGET=WECHATCLAWBOT_DEFAULT_TARGET,
WECHATCLAWBOT_ADMINS=WECHATCLAWBOT_ADMINS,
WECHATCLAWBOT_POLL_TIMEOUT=WECHATCLAWBOT_POLL_TIMEOUT,
)
if temp_client:
return temp_client, None
if source_name:
return None, f"未找到名为 {source_name} 的微信 ClawBot 通知配置"
return None, "微信 ClawBot 通知未启用或配置尚未保存,请先保存并启用当前渠道"
@router.get(
"/wechatclawbot/status",
summary="查询微信 ClawBot 登录状态",
@@ -99,7 +27,7 @@ def wechatclawbot_status(
_: User = Depends(get_current_active_superuser),
):
"""查询微信 ClawBot 登录状态和二维码。"""
client, errmsg = _get_wechatclawbot_client(
client, errmsg = MessageChain.get_wechatclawbot_client(
source=source,
fallback_source=fallback_source,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
@@ -134,7 +62,7 @@ def refresh_wechatclawbot_qrcode(
_: User = Depends(get_current_active_superuser),
):
"""刷新微信 ClawBot 二维码。"""
client, errmsg = _get_wechatclawbot_client(
client, errmsg = MessageChain.get_wechatclawbot_client(
source=source,
fallback_source=fallback_source,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
@@ -168,7 +96,7 @@ def logout_wechatclawbot(
_: User = Depends(get_current_active_superuser),
):
"""退出微信 ClawBot 登录。"""
client, errmsg = _get_wechatclawbot_client(
client, errmsg = MessageChain.get_wechatclawbot_client(
source=source,
fallback_source=fallback_source,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
@@ -202,7 +130,7 @@ def test_wechatclawbot(
_: User = Depends(get_current_active_superuser),
):
"""测试微信 ClawBot 当前登录态是否可用。"""
client, errmsg = _get_wechatclawbot_client(
client, errmsg = MessageChain.get_wechatclawbot_client(
source=source,
fallback_source=fallback_source,
WECHATCLAWBOT_BASE_URL=WECHATCLAWBOT_BASE_URL,
@@ -230,7 +158,7 @@ def migrate_wechatclawbot_cache(
_: User = Depends(get_current_active_superuser),
):
"""在通知名称变更时迁移对应的微信 ClawBot 登录缓存。"""
success, message = WechatClawBot.migrate_cached_state(
success, message = MessageChain.migrate_wechatclawbot_cache(
old_name=old_source,
new_name=new_source,
cleanup_old=cleanup_old,