refactor: 收口 V3 分层架构与插件兼容边界

This commit is contained in:
jxxghp
2026-08-18 13:22:02 +08:00
parent cca99bd421
commit 8472bcff43
274 changed files with 10730 additions and 6130 deletions
+3 -2
View File
@@ -8,11 +8,11 @@ from pathlib import Path
from typing import Optional, Any, Tuple, List, Set, Union, Dict
from app.application.chain.context import ChainRuntimeContext, get_chain_runtime_context
from app.application.chain.data import get_chain_data_ports
from app.chain._messaging import MessageProcessingMixin, NotificationMixin
from app.chain._recognition import RecognitionMixin
from app.domain.context import Context, MediaInfo, SubtitleInfo, TorrentInfo
from app.domain.meta.metabase import MetaBase
from app.runtime.extensions.module.dispatcher import ModuleInvocationDispatcher
from app.runtime.log import logger
from app.schemas.exception import RateLimitExceededException
from app.schemas.transfer import TransferInfo
@@ -52,7 +52,8 @@ class ChainBase(RecognitionMixin, MessageProcessingMixin, NotificationMixin,
self.pluginmanager = context.plugin_manager
self.filecache = context.file_cache
self.async_filecache = context.async_file_cache
self._module_dispatcher = ModuleInvocationDispatcher(
self.data_ports = context.data_ports or get_chain_data_ports()
self._module_dispatcher = context.module_dispatcher_factory(
module_catalog=self.modulemanager,
plugin_catalog=self.pluginmanager,
plugin_error_handler=self.__handle_plugin_error,
+2 -2
View File
@@ -8,13 +8,13 @@ import copy
from datetime import datetime
from typing import Any, Dict, List, Optional, Union
from app.db.oper.user import UserOper
from app.application.chain.data import UserPortProxy as UserOper
from app.domain.context import Context, MediaInfo, MusicInfo, TorrentInfo
from app.domain.meta.metabase import MetaBase
from app.foundation.identity import normalize_internal_user_id
from app.application.messaging.message import MessageTemplateHelper
from app.runtime.config import settings
from app.runtime.extensions.service_registry import ServiceConfigHelper
from app.runtime.extensions.service_config import ServiceConfigHelper
from app.runtime.log import logger
from app.schemas.message import MessageResponse
from app.schemas.message import Message
+6 -5
View File
@@ -9,9 +9,8 @@ from app.application.subscription.contract import (
from app.chain.download import DownloadChain
from app.chain.media import MediaChain
from app.chain.search import SearchChain
from app.db.models.subscribe import Subscribe
from app.db.oper.subscribe import SubscribeOper
from app.db.oper.systemconfig import SystemConfigOper
from app.application.chain.data import SubscribePortProxy as SubscribeOper
from app.application.configuration import get_configured_system_config
from app.domain.context import Context, MediaInfo, MusicInfo
from app.domain.media import MUSIC_SUBSCRIBABLE_TYPES
from app.domain.meta.metamusic import MetaMusic
@@ -23,6 +22,8 @@ from app.schemas.types import (
SystemConfigKey,
)
Subscribe = Any
def _normalize_music_total_tracks(value: Any) -> Optional[int]:
"""将专辑曲目总数归一为正整数,无效或未知值返回 None。"""
@@ -255,7 +256,7 @@ class MusicSubscribeMixin:
sites = self.get_sub_sites(subscribe)
default_rule_key = SystemConfigKey.BestVersionFilterRuleGroups \
if subscribe.best_version else SystemConfigKey.SubscribeFilterRuleGroups
rule_groups = subscribe.filter_groups or SystemConfigOper().get(default_rule_key) or []
rule_groups = subscribe.filter_groups or get_configured_system_config().get(default_rule_key) or []
torrent_helper = TorrentHelper()
matched: List[Context] = []
for source_context in contexts or []:
@@ -369,7 +370,7 @@ class MusicSubscribeMixin:
sites = self.get_sub_sites(subscribe)
default_rule_key = SystemConfigKey.BestVersionFilterRuleGroups \
if subscribe.best_version else SystemConfigKey.SubscribeFilterRuleGroups
rule_groups = subscribe.filter_groups or SystemConfigOper().get(default_rule_key) or []
rule_groups = subscribe.filter_groups or get_configured_system_config().get(default_rule_key) or []
keywords = [subscribe.keyword] if subscribe.keyword else SearchChain.music_site_keywords(mediainfo)
if not keywords:
keywords = [subscribe.name]
+2 -2
View File
@@ -10,7 +10,7 @@ from typing import Optional
from fastapi.concurrency import run_in_threadpool
from app.adapters.external.server import MoviePilotServerHelper
from app.db.oper.systemconfig import SystemConfigOper
from app.application.configuration import get_configured_system_config
from app.domain.context import MediaInfo, MusicInfo
from app.domain.meta.metabase import MetaBase
from app.domain.meta.metamusic import MetaMusic
@@ -85,7 +85,7 @@ class RecognitionMixin:
def _record_media_recognize_share_hit() -> None:
"""记录一次共享媒体识别成功命中,统计失败不影响识别结果。"""
try:
SystemConfigOper().increment(SystemConfigKey.MediaRecognizeShareCount)
get_configured_system_config().increment(SystemConfigKey.MediaRecognizeShareCount)
except Exception as err:
logger.error(f"记录共享媒体识别命中次数失败:{str(err)}")
+10 -6
View File
@@ -22,11 +22,11 @@ from app.application.transfer import TransferTask, job_lock
from app.chain.media import MediaChain
from app.chain.storage import StorageChain
from app.chain.subscribe import SubscribeChain
from app.db.models.downloadhistory import DownloadFiles, DownloadHistory
from app.db.models.transferhistory import TransferHistory
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.transferhistory import TransferHistoryOper
from app.application.chain.data import (
DownloadHistoryPortProxy as DownloadHistoryOper,
TransferHistoryPortProxy as TransferHistoryOper,
)
from app.application.configuration import get_configured_system_config
from app.domain.context import MediaInfo, MusicInfo
from app.domain.media import normalize_music_type
from app.domain.meta.metabase import MetaBase
@@ -48,6 +48,10 @@ from app.schemas.types import (
SystemConfigKey,
)
DownloadFiles = Any
DownloadHistory = Any
TransferHistory = Any
# 字幕文件常见的语言/默认/强制标记,整理同名字幕时只允许剥离这些字幕专属尾缀。
SUBTITLE_STEM_TAGS = {
"cc",
@@ -725,7 +729,7 @@ class EpisodeFormatMixin:
"""
获取启用的集数定位规则
"""
rule_items = SystemConfigOper().get(SystemConfigKey.EpisodeFormatRuleTable) or []
rule_items = get_configured_system_config().get(SystemConfigKey.EpisodeFormatRuleTable) or []
rules: List[_SchemaEpisodeFormatRule] = []
for item in rule_items:
if not isinstance(item, dict):
+8 -4
View File
@@ -28,9 +28,11 @@ from app.runtime.events import eventmanager, Event
from app.domain.meta.metabase import MetaBase
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfo
from app.db.oper.downloadfailure import DownloadFailureOper
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.oper.mediaserver import MediaServerOper
from app.application.chain.data import (
DownloadFailurePortProxy as DownloadFailureOper,
DownloadHistoryPortProxy as DownloadHistoryOper,
MediaServerPortProxy as MediaServerOper,
)
from app.application.directory import DirectoryHelper, validate_download_save_path
from app.application.download.tasks import DownloadTaskService
from app.runtime.thread import ThreadHelper
@@ -53,7 +55,9 @@ from app.foundation import text as text_tools
from app.adapters.system.host import SystemUtils
if TYPE_CHECKING:
from app.db.models.downloadfailure import DownloadFailure
from typing import Any
DownloadFailure = Any
DOWNLOAD_FAILURE_RESOURCE_TTL_SECONDS = 24 * 60 * 60
+1 -1
View File
@@ -13,7 +13,7 @@ from app.application.messaging.media import (
media_interaction_manager,
)
from app.application.torrent import TorrentHelper
from app.db.oper.user import UserOper
from app.application.chain.data import UserPortProxy as UserOper
from app.domain import episode as episode_rules
from app.domain import title as title_rules
from app.domain.context import Context, MediaInfo
+2 -2
View File
@@ -4,8 +4,8 @@ from typing import Callable, Dict, List, Union, Optional, Generator, Any
from app.chain import ChainBase
from app.runtime.config import global_vars
from app.db.oper.mediaserver import MediaServerOper
from app.runtime.extensions.service_registry import ServiceConfigHelper
from app.application.chain.data import MediaServerPortProxy as MediaServerOper
from app.runtime.extensions.service_config import ServiceConfigHelper
from app.runtime.log import logger
from app.schemas.mediaserver import MediaServerLibrary
from app.schemas.mediaserver import MediaServerItem
+2 -2
View File
@@ -23,7 +23,7 @@ from app.runtime.events import eventmanager, Event
from app.domain.meta.metabase import MetaBase
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfo, MetaInfoPath
from app.db.oper.systemconfig import SystemConfigOper
from app.application.configuration import get_configured_system_config
from app.application.audio import AudioMetadataHelper
from app.runtime.log import logger
from app.schemas.workflow import FileItem
@@ -146,7 +146,7 @@ class ScrapingConfig:
:return: MediaScrapingConfig 实例
"""
user_config = SystemConfigOper().get(SystemConfigKey.ScrapingSwitchs) or {}
user_config = get_configured_system_config().get(SystemConfigKey.ScrapingSwitchs) or {}
return cls(user_config)
@staticmethod
+13 -13
View File
@@ -21,7 +21,7 @@ from app.runtime.events import eventmanager, Event
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfo
from app.domain.context import MusicInfo
from app.db.oper.systemconfig import SystemConfigOper
from app.application.configuration import get_configured_system_config
from app.runtime.progress import ProgressHelper
from app.application.site.sites import SitesHelper # pylint: disable=no-name-in-module
from app.application.search.state import (
@@ -1039,7 +1039,7 @@ class SearchChain(ChainBase):
# 记录过滤前的候选资源数,供前端在全部被过滤时给出友好提示
candidate_count = 0
if rule_groups is None:
rule_groups = SystemConfigOper().get(SystemConfigKey.SearchFilterRuleGroups) or []
rule_groups = get_configured_system_config().get(SystemConfigKey.SearchFilterRuleGroups) or []
async for event in self.__async_search_all_sites_stream(
keyword=title, sites=sites, page=page, mtype=mtype):
result = event.pop("items", []) or []
@@ -1104,7 +1104,7 @@ class SearchChain(ChainBase):
return []
if rule_groups is None:
rule_groups = SystemConfigOper().get(SystemConfigKey.SearchFilterRuleGroups) or []
rule_groups = get_configured_system_config().get(SystemConfigKey.SearchFilterRuleGroups) or []
if not rule_groups:
return torrents
@@ -1311,7 +1311,7 @@ class SearchChain(ChainBase):
# 开始过滤规则过滤
if rule_groups is None:
# 取搜索过滤规则
rule_groups: List[str] = SystemConfigOper().get(SystemConfigKey.SearchFilterRuleGroups)
rule_groups: List[str] = get_configured_system_config().get(SystemConfigKey.SearchFilterRuleGroups)
if rule_groups:
logger.info(f'开始过滤规则/剧集过滤,使用规则组:{rule_groups} ...')
torrents = __do_parallel_filter(torrents)
@@ -1439,7 +1439,7 @@ class SearchChain(ChainBase):
if torrenthelper.filter_torrent(torrent, filter_params)
]
if rule_groups is None:
rule_groups = SystemConfigOper().get(SystemConfigKey.SearchFilterRuleGroups) or []
rule_groups = get_configured_system_config().get(SystemConfigKey.SearchFilterRuleGroups) or []
if rule_groups and torrents:
torrents = self.filter_torrents(
rule_groups=rule_groups,
@@ -2272,7 +2272,7 @@ class SearchChain(ChainBase):
# 配置的索引站点
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
for indexer in SitesHelper().get_indexers():
# 检查站点索引开关
@@ -2386,7 +2386,7 @@ class SearchChain(ChainBase):
# 配置的索引站点
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
for indexer in await SitesHelper().async_get_indexers():
# 检查站点索引开关
@@ -2509,7 +2509,7 @@ class SearchChain(ChainBase):
indexer_sites = []
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
for indexer in await SitesHelper().async_get_indexers():
if not sites or indexer.get("id") in sites:
@@ -2646,7 +2646,7 @@ class SearchChain(ChainBase):
indexer_sites = []
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
for indexer in await SitesHelper().async_get_indexers():
if not indexer.get("subtitles"):
@@ -2742,7 +2742,7 @@ class SearchChain(ChainBase):
indexer_sites = []
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
for indexer in await SitesHelper().async_get_indexers():
if not indexer.get("subtitles"):
@@ -2871,10 +2871,10 @@ class SearchChain(ChainBase):
return
if site_id == "*":
# 清空搜索站点
SystemConfigOper().set(SystemConfigKey.IndexerSites, [])
get_configured_system_config().set(SystemConfigKey.IndexerSites, [])
return
# 从选中的rss站点中移除
selected_sites = SystemConfigOper().get(SystemConfigKey.IndexerSites) or []
selected_sites = get_configured_system_config().get(SystemConfigKey.IndexerSites) or []
if site_id in selected_sites:
selected_sites.remove(site_id)
SystemConfigOper().set(SystemConfigKey.IndexerSites, selected_sites)
get_configured_system_config().set(SystemConfigKey.IndexerSites, selected_sites)
+11 -6
View File
@@ -1,7 +1,7 @@
import base64
import re
from datetime import datetime
from typing import Callable, Optional, Tuple, Union, Dict
from typing import Any, Callable, Optional, Tuple, Union, Dict
from urllib.parse import urljoin
from app.application.site.sites import SitesHelper # pylint: disable=no-name-in-module
@@ -11,9 +11,8 @@ from app.chain import ChainBase
from app.chain._interaction import InteractionChainMixin
from app.runtime.config import global_vars, settings
from app.runtime.events import Event, eventmanager
from app.db.models.site import Site
from app.db.oper.site import SiteOper
from app.db.oper.systemconfig import SystemConfigOper
from app.application.chain.data import SitePortProxy as SiteOper
from app.application.configuration import get_configured_system_config
from app.adapters.network.browser import PlaywrightHelper
from app.adapters.network.cloudflare import under_challenge
from app.application.security.cookie import CookieHelper
@@ -32,6 +31,8 @@ from app.foundation import size as size_tools
from app.foundation import url as url_tools
from app.foundation.dom import DomUtils
Site = Any
class SiteChain(InteractionChainMixin, ChainBase):
"""
@@ -640,7 +641,7 @@ class SiteChain(InteractionChainMixin, ChainBase):
# 获取主域名中间那段
domain_host = url_tools.host_label(domain)
# 查询以"site.domain_host"开头的配置项,并清除
systemconfig = SystemConfigOper()
systemconfig = get_configured_system_config()
site_keys = systemconfig.all().keys()
for key in site_keys:
if key.startswith(f"site.{domain_host}"):
@@ -751,7 +752,11 @@ class SiteChain(InteractionChainMixin, ChainBase):
def _interaction_handler(self) -> "SiteInteractionHandler":
"""构造 /sites 交互处理器,Cookie 更新动作由本链提供。"""
return SiteInteractionHandler(messenger=self, cookie_updater=self.update_cookie)
return SiteInteractionHandler(
messenger=self,
cookie_updater=self.update_cookie,
repository=SiteOper(),
)
def remote_disable(self, arg_str: str, channel: NotificationChannel,
userid: Union[str, int] = None, source: Optional[str] = None):
+59 -16
View File
@@ -33,11 +33,12 @@ from app.domain.meta.metabase import MetaBase
from app.domain.meta.metamusic import MetaMusic
from app.domain.meta.words import WordsMatcher
from app.domain.metainfo import MetaInfo
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.models.subscribe import Subscribe
from app.db.oper.site import SiteOper
from app.db.oper.subscribe import SubscribeOper
from app.db.oper.systemconfig import SystemConfigOper
from app.application.chain.data import (
DownloadHistoryPortProxy as DownloadHistoryOper,
SitePortProxy as SiteOper,
SubscribePortProxy as SubscribeOper,
)
from app.application.configuration import get_configured_system_config
from app.application.messaging.subscribe import SubscribeInteractionHandler
from app.application.mediaserver import MediaServerHelper
from app.application.subscribe import add_subscribe, async_add_subscribe
@@ -56,6 +57,43 @@ from app.schemas.types import MUSIC_ENTITY_ALBUM, MediaSource, MediaType, System
ContentType
from app.schemas.media import normalize_media_source, resolve_media_identity
if hasattr(_SchemaSubscribe, "model_fields"):
Subscribe = _SchemaSubscribe
else:
class Subscribe(_SchemaSubscribe):
"""隔离测试或旧插件缺少完整订阅模型时使用的轻量快照。"""
def __init__(self, **kwargs):
"""初始化兼容快照并补齐链路必需的运行字段。"""
super().__init__(**kwargs)
for field, default in {
"best_version_full": 0,
"current_priority": None,
"episode_priority": None,
"total_episode": 0,
"start_episode": 0,
"lack_episode": 0,
"note": [],
}.items():
if not hasattr(self, field):
setattr(self, field, default)
def to_dict(self) -> dict:
"""返回快照字段,兼容整理链的响应转换。"""
return dict(self.__dict__)
# 旧测试与第三方扩展可能替换该名字;它现在只是应用配置端口的本地别名,
# 不再指向数据库 Oper。
SystemConfigOper = get_configured_system_config
_DEFAULT_SYSTEM_CONFIG_PROVIDER = get_configured_system_config
def _system_config():
"""返回配置端口,并兼容旧测试对本地别名的替换。"""
if SystemConfigOper is not _DEFAULT_SYSTEM_CONFIG_PROVIDER:
return SystemConfigOper()
return get_configured_system_config()
def build_subscribe_meta(subscribe: Subscribe) -> MetaBase:
"""兼容旧导入路径,转发订阅媒体元数据构造。"""
@@ -1345,10 +1383,10 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
# 优先级过滤规则
if subscribe.best_version:
rule_groups = subscribe.filter_groups \
or SystemConfigOper().get(SystemConfigKey.BestVersionFilterRuleGroups) or []
or _system_config().get(SystemConfigKey.BestVersionFilterRuleGroups) or []
else:
rule_groups = subscribe.filter_groups \
or SystemConfigOper().get(SystemConfigKey.SubscribeFilterRuleGroups) or []
or _system_config().get(SystemConfigKey.SubscribeFilterRuleGroups) or []
# 搜索,同时电视剧会过滤掉不需要的剧集
contexts = SearchChain().process(mediainfo=mediainfo,
@@ -1631,7 +1669,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
:return: 涉及的站点清单
"""
# 从系统配置获取默认订阅站点
default_sites = SystemConfigOper().get(SystemConfigKey.RssSites) or []
default_sites = _system_config().get(SystemConfigKey.RssSites) or []
# 如果订阅未指定站点,直接返回默认站点
if not subscribe.sites:
return default_sites
@@ -1832,7 +1870,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
# 遍历预识别后的种子
_match_context = []
torrenthelper = TorrentHelper()
systemconfig = SystemConfigOper()
systemconfig = _system_config()
wordsmatcher = WordsMatcher()
for domain, contexts in processed_torrents.items():
if global_vars.is_system_stopped:
@@ -2231,7 +2269,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
:param progress_callback: 定时服务进度更新回调
"""
follow_users: List[str] = SystemConfigOper().get(SystemConfigKey.FollowSubscribers)
follow_users: List[str] = _system_config().get(SystemConfigKey.FollowSubscribers)
if not follow_users:
if progress_callback:
progress_callback(value=100, text="未配置 Follow 订阅用户,跳过刷新")
@@ -2835,7 +2873,12 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
def _interaction_handler(self) -> "SubscribeInteractionHandler":
"""构造 /subscribes 交互处理器,业务动作由本链提供。"""
return SubscribeInteractionHandler(messenger=self, actions=self)
return SubscribeInteractionHandler(
messenger=self,
actions=self,
repository=SubscribeOper(),
report_deleted=MoviePilotServerHelper.sub_done_async,
)
def remote_delete(self, arg_str: str, channel: NotificationChannel,
userid: Union[str, int] = None, source: Optional[str] = None):
@@ -3012,7 +3055,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
subscribeoper = SubscribeOper()
if site_id == "*":
# 站点被重置
SystemConfigOper().set(SystemConfigKey.RssSites, [])
_system_config().set(SystemConfigKey.RssSites, [])
for subscribe in subscribeoper.list():
if not subscribe.sites:
continue
@@ -3021,10 +3064,10 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
})
return
# 从选中的rss站点中移除
selected_sites = SystemConfigOper().get(SystemConfigKey.RssSites) or []
selected_sites = _system_config().get(SystemConfigKey.RssSites) or []
if site_id in selected_sites:
selected_sites.remove(site_id)
SystemConfigOper().set(SystemConfigKey.RssSites, selected_sites)
_system_config().set(SystemConfigKey.RssSites, selected_sites)
# 查询所有订阅
for subscribe in subscribeoper.list():
if not subscribe.sites:
@@ -3057,7 +3100,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
if hasattr(settings, default_subscribe_key):
value = getattr(settings, default_subscribe_key)
else:
value = SystemConfigOper().get(default_subscribe_key)
value = _system_config().get(default_subscribe_key)
if not value:
return None
@@ -3069,7 +3112,7 @@ class SubscribeChain(MusicSubscribeMixin, InteractionChainMixin, ChainBase):
获取订阅默认参数
"""
# 默认过滤规则
default_rule = SystemConfigOper().get(SystemConfigKey.SubscribeDefaultParams) or {}
default_rule = _system_config().get(SystemConfigKey.SubscribeDefaultParams) or {}
return {
key: value for key, value in {
"include": subscribe.include or default_rule.get("include"),
+2 -2
View File
@@ -6,7 +6,7 @@ from typing import Union, Optional
from app.chain import ChainBase
from app.runtime.config import settings
from app.runtime.extensions.plugin_manager import PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.runtime.state import SystemHelper
from app.runtime.log import logger
from app.schemas.message import Message
@@ -154,7 +154,7 @@ class SystemChain(ChainBase):
logger.info(f"插件恢复完成,共恢复 {restored_count} 个项目")
# 安装缺少的依赖
PluginManager.install_plugin_missing_dependencies()
get_plugin_manager().install_plugin_missing_dependencies()
# 删除备份目录
try:
+3 -3
View File
@@ -12,8 +12,8 @@ from app.domain.context import TorrentInfo, Context, MediaInfo
from app.domain.context import MusicInfo
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfo
from app.db.oper.site import SiteOper
from app.db.oper.systemconfig import SystemConfigOper
from app.application.chain.data import SitePortProxy as SiteOper
from app.application.configuration import get_configured_system_config
from app.application.rss import RssHelper
from app.application.torrent import TorrentHelper
from app.runtime.log import logger
@@ -556,7 +556,7 @@ class TorrentsChain(ChainBase):
# 刷新站点
if not sites:
sites = SystemConfigOper().get(SystemConfigKey.RssSites) or []
sites = get_configured_system_config().get(SystemConfigKey.RssSites) or []
# 读取缓存,影视与音乐分别独立存储
if stype == 'spider':
+17 -9
View File
@@ -18,11 +18,13 @@ from app.runtime.events import eventmanager
from app.domain.meta.metabase import MetaBase
from app.domain.meta.metamusic import MetaMusic
from app.domain.metainfo import MetaInfoPath
from app.db.oper.downloadhistory import DownloadHistoryOper
from app.db.models.downloadhistory import DownloadHistory
from app.db.oper.systemconfig import SystemConfigOper
from app.db.oper.transferpending import TransferPendingOper
from app.db.oper.transferhistory import TransferHistoryOper
from app.application.chain.data import (
DownloadHistoryPortProxy as DownloadHistoryOper,
TransferPendingPortProxy as TransferPendingOper,
TransferHistoryPortProxy as TransferHistoryOper,
)
DownloadHistory = Any
from app.application.configuration import get_configured_system_config
from app.application.directory import DirectoryHelper
from app.application.formatting import FormatParser
from app.runtime.progress import ProgressHelper
@@ -53,8 +55,14 @@ from app.schemas.types import (
MediaSource,
)
from app.runtime.reload import ConfigReloadMixin
from app.application.transfer import (FailedRetryScheduler, JobManager,
TransferQueueService, TransferTask, job_lock)
from app.application.transfer import (
FailedRetryScheduler,
JobManager,
TransferQueue,
TransferQueueService,
TransferTask,
job_lock,
)
from app.chain._transfer import (EpisodeFormatMixin, FailedRetryMixin,
FileFilterMixin, FileKeyMixin,
HistoryMatchMixin, ManualHistoryMixin,
@@ -437,7 +445,7 @@ class TransferChain(FileFilterMixin, ScrapeBatchMixin, EpisodeFormatMixin, Histo
tasks = self.jobview.success_tasks(
task.mediainfo, task.meta.begin_season
)
system_config_oper = SystemConfigOper()
system_config_oper = get_configured_system_config()
# 获取整理屏蔽词
transfer_exclude_words = system_config_oper.get(
SystemConfigKey.TransferExcludeWords
@@ -1579,7 +1587,7 @@ class TransferChain(FileFilterMixin, ScrapeBatchMixin, EpisodeFormatMixin, Histo
)
# 整理屏蔽词
transfer_exclude_words = SystemConfigOper().get(
transfer_exclude_words = get_configured_system_config().get(
SystemConfigKey.TransferExcludeWords
)
# 汇总错误信息
+4 -4
View File
@@ -1,12 +1,11 @@
import secrets
from dataclasses import dataclass
from typing import Literal, Optional, Tuple, Union
from typing import Any, Literal, Optional, Tuple, Union
from app.chain import ChainBase
from app.runtime.config import settings
from app.application.security.access import get_password_hash, verify_password
from app.db.models.user import User
from app.db.oper.user import UserOper
from app.application.security.token import get_password_hash, verify_password
from app.application.chain.data import UserPortProxy as UserOper
from app.runtime.log import logger
from app.schemas.event import AuthCredentials
from app.schemas.event import AuthInterceptCredentials
@@ -14,6 +13,7 @@ from app.schemas.types import ChainEventType
from app.application.security.otp import OtpUtils
PASSWORD_INVALID_CREDENTIALS_MESSAGE = "用户名、密码或验证码错误"
User = Any
MfaMethod = Literal["otp"]
+2 -2
View File
@@ -15,8 +15,7 @@ from pydantic import BaseModel
from app.chain import ChainBase
from app.runtime.config import global_vars
from app.runtime.events import Event, eventmanager
from app.db.models import Workflow
from app.db.oper.workflow import WorkflowOper
from app.application.chain.data import WorkflowPortProxy as WorkflowOper
from app.runtime.log import logger
from app.schemas.workflow import ActionContext
from app.schemas.workflow import ActionFlow
@@ -29,6 +28,7 @@ from app.workflow import WorkFlowManager
ARTIFACT_FIELDS = {"torrents", "medias", "fileitems", "downloads", "sites", "subscribes"}
DEFAULT_WORKFLOW_MAX_WORKERS = 4
CIRCULAR_REFERENCE_PLACEHOLDER = "[Circular]"
Workflow = Any
def _serialize_workflow_key(key: Any) -> Any: