Multi-tenant platform: per-streamer overlay/sender links + CI/CD
Some checks failed
CI/CD Pipeline / build-and-deploy (push) Failing after 2s
Some checks failed
CI/CD Pipeline / build-and-deploy (push) Failing after 2s
Streamers log in with Google on a new landing page and get a dashboard with two auto-generated, permanent links: one for their OBS/StreamLabs Browser Source, one to share with viewers. Messages are now scoped to the right streamer via Socket.IO rooms instead of broadcasting globally. Streamer records and tokens are persisted in SQLite (node:sqlite) so links survive restarts/redeploys. Also adds a Forgejo Actions pipeline mirroring t2sTelegramBot's: build, smoke-test, push to the local registry, then deploy to the prod host over SSH. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
7882db1f37
commit
9c91966730
14 changed files with 444 additions and 34 deletions
59
db.js
Normal file
59
db.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
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',
|
||||
created_at INTEGER NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
findStreamerByOverlayToken,
|
||||
findStreamerBySenderToken,
|
||||
getOrCreateStreamerByGoogle,
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue