All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 30s
Streamer dashboard gains an editable AI assistant name (default "Альтушка Ирина"), stored per-streamer and used for the overlay label, TTS intro, and DeepSeek system prompt. Also fixes a bug where a long message's TTS audio could still be playing when the next queued message started its own audio — the overlay queue now waits for the current audio to actually finish (not just the configured display duration) before advancing.
105 lines
3.6 KiB
JavaScript
105 lines
3.6 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
const { DatabaseSync } = require('node:sqlite');
|
|
|
|
const DB_PATH = process.env.DB_PATH || path.join(__dirname, 'data', 'app.db');
|
|
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
|
|
|
|
const db = new DatabaseSync(DB_PATH);
|
|
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS streamers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
google_id TEXT UNIQUE NOT NULL,
|
|
email TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
picture TEXT,
|
|
overlay_token TEXT UNIQUE NOT NULL,
|
|
sender_token TEXT UNIQUE NOT NULL,
|
|
tts_voice TEXT NOT NULL DEFAULT 'ru-RU-DmitryNeural',
|
|
display_duration_seconds INTEGER NOT NULL DEFAULT 10,
|
|
ai_name TEXT NOT NULL DEFAULT 'Альтушка Ирина',
|
|
created_at INTEGER NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS viewer_names (
|
|
streamer_id INTEGER NOT NULL,
|
|
google_id TEXT NOT NULL,
|
|
display_name TEXT NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
PRIMARY KEY (streamer_id, google_id)
|
|
);
|
|
`);
|
|
|
|
// Idempotent migration for databases created before display_duration_seconds existed.
|
|
const existingColumns = db.prepare('PRAGMA table_info(streamers)').all().map((c) => c.name);
|
|
if (!existingColumns.includes('display_duration_seconds')) {
|
|
db.exec('ALTER TABLE streamers ADD COLUMN display_duration_seconds INTEGER NOT NULL DEFAULT 10');
|
|
}
|
|
if (!existingColumns.includes('ai_name')) {
|
|
db.exec("ALTER TABLE streamers ADD COLUMN ai_name TEXT NOT NULL DEFAULT 'Альтушка Ирина'");
|
|
}
|
|
|
|
function generateToken() {
|
|
return crypto.randomBytes(16).toString('hex');
|
|
}
|
|
|
|
function findStreamerByGoogleId(googleId) {
|
|
return db.prepare('SELECT * FROM streamers WHERE google_id = ?').get(googleId);
|
|
}
|
|
|
|
function findStreamerByOverlayToken(token) {
|
|
return db.prepare('SELECT * FROM streamers WHERE overlay_token = ?').get(token);
|
|
}
|
|
|
|
function findStreamerBySenderToken(token) {
|
|
return db.prepare('SELECT * FROM streamers WHERE sender_token = ?').get(token);
|
|
}
|
|
|
|
function createStreamer({ googleId, email, name, picture }) {
|
|
const overlayToken = generateToken();
|
|
const senderToken = generateToken();
|
|
db.prepare(
|
|
`INSERT INTO streamers (google_id, email, name, picture, overlay_token, sender_token, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
|
).run(googleId, email, name, picture || null, overlayToken, senderToken, Date.now());
|
|
return findStreamerByGoogleId(googleId);
|
|
}
|
|
|
|
function getOrCreateStreamerByGoogle({ googleId, email, name, picture }) {
|
|
return findStreamerByGoogleId(googleId) || createStreamer({ googleId, email, name, picture });
|
|
}
|
|
|
|
function getViewerName(streamerId, googleId) {
|
|
const row = db
|
|
.prepare('SELECT display_name FROM viewer_names WHERE streamer_id = ? AND google_id = ?')
|
|
.get(streamerId, googleId);
|
|
return row ? row.display_name : null;
|
|
}
|
|
|
|
function setViewerName(streamerId, googleId, displayName) {
|
|
db.prepare(
|
|
`INSERT INTO viewer_names (streamer_id, google_id, display_name, updated_at)
|
|
VALUES (?, ?, ?, ?)
|
|
ON CONFLICT(streamer_id, google_id) DO UPDATE SET display_name = excluded.display_name, updated_at = excluded.updated_at`
|
|
).run(streamerId, googleId, displayName, Date.now());
|
|
}
|
|
|
|
function updateDisplayDuration(streamerId, seconds) {
|
|
db.prepare('UPDATE streamers SET display_duration_seconds = ? WHERE id = ?').run(seconds, streamerId);
|
|
}
|
|
|
|
function updateAiName(streamerId, aiName) {
|
|
db.prepare('UPDATE streamers SET ai_name = ? WHERE id = ?').run(aiName, streamerId);
|
|
}
|
|
|
|
module.exports = {
|
|
findStreamerByOverlayToken,
|
|
findStreamerBySenderToken,
|
|
getOrCreateStreamerByGoogle,
|
|
getViewerName,
|
|
setViewerName,
|
|
updateDisplayDuration,
|
|
updateAiName,
|
|
};
|