From 01a1a79a339197ebafbc3573c47ddb79dd6ff692 Mon Sep 17 00:00:00 2001 From: EstrellaXD Date: Mon, 26 Jan 2026 13:45:40 +0100 Subject: [PATCH] feat(offset): add suggested offset values to review panel When offset scanner detects a mismatch, it now stores: - suggested_season_offset: recommended season offset value - suggested_episode_offset: recommended episode offset value These values are returned in the API response for bangumi that need review, allowing the frontend to display them to help users configure the correct offset. Database migration v7 adds the new columns. Co-Authored-By: Claude Opus 4.5 --- backend/src/module/core/offset_scanner.py | 10 ++++++-- backend/src/module/database/bangumi.py | 28 ++++++++++++++++++--- backend/src/module/database/combine.py | 8 ++++++ backend/src/module/models/bangumi.py | 30 ++++++++++++++++++----- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/backend/src/module/core/offset_scanner.py b/backend/src/module/core/offset_scanner.py index 02f42128..81a22d94 100644 --- a/backend/src/module/core/offset_scanner.py +++ b/backend/src/module/core/offset_scanner.py @@ -90,9 +90,15 @@ class OffsetScanner: if suggestion and suggestion.confidence in ("high", "medium"): with Database() as db: - db.bangumi.set_needs_review(bangumi.id, suggestion.reason) + db.bangumi.set_needs_review( + bangumi.id, + suggestion.reason, + suggested_season_offset=suggestion.season_offset, + suggested_episode_offset=suggestion.episode_offset, + ) logger.info( - f"[OffsetScanner] Flagged {bangumi.official_title} for review: {suggestion.reason}" + f"[OffsetScanner] Flagged {bangumi.official_title} for review: {suggestion.reason} " + f"(suggested: season={suggestion.season_offset}, episode={suggestion.episode_offset})" ) return True diff --git a/backend/src/module/database/bangumi.py b/backend/src/module/database/bangumi.py index 94816028..6afb2571 100644 --- a/backend/src/module/database/bangumi.py +++ b/backend/src/module/database/bangumi.py @@ -373,26 +373,46 @@ class BangumiDatabase: result = self.session.execute(statement) return list(result.scalars().all()) - def set_needs_review(self, _id: int, reason: str) -> bool: - """Mark a bangumi as needing review.""" + def set_needs_review( + self, + _id: int, + reason: str, + suggested_season_offset: int | None = None, + suggested_episode_offset: int | None = None, + ) -> bool: + """Mark a bangumi as needing review with suggested offsets. + + Args: + _id: The bangumi ID + reason: Human-readable reason for the review + suggested_season_offset: Suggested season offset value + suggested_episode_offset: Suggested episode offset value + """ bangumi = self.session.get(Bangumi, _id) if not bangumi: return False bangumi.needs_review = True bangumi.needs_review_reason = reason + bangumi.suggested_season_offset = suggested_season_offset + bangumi.suggested_episode_offset = suggested_episode_offset self.session.add(bangumi) self.session.commit() _invalidate_bangumi_cache() - logger.debug(f"[Database] Marked bangumi id {_id} as needs_review: {reason}") + logger.debug( + f"[Database] Marked bangumi id {_id} as needs_review: {reason} " + f"(suggested: season={suggested_season_offset}, episode={suggested_episode_offset})" + ) return True def clear_needs_review(self, _id: int) -> bool: - """Clear the needs_review flag for a bangumi.""" + """Clear the needs_review flag and suggested offsets for a bangumi.""" bangumi = self.session.get(Bangumi, _id) if not bangumi: return False bangumi.needs_review = False bangumi.needs_review_reason = None + bangumi.suggested_season_offset = None + bangumi.suggested_episode_offset = None self.session.add(bangumi) self.session.commit() _invalidate_bangumi_cache() diff --git a/backend/src/module/database/combine.py b/backend/src/module/database/combine.py index afda0a08..eddbfc14 100644 --- a/backend/src/module/database/combine.py +++ b/backend/src/module/database/combine.py @@ -88,6 +88,14 @@ MIGRATIONS = [ "CREATE INDEX IF NOT EXISTS ix_torrent_qb_hash ON torrent(qb_hash)", ], ), + ( + 7, + "add suggested offset columns for offset review", + [ + "ALTER TABLE bangumi ADD COLUMN suggested_season_offset INTEGER DEFAULT NULL", + "ALTER TABLE bangumi ADD COLUMN suggested_episode_offset INTEGER DEFAULT NULL", + ], + ), ] diff --git a/backend/src/module/models/bangumi.py b/backend/src/module/models/bangumi.py index d5a3b834..e6f41831 100644 --- a/backend/src/module/models/bangumi.py +++ b/backend/src/module/models/bangumi.py @@ -11,7 +11,9 @@ class Bangumi(SQLModel, table=True): default="official_title", alias="official_title", title="番剧中文名" ) year: Optional[str] = Field(alias="year", title="番剧年份") - title_raw: str = Field(default="title_raw", alias="title_raw", title="番剧原名", index=True) + title_raw: str = Field( + default="title_raw", alias="title_raw", title="番剧原名", index=True + ) season: int = Field(default=1, alias="season", title="番剧季度") season_raw: Optional[str] = Field(alias="season_raw", title="番剧季度原名") group_name: Optional[str] = Field(alias="group_name", title="字幕组") @@ -28,10 +30,22 @@ class Bangumi(SQLModel, table=True): rule_name: Optional[str] = Field(alias="rule_name", title="番剧规则名") save_path: Optional[str] = Field(alias="save_path", title="番剧保存路径") deleted: bool = Field(False, alias="deleted", title="是否已删除", index=True) - archived: bool = Field(default=False, alias="archived", title="是否已归档", index=True) - air_weekday: Optional[int] = Field(default=None, alias="air_weekday", title="放送星期") + archived: bool = Field( + default=False, alias="archived", title="是否已归档", index=True + ) + air_weekday: Optional[int] = Field( + default=None, alias="air_weekday", title="放送星期" + ) needs_review: bool = Field(default=False, alias="needs_review", title="需要检查") - needs_review_reason: Optional[str] = Field(default=None, alias="needs_review_reason", title="检查原因") + needs_review_reason: Optional[str] = Field( + default=None, alias="needs_review_reason", title="检查原因" + ) + suggested_season_offset: Optional[int] = Field( + default=None, alias="suggested_season_offset", title="建议季度偏移" + ) + suggested_episode_offset: Optional[int] = Field( + default=None, alias="suggested_episode_offset", title="建议集数偏移" + ) class BangumiUpdate(SQLModel): @@ -57,9 +71,13 @@ class BangumiUpdate(SQLModel): save_path: Optional[str] = Field(alias="save_path", title="番剧保存路径") deleted: bool = Field(False, alias="deleted", title="是否已删除") archived: bool = Field(default=False, alias="archived", title="是否已归档") - air_weekday: Optional[int] = Field(default=None, alias="air_weekday", title="放送星期") + air_weekday: Optional[int] = Field( + default=None, alias="air_weekday", title="放送星期" + ) needs_review: bool = Field(default=False, alias="needs_review", title="需要检查") - needs_review_reason: Optional[str] = Field(default=None, alias="needs_review_reason", title="检查原因") + needs_review_reason: Optional[str] = Field( + default=None, alias="needs_review_reason", title="检查原因" + ) class Notification(BaseModel):