Add streamer dashboard stats; fix TTS overlap race properly
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 30s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 30s
Dashboard now shows unique visitors (via sender link), total messages, and unique senders per streamer, tracked via new viewer_visits/messages tables. The previous overlay TTS-overlap fix had a race: audio not having arrived yet was treated the same as "no audio at all", letting the queue advance before slow-to-synthesize audio (e.g. a long question) ever started playing. Now "not arrived yet" is explicitly distinct from "finished playing", with a grace-period fallback for genuine TTS failures. Also drop the hardcoded AI name from ai-prompt.txt since it's now injected dynamically from the streamer's configured ai_name.
This commit is contained in:
parent
ec6d8c4cfe
commit
b669c2d0b7
5 changed files with 114 additions and 9 deletions
42
db.js
42
db.js
|
|
@ -30,6 +30,21 @@ db.exec(`
|
|||
updated_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (streamer_id, google_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS viewer_visits (
|
||||
streamer_id INTEGER NOT NULL,
|
||||
google_id TEXT NOT NULL,
|
||||
first_seen_at INTEGER NOT NULL,
|
||||
last_seen_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (streamer_id, google_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
streamer_id INTEGER NOT NULL,
|
||||
google_id TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL
|
||||
);
|
||||
`);
|
||||
|
||||
// Idempotent migration for databases created before display_duration_seconds existed.
|
||||
|
|
@ -94,6 +109,30 @@ function updateAiName(streamerId, aiName) {
|
|||
db.prepare('UPDATE streamers SET ai_name = ? WHERE id = ?').run(aiName, streamerId);
|
||||
}
|
||||
|
||||
function recordVisit(streamerId, googleId) {
|
||||
const now = Date.now();
|
||||
db.prepare(
|
||||
`INSERT INTO viewer_visits (streamer_id, google_id, first_seen_at, last_seen_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(streamer_id, google_id) DO UPDATE SET last_seen_at = excluded.last_seen_at`
|
||||
).run(streamerId, googleId, now, now);
|
||||
}
|
||||
|
||||
function recordMessage(streamerId, googleId) {
|
||||
db.prepare(
|
||||
'INSERT INTO messages (streamer_id, google_id, created_at) VALUES (?, ?, ?)'
|
||||
).run(streamerId, googleId, Date.now());
|
||||
}
|
||||
|
||||
function getStreamerStats(streamerId) {
|
||||
const visitors = db.prepare('SELECT COUNT(*) AS c FROM viewer_visits WHERE streamer_id = ?').get(streamerId).c;
|
||||
const messages = db.prepare('SELECT COUNT(*) AS c FROM messages WHERE streamer_id = ?').get(streamerId).c;
|
||||
const uniqueSenders = db
|
||||
.prepare('SELECT COUNT(DISTINCT google_id) AS c FROM messages WHERE streamer_id = ?')
|
||||
.get(streamerId).c;
|
||||
return { visitors, messages, uniqueSenders };
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
findStreamerByOverlayToken,
|
||||
findStreamerBySenderToken,
|
||||
|
|
@ -102,4 +141,7 @@ module.exports = {
|
|||
setViewerName,
|
||||
updateDisplayDuration,
|
||||
updateAiName,
|
||||
recordVisit,
|
||||
recordMessage,
|
||||
getStreamerStats,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue