Files
strimserve/db/update_db.js
T
2026-09-02 20:33:23 +02:00

81 lines
2.9 KiB
JavaScript

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}.`);
}