Run full live catalog refreshes through live source sync, complete channel analysis, EPG source refresh, and persisted EPG rematching while keeping check-new incremental. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
100 lines
3.4 KiB
JavaScript
100 lines
3.4 KiB
JavaScript
const LIVE_PROJECTION_COLUMNS = {
|
|
logical_channel_id: 'TEXT',
|
|
grouping_fingerprint: 'TEXT',
|
|
grouping_input_hash: 'TEXT',
|
|
quality_label: 'TEXT',
|
|
quality_rank: 'INTEGER',
|
|
variant_rank: 'INTEGER',
|
|
language_code: 'TEXT',
|
|
language_confidence: 'REAL',
|
|
language_scores: 'JSON',
|
|
language_evidence: 'JSON',
|
|
language_detector: 'TEXT',
|
|
language_input_hash: 'TEXT'
|
|
};
|
|
|
|
const CATALOG_PROJECTION_STATE_COLUMNS = {
|
|
phase: "TEXT NOT NULL DEFAULT 'idle'",
|
|
processed_count: 'INTEGER NOT NULL DEFAULT 0',
|
|
total_count: 'INTEGER NOT NULL DEFAULT 0',
|
|
laya_processed_count: 'INTEGER NOT NULL DEFAULT 0',
|
|
laya_total_count: 'INTEGER NOT NULL DEFAULT 0'
|
|
};
|
|
|
|
const LIVE_PROJECTION_SCHEMA_SQL = `
|
|
CREATE INDEX IF NOT EXISTS idx_items_logical_channel ON playlist_items(logical_channel_id);
|
|
CREATE INDEX IF NOT EXISTS idx_items_grouping_fingerprint ON playlist_items(grouping_fingerprint);
|
|
|
|
CREATE TABLE IF NOT EXISTS logical_channels (
|
|
id TEXT PRIMARY KEY,
|
|
fingerprint TEXT NOT NULL UNIQUE,
|
|
display_name TEXT NOT NULL,
|
|
preferred_variant_id TEXT,
|
|
variant_count INTEGER NOT NULL DEFAULT 0,
|
|
created_at INTEGER NOT NULL,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_logical_channels_fingerprint ON logical_channels(fingerprint);
|
|
|
|
CREATE TABLE IF NOT EXISTS iptv_org_channels (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
normalized_name TEXT NOT NULL,
|
|
alt_names JSON NOT NULL DEFAULT '[]',
|
|
country TEXT,
|
|
languages JSON NOT NULL DEFAULT '[]',
|
|
data JSON,
|
|
updated_at INTEGER NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_iptv_org_channels_name ON iptv_org_channels(normalized_name);
|
|
|
|
CREATE TABLE IF NOT EXISTS iptv_org_cache_state (
|
|
resource TEXT PRIMARY KEY,
|
|
refreshed_at INTEGER NOT NULL,
|
|
item_count INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS live_epg_matches (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
logical_channel_id TEXT NOT NULL,
|
|
language_code TEXT NOT NULL,
|
|
source_id INTEGER,
|
|
channel_id TEXT,
|
|
match_confidence REAL NOT NULL DEFAULT 0,
|
|
data JSON,
|
|
updated_at INTEGER NOT NULL,
|
|
UNIQUE (logical_channel_id, language_code)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_live_epg_matches_channel
|
|
ON live_epg_matches(logical_channel_id, language_code);
|
|
|
|
CREATE TABLE IF NOT EXISTS catalog_projection_state (
|
|
projection TEXT PRIMARY KEY,
|
|
status TEXT NOT NULL,
|
|
started_at INTEGER,
|
|
completed_at INTEGER,
|
|
input_hash TEXT,
|
|
projected_count INTEGER NOT NULL DEFAULT 0,
|
|
phase TEXT NOT NULL DEFAULT 'idle',
|
|
processed_count INTEGER NOT NULL DEFAULT 0,
|
|
total_count INTEGER NOT NULL DEFAULT 0,
|
|
laya_processed_count INTEGER NOT NULL DEFAULT 0,
|
|
laya_total_count INTEGER NOT NULL DEFAULT 0,
|
|
error TEXT
|
|
);
|
|
`;
|
|
|
|
function ensureColumns(database, table, columns) {
|
|
const existing = new Set(database.prepare(`PRAGMA table_info(${table})`).all().map(column => column.name));
|
|
for (const [name, definition] of Object.entries(columns)) {
|
|
if (!existing.has(name)) database.exec(`ALTER TABLE ${table} ADD COLUMN ${name} ${definition}`);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
CATALOG_PROJECTION_STATE_COLUMNS,
|
|
ensureColumns,
|
|
LIVE_PROJECTION_COLUMNS,
|
|
LIVE_PROJECTION_SCHEMA_SQL
|
|
};
|