import fs from 'fs'; import path from 'path'; import { Database } from 'bun:sqlite'; import dotenv from 'dotenv'; dotenv.config({ path: '../.env' }); const jsonFolder = path.resolve(process.env.STREAM_JSON_LOCATION); const dbName = 'strimserve.db'; const db = new Database(dbName); // Map JSON attribute names to database column names // Not needed today, but makes schema changes easier const lookup = { id: 'id', date: 'stream_date', filename: 'filename', format: 'format', title: 'title', tags: 'tags', description: 'description', length_seconds: 'length_seconds', tracks: 'tracks' }; const existingRow = db.prepare('SELECT * FROM Stream WHERE id = ?'); // Overwrite differing streams without asking const shouldOverwrite = process.argv.includes('--overwrite'); // Process JSON files and insert data into Stream const files = fs.readdirSync(jsonFolder); console.log(`Found ${files.length} JSON file(s) in ${jsonFolder}.`); for (const file of files) { if (!file.endsWith('.json')) continue; if (file.endsWith('.sideload.json')) continue; const jsonString = fs.readFileSync(path.join(jsonFolder, file), 'utf8'); let jsonData = JSON.parse(jsonString); const sideloadPath = path.join(jsonFolder, file.slice(0, -5) + '.sideload.json'); if (fs.existsSync(sideloadPath)) { const sideloadData = JSON.parse(fs.readFileSync(sideloadPath)); jsonData = { ...jsonData, ...sideloadData }; } // A key with no column would otherwise reach the query as `undefined` const unknown = Object.keys(jsonData).filter((key) => !(key in lookup)); if (unknown.length > 0) console.log(`Ignored unknown key(s) in ${file}: ${unknown.join(', ')}.`); // Prepare attributes for insertion const fields = Object.entries(jsonData) .filter(([key]) => key in lookup) // Serialize value if array .map(([key, value]) => [lookup[key], Array.isArray(value) ? JSON.stringify(value) : value]); const row = existingRow.get(jsonData.id); if (row) { const changed = fields .filter(([column, value]) => String(row[column] ?? '') !== String(value ?? '')) .map(([column]) => column); if (changed.length === 0) { console.log(`Unchanged data for ID ${jsonData.id}.`); continue; } console.log(`ID ${jsonData.id} differs from the database in: ${changed.join(', ')}.`); if (!shouldOverwrite && !confirm(`Overwrite ID ${jsonData.id}?`)) { console.log(`Kept database version of ID ${jsonData.id}.`); continue; } } const columns = fields.map(([column]) => column); const sql = `INSERT OR REPLACE INTO Stream (${columns.join(', ')}) VALUES (${columns.map(() => '?').join(', ')})`; db.prepare(sql).run(...fields.map(([, value]) => value)); console.log(`Inserted data for ID ${jsonData.id}.`); }