Extend video catalog source metadata
This commit is contained in:
42
server/db.js
42
server/db.js
@@ -257,6 +257,7 @@ export async function initDb() {
|
||||
last_used_at INTEGER
|
||||
);
|
||||
`);
|
||||
await migrateVideoMeta();
|
||||
// Uploads shared from devices (PWA share target): who sent it, and whether it
|
||||
// is listed in everyone's search (admin uploads) or reachable only by link.
|
||||
for (const col of ['owner TEXT', 'listed INTEGER NOT NULL DEFAULT 1']) {
|
||||
@@ -284,6 +285,47 @@ export async function initDb() {
|
||||
}
|
||||
}
|
||||
|
||||
const YOUTUBE_ID = /^[\w-]{11}$/;
|
||||
const folded = value => String(value || '').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
|
||||
|
||||
// These columns were added after video_meta shipped. Keep startup migration
|
||||
// idempotent and page the backfill so a large catalogue never becomes one
|
||||
// unbounded JS allocation.
|
||||
export async function migrateVideoMeta({ pageSize = 500 } = {}) {
|
||||
for (const [name, type] of [['url', 'TEXT'], ['channel_id', 'TEXT'], ['channel_url', 'TEXT'], ['published', 'TEXT'], ['lang', 'TEXT']]) {
|
||||
try { await db.execute(`ALTER TABLE video_meta ADD COLUMN ${name} ${type}`); } catch { /* column already exists */ }
|
||||
}
|
||||
await db.execute('CREATE TABLE IF NOT EXISTS catalog_schema_migrations (version INTEGER PRIMARY KEY, applied_at INTEGER NOT NULL)');
|
||||
const done = await db.execute({ sql: 'SELECT 1 FROM catalog_schema_migrations WHERE version=1' });
|
||||
if (done.rows.length) return;
|
||||
let cursor = '';
|
||||
for (;;) {
|
||||
const rows = (await db.execute({
|
||||
sql: 'SELECT id,card,hay FROM video_meta WHERE id>? ORDER BY id LIMIT ?', args: [cursor, pageSize],
|
||||
})).rows;
|
||||
if (!rows.length) break;
|
||||
const updates = [];
|
||||
for (const row of rows) {
|
||||
cursor = row.id;
|
||||
let card = {};
|
||||
try { card = JSON.parse(row.card || '{}'); } catch { /* malformed legacy card */ }
|
||||
const url = YOUTUBE_ID.test(row.id) ? `https://www.youtube.com/watch?v=${row.id}` : null;
|
||||
const channelId = card.channelId || card.channel_id || null;
|
||||
const channelUrl = card.channelUrl || card.channel_url || null;
|
||||
const published = card.published || card.publishedAt || card.upload_date || null;
|
||||
const lang = card.lang || card.language || null;
|
||||
card = { ...card, url, channelId: channelId || '', channelUrl: channelUrl || '' };
|
||||
const hay = folded([card.title, card.channel, channelId, card.description,
|
||||
...(Array.isArray(card.tags) ? card.tags : []), ...(Array.isArray(card.categories) ? card.categories : [])].filter(Boolean).join(' '));
|
||||
updates.push({ sql: 'UPDATE video_meta SET card=?,url=?,channel_id=?,channel_url=?,published=?,lang=?,hay=? WHERE id=?',
|
||||
args: [JSON.stringify(card), url, channelId, channelUrl, published, lang, hay || folded(row.hay), row.id] });
|
||||
}
|
||||
await db.batch(updates, 'write');
|
||||
if (rows.length < pageSize) break;
|
||||
}
|
||||
await db.execute({ sql: 'INSERT OR IGNORE INTO catalog_schema_migrations(version,applied_at) VALUES(1,?)', args: [Date.now()] });
|
||||
}
|
||||
|
||||
// ---- Shared video notes (lyrics / chapters) ---------------------------------
|
||||
|
||||
function noteRow(r) {
|
||||
|
||||
Reference in New Issue
Block a user