feat(identity): 识别接入集数解析——映射规则表、规范季集写回解析结果、待确认不建单元并开待处理、规则失效停用、按作品重算

迁移 0066_episode_mapping。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-03 18:03:32 +08:00
1 parent 7b9939e0a0
commit 691671a1d2
20 files changed
+1181 -17

No files matched your search

+32 -1
View File
@@ -111,7 +111,8 @@ export type DecisionKind =
| "metadata_conflict"
| "source_unreachable"
| "other"
| "identity_unresolved";
| "identity_unresolved"
| "episode_mapping";
export type DecisionStatus = "open" | "investigating" | "awaiting_user" | "resolved" | "dismissed" | "expired";
export type DecisionSeverity = "info" | "warning" | "critical";
export type DownloadTaskOrigin = "submitted" | "adopted";
@@ -130,6 +131,11 @@ export type DownloadTaskStatus =
export type DownloadTaskPauseReason = "user" | "threshold" | "policy" | "agent";
export type DownloaderInstanceKind = "qbittorrent";
export type DownloaderInstanceHealthStatus = "unknown" | "healthy" | "degraded" | "offline";
export type EpisodeMappingRuleKind = "expression" | "table" | "special";
export type EpisodeMappingRuleSpecial = "special" | "extra" | "ignore";
export type EpisodeMappingRuleStatus = "active" | "disabled";
export type EpisodeMappingRuleEvidenceLevel = "manual" | "rule_confirmed" | "multi_evidence" | "needs_review";
export type EpisodeMappingRuleCreatedByType = "user" | "agent" | "system" | "api_key";
export type ExternalIdentityEntityType = "movie" | "tv" | "season" | "episode" | "collection" | "person";
export type ExternalIdentityStatus = "accepted" | "proposed" | "conflicted" | "retired";
export type ExternalIdentityEvidenceLevel = "manual" | "rule_confirmed" | "multi_evidence" | "needs_review";
@@ -734,6 +740,26 @@ export interface DownloaderInstanceTable {
is_default: Generated<boolean>;
}
export interface EpisodeMappingRuleTable {
id: Generated<string>;
media_entity_id: string;
season: number | null;
release_group: string | null;
kind: EpisodeMappingRuleKind;
expression: string | null;
target_season: number | null;
table_entries: Json | null;
special: EpisodeMappingRuleSpecial | null;
status: Generated<EpisodeMappingRuleStatus>;
evidence_level: Generated<EpisodeMappingRuleEvidenceLevel>;
evidence: Generated<Json>;
disabled_reason: string | null;
created_by_type: EpisodeMappingRuleCreatedByType;
created_by_id: string | null;
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
}
export interface ExternalIdentityTable {
id: Generated<string>;
media_entity_id: string | null;
@@ -1557,6 +1583,7 @@ export interface SourceReleaseTable {
created_at: GeneratedTimestamptz;
updated_at: GeneratedTimestamptz;
resolution_locked: Generated<boolean>;
episode_resolution: Json | null;
}
export interface SseEventTable {
@@ -1748,6 +1775,7 @@ export interface DB {
decision: DecisionTable;
download_task: DownloadTaskTable;
downloader_instance: DownloaderInstanceTable;
episode_mapping_rule: EpisodeMappingRuleTable;
external_identity: ExternalIdentityTable;
feed_source: FeedSourceTable;
field_override: FieldOverrideTable;
@@ -1887,6 +1915,9 @@ export type DownloadTaskUpdate = Updateable<DownloadTaskTable>;
export type DownloaderInstanceRow = Selectable<DownloaderInstanceTable>;
export type NewDownloaderInstance = Insertable<DownloaderInstanceTable>;
export type DownloaderInstanceUpdate = Updateable<DownloaderInstanceTable>;
export type EpisodeMappingRuleRow = Selectable<EpisodeMappingRuleTable>;
export type NewEpisodeMappingRule = Insertable<EpisodeMappingRuleTable>;
export type EpisodeMappingRuleUpdate = Updateable<EpisodeMappingRuleTable>;
export type ExternalIdentityRow = Selectable<ExternalIdentityTable>;
export type NewExternalIdentity = Insertable<ExternalIdentityTable>;
export type ExternalIdentityUpdate = Updateable<ExternalIdentityTable>;