jevstrudel.git / website / src / jev / parties.mjs
1// The live listening parties, for the listening tab (LiveParties.jsx), from
2// GET /jev/parties (worker/src/party.ts): each party's song, people, whether
3// its host is there and since when. A party whose host shows themselves
4// (the lobby's "show me here") is listed to join: its entry carries an id
5// the room answers with its name for (GET /jev/parties/<id>), and joining is
6// the ordinary guest join (`joinParty`, party.mjs), which plays the song
7// from this page's own build. An unlisted party is only described.
8import { joinParty, PARTIES_PATH } from './party.mjs';
9
10const ID = /^[0-9a-f]{64}$/;
11const SONG = /^[a-z0-9-]{1,64}\/[a-z0-9-]{1,64}$/;
12
13// 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}
24
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}
31
32// 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}