diff --git a/backend/src/module/core/offset_scanner.py b/backend/src/module/core/offset_scanner.py index 385c489d..da94603e 100644 --- a/backend/src/module/core/offset_scanner.py +++ b/backend/src/module/core/offset_scanner.py @@ -8,7 +8,7 @@ from module.models import Bangumi from module.notification.events import OffsetReviewEvent from module.parser.analyser.offset_detector import detect_offset_mismatch from module.parser.analyser.selector import parse_configured_release_title -from module.parser.analyser.tmdb_parser import FINAL_SERIES_STATUSES, tmdb_parser +from module.parser.analyser.tmdb_parser import tmdb_parser from module.parser.release_policy import is_offset_signal logger = logging.getLogger(__name__) @@ -95,27 +95,21 @@ class OffsetScanner: "high", "medium", ) - # 建议的偏移全为 0 时只是集数超出 TMDB 该季集数;未完结的剧集是字幕组 - # 跑在 TMDB 前面,不算不匹配。否则 TMDB 缓存每天过期、跟上后清除, - # 下周新集又超出,每周都会重新标记并通知一次 - if ( - suggestion is not None - and not suggestion.season_offset - and not suggestion.episode_offset - and tmdb_info.series_status not in FINAL_SERIES_STATUSES - ): - flagged = False # 已标记的番剧也要重新扫描:TMDB 集数更新或解析修正后,误报不会自己消失 # (#1072)。needs_review 只由本扫描器设置;用户忽略或应用后标记已清除, # 手动配了偏移的在上面已跳过,这里清除的只会是扫描器自己的旧标记 if bangumi.needs_review: if not flagged: - async with Database() as db: - await db.bangumi.clear_needs_review(bangumi.id) - logger.info( - "Cleared review flag for %s: no mismatch on rescan", - bangumi.official_title, - ) + # 建议的偏移全为 0 的标记只是集数超出 TMDB 该季集数:连载中 TMDB + # 跟上后清除、下周新集又超出,会每周重复通知,所以不自动清除, + # 由用户忽略或应用 + if bangumi.suggested_season_offset or bangumi.suggested_episode_offset: + async with Database() as db: + await db.bangumi.clear_needs_review(bangumi.id) + logger.info( + "Cleared review flag for %s: no mismatch on rescan", + bangumi.official_title, + ) elif suggestion is not None and ( suggestion.reason, suggestion.season_offset, diff --git a/backend/src/test/test_offset_scanner.py b/backend/src/test/test_offset_scanner.py index b3c7e83e..e9c661e1 100644 --- a/backend/src/test/test_offset_scanner.py +++ b/backend/src/test/test_offset_scanner.py @@ -360,15 +360,17 @@ class TestCheckBangumiUsesRealSignal: assert "12" in updated.needs_review_reason @pytest.mark.parametrize( - ("season", "episode", "flagged"), + ("season", "episode", "kept_after_catch_up"), [ - (1, 13, False), # 只超出集数:字幕组跑在 TMDB 前面,不标记 - (2, 5, True), # 季度对不上:真实不匹配,照常标记 + (1, 13, True), # 只超出集数:TMDB 跟上后也不自动清除,由用户处理 + (2, 5, False), # 季度对不上:TMDB 跟上后不再不匹配,自动清除 ], ids=["overflow-only", "season-mismatch"], ) - async def test_airing_show_flags_only_real_mismatch(self, season, episode, flagged): - """连载中的番剧只有建议的偏移非 0 时才标记,否则每周都会误报一次(#1072)。""" + async def test_airing_show_flag_notifies_once( + self, season, episode, kept_after_catch_up + ): + """连载中的番剧标记后只通知一次;只超出集数的标记不随复扫清除(#1072)。""" scanner = OffsetScanner() async with Database() as db: bangumi = make_bangumi( @@ -388,16 +390,31 @@ class TestCheckBangumiUsesRealSignal: tmdb_info = self._ended_twelve_episode_season() tmdb_info.series_status = "Returning Series" - with patch( - "module.core.offset_scanner.tmdb_parser", - new=AsyncMock(return_value=tmdb_info), - ): - event = await scanner._check_bangumi(bangumi) - assert isinstance(event, OffsetReviewEvent) is flagged - async with Database() as db: - updated = await db.bangumi.search_id(bangumi.id) - assert updated.needs_review is flagged + async def scan(): + async with Database() as db: + current = await db.bangumi.search_id(bangumi.id) + with patch( + "module.core.offset_scanner.tmdb_parser", + new=AsyncMock(return_value=tmdb_info), + ): + event = await scanner._check_bangumi(current) + async with Database() as db: + updated = await db.bangumi.search_id(bangumi.id) + return event, updated.needs_review + + # 首次扫描:标记并通知一次 + event, needs_review = await scan() + assert isinstance(event, OffsetReviewEvent) + assert needs_review is True + + # 复扫仍是同样的不匹配:保留标记,不再通知 + assert await scan() == (None, True) + + # TMDB 跟上(多了第 13 集和第 2 季)后复扫:不再通知 + tmdb_info.last_season = 2 + tmdb_info.season_episode_counts = {1: 13, 2: 12} + assert await scan() == (None, kept_after_catch_up) class TestRescanFlaggedBangumi: @@ -426,8 +443,9 @@ class TestRescanFlaggedBangumi: episode_offset=0, ) await db.bangumi.add(bangumi) + # 建议偏移非 0 的真实不匹配标记;只超出集数的标记不自动清除 await db.bangumi.set_needs_review( - bangumi.id, reason, suggested_season_offset=0 + bangumi.id, reason, suggested_season_offset=-1 ) await db.torrent.add( Torrent(