From a9211150f87ff30a04832ffb58f9db3c5d2f910a Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Tue, 21 Jan 2025 15:46:34 +0000 Subject: [PATCH] Expose `livestreamId` from auditoria to the video stream widget --- config/default.yaml | 2 +- .../JsonScheduleBackend.test.ts.snap | 3 +++ .../backends/json/fosdem_democon.json | 6 +++--- .../PentabarfParser.test.ts.snap | 2 ++ src/backends/json/FosdemJsonScheduleLoader.ts | 21 +++++++++++++++++++ .../FosdemJsonSchedule.schema.json | 2 +- .../jsontypes/FosdemJsonSchedule.schema.d.ts | 2 +- src/web.ts | 1 + 8 files changed, 33 insertions(+), 6 deletions(-) diff --git a/config/default.yaml b/config/default.yaml index 727521b..e7b80fe 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -36,7 +36,7 @@ livestream: # The template for livestreams in auditorium rooms # Available variables: # id - The room ID/name (eg: "D.collab") - # sId - The room ID/name, but lowercase and only alphanumeric characters + # sId - [DEPRECATED] The room ID/name, but lowercase and only alphanumeric characters # are included (eg: "dcollab") # livestreamId - The livestream ID acquired from the conference schedule source. auditoriumUrl: "https://stream.example.org/conference/hls/{id}.m3u8" diff --git a/src/__tests__/backends/json/__snapshots__/JsonScheduleBackend.test.ts.snap b/src/__tests__/backends/json/__snapshots__/JsonScheduleBackend.test.ts.snap index 23c634e..82ce5bd 100644 --- a/src/__tests__/backends/json/__snapshots__/JsonScheduleBackend.test.ts.snap +++ b/src/__tests__/backends/json/__snapshots__/JsonScheduleBackend.test.ts.snap @@ -6,6 +6,7 @@ Map { "id": "5", "isPhysical": true, "kind": "auditorium", + "livestreamId": "c1111a", "name": "Open CAD/CAM devroom", "slug": "open_cad_cam", "talks": Map { @@ -50,6 +51,7 @@ Map { "id": "6", "isPhysical": true, "kind": "auditorium", + "livestreamId": "c4172", "name": "Self-Hosted Software devroom", "slug": "selfhosting", "talks": Map { @@ -115,6 +117,7 @@ Map { "id": "7", "isPhysical": true, "kind": "auditorium", + "livestreamId": "", "name": "Keynotes (TALKS NOT ANNOUNCED YET)", "slug": "key_notes", "talks": Map {}, diff --git a/src/__tests__/backends/json/fosdem_democon.json b/src/__tests__/backends/json/fosdem_democon.json index 6fe737c..4086247 100644 --- a/src/__tests__/backends/json/fosdem_democon.json +++ b/src/__tests__/backends/json/fosdem_democon.json @@ -26,7 +26,7 @@ "matrix_id": "@conal:example.org" } ], - "conference_room": "C.1.111", + "conference_room": "c1111a", "start_datetime": "2024-02-01T09:30:00+01:00", "duration": 30, "track": { @@ -55,7 +55,7 @@ "matrix_id": "@chloe:example.org" } ], - "conference_room": "C.4.172", + "conference_room": "c4172", "start_datetime": "2024-02-01T09:45:00+01:00", "duration": 45, "track": { @@ -84,7 +84,7 @@ "matrix_id": "@chloe:example.org" } ], - "conference_room": "C.4.172", + "conference_room": "c4172", "start_datetime": "2024-02-01T10:45:00+01:00", "duration": 45, "track": { diff --git a/src/__tests__/backends/penta/__snapshots__/PentabarfParser.test.ts.snap b/src/__tests__/backends/penta/__snapshots__/PentabarfParser.test.ts.snap index 8701cc7..8184533 100644 --- a/src/__tests__/backends/penta/__snapshots__/PentabarfParser.test.ts.snap +++ b/src/__tests__/backends/penta/__snapshots__/PentabarfParser.test.ts.snap @@ -6,6 +6,7 @@ exports[`parsing pentabarf XML: overview: auditoriums 1`] = ` "id": "A.01 (Someroom)", "isPhysical": false, "kind": "auditorium", + "livestreamId": "", "name": "A.01 (Someroom)", "slug": "a.01_someroom_", "talks": Map { @@ -50,6 +51,7 @@ exports[`parsing pentabarf XML: overview: conference 1`] = ` "id": "A.01 (Someroom)", "isPhysical": false, "kind": "auditorium", + "livestreamId": "", "name": "A.01 (Someroom)", "slug": "a.01_someroom_", "talks": Map { diff --git a/src/backends/json/FosdemJsonScheduleLoader.ts b/src/backends/json/FosdemJsonScheduleLoader.ts index ad40a68..47528b0 100644 --- a/src/backends/json/FosdemJsonScheduleLoader.ts +++ b/src/backends/json/FosdemJsonScheduleLoader.ts @@ -21,6 +21,7 @@ export class FosdemJsonScheduleLoader { const jsonSchedule = jsonDesc as FOSDEMSpecificJSONSchedule; this.auditoriums = new Map(); + const livestreamIdMapping = this.makeLivestreamIdMapping(jsonSchedule); for (let rawTrack of jsonSchedule.tracks) { // Tracks are now (since 2025) mapped 1:1 to auditoria @@ -29,6 +30,12 @@ export class FosdemJsonScheduleLoader { throw `Conflict in auditorium ID «${auditorium.id}»!`; } this.auditoriums.set(auditorium.id, auditorium); + + // Look up the livestream ID + let livestreamId = livestreamIdMapping.get(auditorium.id); + if (livestreamId !== undefined) { + auditorium.livestreamId = livestreamId; + } } this.talks = new Map(); @@ -57,6 +64,19 @@ export class FosdemJsonScheduleLoader { }; } + /** + * Returns a mapping from auditorium (track) ID to the conference_room for one of the talks in that track. + * + * Assumption: All talks in the same track are scheduled in the same room. (this is true for FOSDEM) + */ + private makeLivestreamIdMapping(sched: FOSDEMSpecificJSONSchedule): Map { + let out = new Map(); + for (let talk of sched.talks) { + out.set(talk.track.id.toString(), talk.conference_room); + } + return out; + } + private convertPerson(person: FOSDEMPerson): IPerson { if (! Object.values(Role).includes(person.event_role)) { throw new Error("unknown role: " + person.event_role); @@ -117,6 +137,7 @@ export class FosdemJsonScheduleLoader { talks: new Map(), // Hardcoded: FOSDEM is always physical now. isPhysical: true, + // This will be populated afterwards, with the value of one of the talks. livestreamId: '', }; } diff --git a/src/backends/json/jsonschemas/FosdemJsonSchedule.schema.json b/src/backends/json/jsonschemas/FosdemJsonSchedule.schema.json index c8478fc..0371202 100644 --- a/src/backends/json/jsonschemas/FosdemJsonSchedule.schema.json +++ b/src/backends/json/jsonschemas/FosdemJsonSchedule.schema.json @@ -104,7 +104,7 @@ }, "conference_room": { "type": "string", - "description": "Name of the physical (in real life) room that the talk is held in." + "description": "System name (not human-friendly) of the physical (in real life) room that the talk is held in. e.g. `ud2218a`" } }, "required": [ "event_id", "title", "start_datetime", "duration", "persons", "track", "conference_room" ] diff --git a/src/backends/json/jsontypes/FosdemJsonSchedule.schema.d.ts b/src/backends/json/jsontypes/FosdemJsonSchedule.schema.d.ts index acf8056..afa8cdf 100644 --- a/src/backends/json/jsontypes/FosdemJsonSchedule.schema.d.ts +++ b/src/backends/json/jsontypes/FosdemJsonSchedule.schema.d.ts @@ -49,7 +49,7 @@ export interface FOSDEMTalk { [k: string]: unknown; }; /** - * Name of the physical (in real life) room that the talk is held in. + * System name (not human-friendly) of the physical (in real life) room that the talk is held in. e.g. `ud2218a` */ conference_room: string; [k: string]: unknown; diff --git a/src/web.ts b/src/web.ts index 105351d..0674fc7 100644 --- a/src/web.ts +++ b/src/web.ts @@ -42,6 +42,7 @@ export function renderAuditoriumWidget(req: Request, res: Response, conference: // HACK for FOSDEM 2023 and FOSDEM 2024: transform auditorium IDs to the livestream ID // 1. 'K1.105A (Words)' -> 'k1.105a' // 2. 'k1.105a' -> 'k1105a' + // DEPRECATED — see livestreamId instead nowadays! let sid = audId.toLowerCase().replace(/\s+\(.+\)$/, '').replace(/[^a-z0-9]/g, ''); const streamUrl = template(auditoriumUrl, {