fix(backend): 连载番剧只超出集数时照常标记并只通知一次,此类标记不随复扫清除 (#1072)

- offset_scanner: 去掉“建议偏移全为 0 且未完结不标记”的跳过;已标记番剧复扫无不匹配时,只清除建议偏移非 0 的标记,只超出集数的标记由用户忽略或应用(与 3.3 一致)
- 测试:连载番剧首扫标记并通知、复扫不再通知、TMDB 跟上后只超出集数的标记保留而季度不匹配的标记清除;复扫测试的旧标记改为真实不匹配
This commit is contained in:
Estrella Pan
2026-10-21 10:29:25 +02:00
parent 1dda39f2d5
commit b592d6cb0d
2 changed files with 44 additions and 32 deletions

View File

@@ -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,

View File

@@ -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(