mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 15:09:46 +08:00
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:
@@ -19,7 +19,7 @@ from app.db.oper.systemconfig import SystemConfigOper
|
||||
from app.api.deps import get_current_active_superuser
|
||||
from app.runtime.extensions.service_registry import ServiceConfigHelper
|
||||
from app.runtime.log import logger
|
||||
from app.modules.wechat.WXBizMsgCrypt3 import WXBizMsgCrypt
|
||||
from app.adapters.external.wechat_crypt import WXBizMsgCrypt
|
||||
from app.schemas.types import MessageChannel, SystemConfigKey
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
|
||||
@@ -11,12 +11,12 @@ from app.domain.context import MusicAlbumInfo, MusicArtistInfo, MusicInfo
|
||||
from app.application.security.access import verify_token
|
||||
from app.db.models.user import User
|
||||
from app.api.deps import get_current_active_superuser_async
|
||||
from app.modules.listenbrainz import (
|
||||
from app.chain.listenbrainz import (
|
||||
LISTENBRAINZ_CHART_RANGES,
|
||||
LISTENBRAINZ_FRESH_MAX_DAYS,
|
||||
LISTENBRAINZ_FRESH_SORTS,
|
||||
)
|
||||
from app.modules.musicbrainz.music_cache import MusicBrainzCache
|
||||
from app.chain.musicbrainz import MusicBrainzChain
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
|
||||
@@ -111,7 +111,7 @@ async def music_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""查询可管理的 MusicBrainz 识别缓存。"""
|
||||
cache_items = MusicBrainzCache().list_items()
|
||||
cache_items = MusicBrainzChain.cache_items()
|
||||
recognized_count = sum(1 for item in cache_items if item["media_id"])
|
||||
return schemas.Response(
|
||||
success=True,
|
||||
@@ -134,7 +134,7 @@ async def delete_music_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""按缓存键删除单条 MusicBrainz 识别缓存。"""
|
||||
deleted_item = MusicBrainzCache().delete(cache_key)
|
||||
deleted_item = MusicBrainzChain.delete_cache(cache_key)
|
||||
if not deleted_item:
|
||||
return schemas.Response(success=False, message="音乐识别缓存不存在")
|
||||
return schemas.Response(success=True, message="音乐识别缓存删除成功")
|
||||
@@ -147,7 +147,7 @@ async def clear_music_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""清空全部 MusicBrainz 识别缓存。"""
|
||||
MusicBrainzCache().clear()
|
||||
MusicBrainzChain.clear_cache()
|
||||
return schemas.Response(success=True, message="音乐识别缓存清理完成")
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -7,7 +7,7 @@ from app.api.response import ResponseAPIRouter
|
||||
from app.chain.recommend import RecommendChain
|
||||
from app.runtime.events import eventmanager
|
||||
from app.application.security.access import verify_token
|
||||
from app.modules.themoviedb.tmdbv3api.exceptions import TMDbException
|
||||
from app.chain.tmdb import TMDbException
|
||||
from app.schemas import RecommendSourceEventData
|
||||
from app.schemas.types import ChainEventType
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ from app.application.security.access import verify_token
|
||||
from app.db.models.user import User
|
||||
from app.db.oper.systemconfig import SystemConfigOper
|
||||
from app.api.deps import get_current_active_superuser_async
|
||||
from app.modules.themoviedb.tmdb_cache import TmdbCache
|
||||
from app.schemas.types import MediaType, SystemConfigKey
|
||||
|
||||
router = ResponseAPIRouter()
|
||||
@@ -25,7 +24,7 @@ async def tmdb_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""查询可管理的 TheMovieDb 识别缓存。"""
|
||||
cache_items = TmdbCache().list_items()
|
||||
cache_items = TmdbChain.cache_items()
|
||||
recognized_count = sum(1 for item in cache_items if item["tmdb_id"])
|
||||
return schemas.Response(
|
||||
success=True,
|
||||
@@ -52,7 +51,7 @@ async def delete_tmdb_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""按缓存键删除单条 TheMovieDb 识别缓存。"""
|
||||
deleted_item = TmdbCache().delete(cache_key)
|
||||
deleted_item = TmdbChain.delete_cache(cache_key)
|
||||
if not deleted_item:
|
||||
return schemas.Response(success=False, message="TheMovieDb 识别缓存不存在")
|
||||
return schemas.Response(success=True, message="TheMovieDb 识别缓存删除成功")
|
||||
@@ -65,7 +64,7 @@ async def clear_tmdb_recognition_cache(
|
||||
_: User = Depends(get_current_active_superuser_async),
|
||||
) -> schemas.Response:
|
||||
"""清空全部 TheMovieDb 识别缓存。"""
|
||||
TmdbCache().clear()
|
||||
TmdbChain.clear_cache()
|
||||
return schemas.Response(success=True, message="TheMovieDb 识别缓存清理完成")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user