Files
Nodecast/server/db/liveProjectionSchema.js
blomios b3dbb3cfba feat: run full refresh with EPG rematching
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>
2026-10-08 00:05:00 +02:00

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
};