Refactored code to use sqlite for channel, epg and vod data
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
const Database = require('better-sqlite3');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const dataDir = path.join(__dirname, '..', '..', 'data');
|
||||
const dbPath = path.join(dataDir, 'content.db');
|
||||
|
||||
// Ensure data directory exists
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
}
|
||||
|
||||
let db;
|
||||
|
||||
function getDb() {
|
||||
if (!db) {
|
||||
console.log('[SQLite] Opening database at', dbPath);
|
||||
db = new Database(dbPath);
|
||||
// Optimize performance
|
||||
db.pragma('journal_mode = WAL');
|
||||
db.pragma('synchronous = NORMAL');
|
||||
initSchema();
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
function initSchema() {
|
||||
if (!db) throw new Error('Database not initialized');
|
||||
|
||||
// Categories (Groups)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS categories (
|
||||
id TEXT PRIMARY KEY, -- Composite key: sourceId:categoryId
|
||||
source_id INTEGER NOT NULL,
|
||||
category_id TEXT NOT NULL,
|
||||
type TEXT NOT NULL, -- 'live', 'movie', 'series'
|
||||
name TEXT NOT NULL,
|
||||
parent_id TEXT, -- For nested categories
|
||||
is_hidden INTEGER DEFAULT 0,
|
||||
data JSON -- Extra provider data
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_categories_source_type ON categories(source_id, type);
|
||||
`);
|
||||
|
||||
// Playlist Items (Channels, Movies, Series, Episodes)
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS playlist_items (
|
||||
id TEXT PRIMARY KEY, -- Composite key: sourceId:itemId
|
||||
source_id INTEGER NOT NULL,
|
||||
item_id TEXT NOT NULL, -- Original ID from provider
|
||||
type TEXT NOT NULL, -- 'live', 'movie', 'series', 'episode'
|
||||
name TEXT NOT NULL,
|
||||
category_id TEXT, -- maps to categories.category_id (not our composite id)
|
||||
parent_id TEXT, -- For episodes -> series_id
|
||||
|
||||
-- Common Media Fields
|
||||
stream_icon TEXT,
|
||||
stream_url TEXT, -- Direct link if available
|
||||
container_extension TEXT,
|
||||
|
||||
-- VOD/Series Specific
|
||||
rating REAL,
|
||||
year TEXT,
|
||||
added_at TEXT,
|
||||
|
||||
-- App State
|
||||
is_hidden INTEGER DEFAULT 0,
|
||||
is_favorite INTEGER DEFAULT 0,
|
||||
|
||||
data JSON -- Full original JSON object
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_items_source_type ON playlist_items(source_id, type);
|
||||
CREATE INDEX IF NOT EXISTS idx_items_category ON playlist_items(source_id, category_id);
|
||||
`);
|
||||
|
||||
// EPG Programs
|
||||
// Optimized for range queries
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS epg_programs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
channel_id TEXT NOT NULL, -- matches playlist_items.id if possible, or mapping key
|
||||
source_id INTEGER NOT NULL,
|
||||
start_time INTEGER NOT NULL, -- Unix timestamp (ms)
|
||||
end_time INTEGER NOT NULL, -- Unix timestamp (ms)
|
||||
title TEXT,
|
||||
description TEXT,
|
||||
data JSON
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_epg_channel_time ON epg_programs(channel_id, start_time, end_time);
|
||||
CREATE INDEX IF NOT EXISTS idx_epg_cleanup ON epg_programs(end_time); -- For deleting old programs
|
||||
`);
|
||||
|
||||
// Sync Status
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS sync_status (
|
||||
source_id INTEGER NOT NULL,
|
||||
type TEXT NOT NULL, -- 'live', 'vod', 'series', 'epg'
|
||||
last_sync INTEGER NOT NULL,
|
||||
status TEXT, -- 'success', 'error', 'syncing'
|
||||
error TEXT,
|
||||
PRIMARY KEY (source_id, type)
|
||||
);
|
||||
`);
|
||||
|
||||
console.log('[SQLite] Schema initialized');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDb,
|
||||
initSchema
|
||||
};
|
||||
Reference in New Issue
Block a user