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):