Add host-approved party suggestions and live upvotes

This commit is contained in:
Jonathan Sykes
2026-10-03 14:52:10 +08:00
parent 75dbc468cc
commit d7721045fb
10 changed files with 101 additions and 3 deletions

View File

@@ -18,6 +18,7 @@
* link); the host resumes it with the secret it was given.
* ========================================================================== */
import { createDJQueue, changeDJQueue, queueSnapshot, takeDJVideo } from './party-dj.js';
import { randomBytes, randomInt, timingSafeEqual } from 'node:crypto';
const ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // no 0/O, 1/I
@@ -88,7 +89,7 @@ export function createPartyHub({ now = () => Date.now() } = {}) {
if (p && !same(p.secret, d.secret)) { ws.close(4003, 'not the host of this party'); return; }
if (!p) {
const code = newCode();
p = { code, secret: randomBytes(18).toString('base64url'), hostPid: d.pid, members: new Map(), state: null, chat: [], allowControl: false, hostOnline: true, hostLeftAt: 0 };
p = { code, secret: randomBytes(18).toString('base64url'), hostPid: d.pid, members: new Map(), state: null, chat: [], dj: createDJQueue(), allowControl: false, hostOnline: true, hostLeftAt: 0 };
parties.set(code, p);
}
p.hostPid = d.pid;
@@ -103,7 +104,7 @@ export function createPartyHub({ now = () => Date.now() } = {}) {
p.members.set(d.pid, { ws, pid: d.pid, name: d.name, voice: false, lastChat: 0 });
send(ws, {
type: 'hello', code: p.code, secret: d.role === 'host' ? p.secret : undefined, you: d.pid,
now: now(), members: members(p), state: p.state, chat: p.chat, allowControl: p.allowControl,
now: now(), members: members(p), state: p.state, chat: p.chat, dj: queueSnapshot(p.dj), allowControl: p.allowControl,
});
broadcast(p, { type: 'members', members: members(p), joined: d.name }, ws);
}
@@ -117,7 +118,10 @@ export function createPartyHub({ now = () => Date.now() } = {}) {
const me = p && p.members.get(d.pid);
if (!me || me.ws !== ws || !m || typeof m !== 'object') return;
const isHost = d.pid === p.hostPid;
if (m.type === 'state' && isHost) {
if (m.type === 'dj') {
if (m.action === 'take' && isHost) { const video = takeDJVideo(p.dj); send(ws, { type: 'dj-play', video }); if (video) broadcast(p, { type: 'dj', ...queueSnapshot(p.dj) }); }
else if (changeDJQueue(p.dj, m, me.pid, isHost)) broadcast(p, { type: 'dj', ...queueSnapshot(p.dj) });
} else if (m.type === 'state' && isHost) {
p.state = { ...(m.state || {}), ts: now() };
broadcast(p, { type: 'state', state: p.state }, ws);
} else if (m.type === 'settings' && isHost) {