mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-06 16:07:01 +08:00
refactor(subscribe): unify best_version episode upgrade logic and always track downloads in note
- Simplify and centralize logic for filtering TV episodes during best_version (wash) mode, ensuring only episodes with strictly higher priority are considered for upgrade. - Always update subscribe.note with downloaded episodes regardless of best_version state, ensuring download history is reliably tracked and available for all subscription modes. - Remove redundant episode_group field from subscribe dict output. - Refactor search: remove multi-page search logic, streamline concurrent site search for both sync and async paths, and update progress reporting accordingly. - Remove obsolete tests for allowed_episodes propagation and note tracking, as logic is now unified and simplified.
This commit is contained in:
+2
-3
@@ -882,7 +882,6 @@ class SearchChain(ChainBase):
|
|||||||
|
|
||||||
# 开始匹配
|
# 开始匹配
|
||||||
_match_torrents = []
|
_match_torrents = []
|
||||||
torrenthelper = TorrentHelper()
|
|
||||||
try:
|
try:
|
||||||
# 英文标题应该在别名/原标题中,不需要再匹配
|
# 英文标题应该在别名/原标题中,不需要再匹配
|
||||||
logger.info(f"开始匹配结果 标题:{mediainfo.title},原标题:{mediainfo.original_title},别名:{mediainfo.names}")
|
logger.info(f"开始匹配结果 标题:{mediainfo.title},原标题:{mediainfo.original_title},别名:{mediainfo.names}")
|
||||||
@@ -916,7 +915,7 @@ class SearchChain(ChainBase):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# 比对种子
|
# 比对种子
|
||||||
if torrenthelper.match_torrent(mediainfo=mediainfo,
|
if TorrentHelper.match_torrent(mediainfo=mediainfo,
|
||||||
torrent_meta=torrent_meta,
|
torrent_meta=torrent_meta,
|
||||||
torrent=torrent):
|
torrent=torrent):
|
||||||
# 匹配成功
|
# 匹配成功
|
||||||
@@ -950,7 +949,7 @@ class SearchChain(ChainBase):
|
|||||||
# 排序
|
# 排序
|
||||||
progress.update(value=99,
|
progress.update(value=99,
|
||||||
text=f'正在对 {len(contexts)} 个资源进行排序,请稍候...')
|
text=f'正在对 {len(contexts)} 个资源进行排序,请稍候...')
|
||||||
contexts = torrenthelper.sort_torrents(contexts)
|
contexts = TorrentHelper.sort_torrents(contexts)
|
||||||
|
|
||||||
# 结束进度
|
# 结束进度
|
||||||
logger.info(f'搜索完成,共 {len(contexts)} 个资源')
|
logger.info(f'搜索完成,共 {len(contexts)} 个资源')
|
||||||
|
|||||||
@@ -1441,7 +1441,7 @@ class SubscribeChain(ChainBase):
|
|||||||
not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id):
|
not torrent_mediainfo.tmdb_id and not torrent_mediainfo.douban_id):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...')
|
f'{torrent_info.site_name} - {torrent_info.title} 重新识别失败,尝试通过标题匹配...')
|
||||||
if torrenthelper.match_torrent(mediainfo=mediainfo,
|
if TorrentHelper.match_torrent(mediainfo=mediainfo,
|
||||||
torrent_meta=torrent_meta,
|
torrent_meta=torrent_meta,
|
||||||
torrent=torrent_info):
|
torrent=torrent_info):
|
||||||
# 匹配成功
|
# 匹配成功
|
||||||
|
|||||||
@@ -92,6 +92,11 @@ def _load_subscribe_chain_class():
|
|||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_event_listener(*args, **kwargs):
|
||||||
|
"""兼容模块导入时注册配置变更监听。"""
|
||||||
|
return None
|
||||||
|
|
||||||
event_module.eventmanager = _EventManager()
|
event_module.eventmanager = _EventManager()
|
||||||
event_module.Event = SimpleNamespace
|
event_module.Event = SimpleNamespace
|
||||||
|
|
||||||
@@ -266,6 +271,8 @@ def _load_subscribe_chain_class():
|
|||||||
assert spec and spec.loader
|
assert spec and spec.loader
|
||||||
spec.loader.exec_module(module)
|
spec.loader.exec_module(module)
|
||||||
module._injected_modules = injected_modules
|
module._injected_modules = injected_modules
|
||||||
|
for injected_name in injected_modules:
|
||||||
|
sys.modules.pop(injected_name, None)
|
||||||
return module, module.SubscribeChain
|
return module, module.SubscribeChain
|
||||||
|
|
||||||
|
|
||||||
@@ -313,6 +320,73 @@ class SubscribeChainTest(TestCase):
|
|||||||
meta_info=SimpleNamespace(season_list=[1], episode_list=meta_episodes or []),
|
meta_info=SimpleNamespace(season_list=[1], episode_list=meta_episodes or []),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_match_title_fallback_calls_torrent_match_from_class(self):
|
||||||
|
"""确保标题兜底匹配不依赖 TorrentHelper 实例绑定。"""
|
||||||
|
|
||||||
|
class _ReachedTitleMatch(Exception):
|
||||||
|
"""标记测试已经进入标题匹配函数体。"""
|
||||||
|
|
||||||
|
class _PlainTorrentHelper:
|
||||||
|
"""模拟未声明 staticmethod 的历史 TorrentHelper 形态。"""
|
||||||
|
|
||||||
|
def match_torrent(mediainfo, torrent_meta, torrent):
|
||||||
|
"""标记类级调用已经正确进入匹配逻辑。"""
|
||||||
|
raise _ReachedTitleMatch
|
||||||
|
|
||||||
|
def filter_torrent(self, *args, **kwargs):
|
||||||
|
"""保持订阅匹配后续过滤流程可继续执行。"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
subscribe = self._build_subscribe(
|
||||||
|
best_version=0,
|
||||||
|
custom_words=None,
|
||||||
|
doubanid=None,
|
||||||
|
episode_group=None,
|
||||||
|
sites=[],
|
||||||
|
tmdbid=1,
|
||||||
|
)
|
||||||
|
mediainfo = SimpleNamespace(
|
||||||
|
clear=lambda: None,
|
||||||
|
douban_id=None,
|
||||||
|
title_year="Test Show (2026)",
|
||||||
|
tmdb_id=1,
|
||||||
|
type=MediaType.TV,
|
||||||
|
)
|
||||||
|
context = SimpleNamespace(
|
||||||
|
media_info=None,
|
||||||
|
media_recognize_fail_count=3,
|
||||||
|
meta_info=SimpleNamespace(
|
||||||
|
begin_season=1,
|
||||||
|
episode_list=[],
|
||||||
|
org_string="Test Show",
|
||||||
|
season_list=[1],
|
||||||
|
),
|
||||||
|
torrent_info=SimpleNamespace(
|
||||||
|
description="",
|
||||||
|
site=1,
|
||||||
|
site_name="TestSite",
|
||||||
|
title="Test Show S01",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
class _SubscribeOper:
|
||||||
|
"""提供单条订阅,避免依赖真实数据库。"""
|
||||||
|
|
||||||
|
def list(self, *args, **kwargs):
|
||||||
|
"""返回当前测试构造的订阅列表。"""
|
||||||
|
return [subscribe]
|
||||||
|
|
||||||
|
chain = SubscribeChain()
|
||||||
|
chain.recognize_media = lambda **kwargs: mediainfo
|
||||||
|
chain.check_and_handle_existing_media = lambda **kwargs: (False, {})
|
||||||
|
|
||||||
|
with patch.object(SUBSCRIBE_CHAIN_MODULE, "SubscribeOper", _SubscribeOper), patch.object(
|
||||||
|
SUBSCRIBE_CHAIN_MODULE,
|
||||||
|
"TorrentHelper",
|
||||||
|
_PlainTorrentHelper,
|
||||||
|
), self.assertRaises(_ReachedTitleMatch):
|
||||||
|
chain.match({"test.example": [context]})
|
||||||
|
|
||||||
def test_get_episode_priority_falls_back_to_current_priority(self):
|
def test_get_episode_priority_falls_back_to_current_priority(self):
|
||||||
subscribe = self._build_subscribe(current_priority=80, episode_priority=None)
|
subscribe = self._build_subscribe(current_priority=80, episode_priority=None)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user