The live listening parties, for the listening tab (LiveParties.jsx), from
GET /jev/parties (worker/src/party.ts): each party's song, people, whether
its host is there and since when. A party whose host shows themselves
(the lobby's "show me here") is listed to join: its entry carries an id
the room answers with its name for (GET /jev/parties/<id>), and joining is
the ordinary guest join (joinParty, party.mjs), which plays the song
from this page's own build. An unlisted party is only described.
8import { joinParty, PARTIES_PATH } from './party.mjs';
Only the fields the directory sends, checked.
14export function partyOf(p) { 15 if (!p || typeof p !== 'object') return null; 16 return { 17 id: typeof p.id === 'string' && ID.test(p.id) ? p.id : null, 18 song: typeof p.song === 'string' && SONG.test(p.song) ? p.song : null, 19 people: Number.isInteger(p.people) && p.people > 0 ? p.people : 0, 20 host: p.host === true, 21 since: typeof p.since === 'number' ? p.since : null, 22 }; 23}
25export async function loadParties(fetcher = fetch) { 26 const res = await fetcher(PARTIES_PATH, { headers: { Accept: 'application/json' } }); 27 if (!res.ok) throw new Error(`the site answered ${res.status}`); 28 const body = await res.json(); 29 return (Array.isArray(body.parties) ? body.parties : []).map(partyOf).filter((p) => p && p.people > 0); 30}
Join a listed party: its room, from the room itself, then as a guest.
33export async function joinListed(id, fetcher = fetch, join = joinParty) { 34 if (!ID.test(id)) throw new Error('not a listed party'); 35 const res = await fetcher(`${PARTIES_PATH}/${id}`, { headers: { Accept: 'application/json' } }); 36 if (res.status === 404) throw new Error('this party is over, or no longer listed'); 37 if (!res.ok) throw new Error(`the site answered ${res.status}`); 38 const { room } = await res.json(); 39 if (typeof room !== 'string') throw new Error('the party did not say where it is'); 40 join(room); 41}