Files
sendewerk/scripts/seed.mjs
T
2026-10-21 21:05:57 +02:00

339 lines
8.7 KiB
JavaScript

import Database from 'better-sqlite3';
import { mkdirSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { getPaths } from './config.mjs';
export function seed(databasePath = getPaths().database) {
mkdirSync(path.dirname(databasePath), { recursive: true });
const database = new Database(databasePath);
database.pragma('foreign_keys = ON');
const seedDatabase = database.transaction(() => {
const replace = (table, columns, rows) => {
const placeholders = columns.map(() => '?').join(', ');
const update = columns
.filter((column) => column !== 'id')
.map((column) => `${column} = excluded.${column}`)
.join(', ');
const statement = database.prepare(
`INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})
ON CONFLICT(id) DO UPDATE SET ${update}`
);
for (const row of rows) statement.run(...row);
};
replace(
'section_categories',
['id', 'name', 'color', 'sort_order'],
[
['cat-jc', 'JC', '#67DDE8', 0],
['cat-reaction', 'Reaction', '#E7B957', 1],
['cat-game', 'Spiel', '#9B8AFB', 2]
]
);
replace(
'formats',
['id', 'name'],
[
['format-find', 'Fundstück'],
['format-talk', 'Gespräch'],
['format-quiz', 'Quiz']
]
);
replace(
'topics',
['id', 'name'],
[
['topic-gaming', 'Gaming'],
['topic-film', 'Film & Serien'],
['topic-internet', 'Netzkultur']
]
);
const timestamp = '2026-10-21T10:00:00.000Z';
replace(
'pieces',
[
'id',
'title',
'summary',
'format_id',
'status',
'duration_seconds',
'intro',
'moderation_notes',
'transition_text',
'presentation_text',
'created_at_utc',
'updated_at_utc'
],
[
[
'piece-console',
'Die kleine Konsole mit dem großen Dreh',
'Ein ungewöhnliches Handheld-Konzept sorgt für Diskussionsstoff.',
'format-find',
'ready',
480,
'Eine Kurbel, ein gelber Knopf und sehr viel Charme: Was macht kleine Hardware spannend?',
'Erst Formfaktor zeigen, dann über bewusst gesetzte Grenzen sprechen.',
'Von der kleinen Konsole geht es zur ganz großen Leinwand.',
'Weniger Leistung, mehr Idee.',
timestamp,
timestamp
],
[
'piece-effects',
'Warum praktische Effekte wieder auffallen',
'Neue Produktionen mischen Miniaturen, Masken und digitale Nacharbeit.',
'format-talk',
'ready',
720,
'Man sieht manchmal gerade deshalb weniger Trick, weil wieder mehr vor der Kamera passiert.',
'Beispiele vergleichen, nicht analog gegen digital ausspielen.',
'Nach so viel Handarbeit wird es spielerisch.',
'Wenn das Licht wirklich auf ein Modell fällt.',
timestamp,
timestamp
],
[
'piece-quiz',
'Drei Sounds, ein Spiel',
'Kurzes Audioquiz mit bekannten Inventar- und Menüklängen.',
'format-quiz',
'preparing',
600,
'Augen zu: Erkennt ihr das Spiel nur an seinem Inventar?',
'Drei Runden, Auflösung jeweils erst nach den Tipps.',
'Damit sind die Ohren warm für unser erstes Spiel.',
'Welches Spiel steckt hinter diesem Klang?',
timestamp,
timestamp
],
[
'piece-pixels',
'Pixelart, die nicht nostalgisch sein will',
'Wie moderne Spiele Pixel als Material statt als Rückblick einsetzen.',
'format-find',
'ready',
540,
'Pixel sind längst keine technische Notlösung mehr.',
'Großaufnahmen vorbereiten, drei Stilmittel benennen.',
'Genug Theorie, jetzt spielen wir selbst.',
'Pixel als bewusste Entscheidung.',
timestamp,
timestamp
],
[
'piece-inbox-link',
'Indie-Showcase nachhören',
'Ein Fundstück aus dem letzten Showcase, das noch eingeordnet werden muss.',
'format-find',
'inbox',
0,
'',
'',
'',
'',
timestamp,
timestamp
],
[
'piece-archive-demo',
'Controller mit eingebautem Bildschirm',
'Ein früheres Fundstück, das bewusst im Archiv liegt.',
'format-find',
'archived',
300,
'',
'',
'',
'',
timestamp,
timestamp
]
]
);
database
.prepare('UPDATE pieces SET research_text = ? WHERE id = ?')
.run(
'## Recherche\n\n- Herstellerangaben gegen unabhängige Tests prüfen\n- Fokus auf Bedienidee statt Leistungsdaten',
'piece-console'
);
database
.prepare('UPDATE pieces SET presentation_text = ? WHERE id = ?')
.run(
'## Weniger Leistung, mehr Idee\n\nDie Kurbel ist Teil des Spiels, nicht nur Dekoration.',
'piece-console'
);
database.prepare('DELETE FROM piece_topics WHERE piece_id LIKE ?').run('piece-%');
const addTopic = database.prepare(
'INSERT INTO piece_topics (piece_id, topic_id) VALUES (?, ?)'
);
for (const values of [
['piece-console', 'topic-gaming'],
['piece-effects', 'topic-film'],
['piece-quiz', 'topic-gaming'],
['piece-pixels', 'topic-gaming'],
['piece-pixels', 'topic-internet'],
['piece-inbox-link', 'topic-gaming'],
['piece-archive-demo', 'topic-gaming']
])
addTopic.run(...values);
database.prepare('DELETE FROM piece_category_suggestions WHERE piece_id LIKE ?').run('piece-%');
const addCategory = database.prepare(
'INSERT INTO piece_category_suggestions (piece_id, category_id) VALUES (?, ?)'
);
for (const values of [
['piece-console', 'cat-jc'],
['piece-effects', 'cat-reaction'],
['piece-quiz', 'cat-jc'],
['piece-pixels', 'cat-reaction'],
['piece-inbox-link', 'cat-reaction'],
['piece-archive-demo', 'cat-reaction']
])
addCategory.run(...values);
replace(
'piece_sources',
['id', 'piece_id', 'label', 'url', 'timecode_seconds', 'position'],
[
[
'source-console',
'piece-console',
'Herstellerseite',
'https://example.com/console',
null,
0
],
[
'source-effects',
'piece-effects',
'Werkstattbericht',
'https://example.com/effects',
95,
0
],
['source-pixels', 'piece-pixels', 'Galerie', 'https://example.com/pixels', null, 0],
[
'source-inbox-showcase',
'piece-inbox-link',
'Showcase-Aufzeichnung',
'https://example.com/showcase',
120,
0
]
]
);
replace(
'shows',
[
'id',
'title',
'starts_at_utc',
'twitch_title',
'announcement_text',
'status',
'created_at_utc',
'updated_at_utc'
],
[
[
'show-october',
'Herbstsendung: Kleine Welten',
'2026-10-23T18:00:00.000Z',
'Kleine Welten, große Ideen | heinzlive',
'Heute schauen wir auf Hardware mit Kurbel, handgemachte Filmtricks und Pixel mit Haltung.',
'ready',
timestamp,
timestamp
]
]
);
replace(
'show_sections',
['id', 'show_id', 'name', 'category_id', 'position', 'explicit_duration_seconds'],
[
['section-start', 'show-october', 'Ankommen & Warmwerden', 'cat-jc', 0, 300],
['section-stories', 'show-october', 'Kleine Welten', 'cat-reaction', 1, null],
['section-game', 'show-october', 'Spiel 1', 'cat-game', 2, 3600]
]
);
replace(
'piece_usages',
[
'id',
'show_section_id',
'original_piece_id',
'position',
'status',
'duration_seconds',
'title_snapshot',
'intro_snapshot',
'moderation_snapshot',
'transition_snapshot',
'presentation_snapshot',
'is_reserve'
],
[
[
'usage-console',
'section-stories',
'piece-console',
0,
'current',
480,
'Die kleine Konsole mit dem großen Dreh',
'Eine Kurbel, ein gelber Knopf und sehr viel Charme: Was macht kleine Hardware spannend?',
'Erst Formfaktor zeigen, dann über bewusst gesetzte Grenzen sprechen.',
'Von der kleinen Konsole geht es zur ganz großen Leinwand.',
'Weniger Leistung, mehr Idee.',
0
],
[
'usage-effects',
'section-stories',
'piece-effects',
1,
'open',
720,
'Warum praktische Effekte wieder auffallen',
'Man sieht manchmal gerade deshalb weniger Trick, weil wieder mehr vor der Kamera passiert.',
'Beispiele vergleichen, nicht analog gegen digital ausspielen.',
'Nach so viel Handarbeit wird es spielerisch.',
'Wenn das Licht wirklich auf ein Modell fällt.',
0
],
[
'usage-reserve',
'section-stories',
'piece-pixels',
2,
'open',
540,
'Pixelart, die nicht nostalgisch sein will',
'Pixel sind längst keine technische Notlösung mehr.',
'Großaufnahmen vorbereiten, drei Stilmittel benennen.',
'Genug Theorie, jetzt spielen wir selbst.',
'Pixel als bewusste Entscheidung.',
1
]
]
);
});
seedDatabase();
database.close();
console.log(`Example data ready: ${databasePath}`);
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
seed();
}