Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions src/zoom-recaps-to-slack/build-candidates.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Pick the one meeting to post this run: the newest UNPOSTED occurrence of any configured meeting
// (on a webhook run, of the triggering meeting only) whose summary is ready to post (see readyToPost). An occurrence with nothing to post - a room started
// Pick the one meeting to post this run: the newest UNPOSTED occurrence from the last 48 hours of any
// configured meeting (on a webhook run, the triggering occurrence only) whose summary is ready to post
// (see readyToPost). An occurrence with nothing to post - a room started
// and stopped in seconds, a summary Zoom never generated, a failed fetch - is skipped, never allowed to
// block the occurrences behind it. Calendar guardrail: a meeting headed for a PUBLIC channel
// must match a scheduled public-calendar event (same Zoom meeting id + weekday/time) - this stops a
Expand Down Expand Up @@ -52,14 +53,17 @@ try { trigger = $('Verify Zoom').first().json; } catch (e) { trigger = null; }
const triggerId = trigger && trigger.meetingId ? String(trigger.meetingId) : '';
const triggerUuid = trigger && trigger.meetingUuid ? String(trigger.meetingUuid) : '';

// Every unposted occurrence of a configured meeting, newest first.
let eligible = all
// Zoom's summaries list ignores the date window and returns back to 2024, so only a meeting that
// started within the last 48 hours is ever a candidate: an older unposted one is history, not news.
const cutoff = Date.now() - 48 * 60 * 60 * 1000;
// Every recent unposted occurrence of a configured meeting, newest first. A webhook run considers only
// the exact occurrence that fired it - if that one is already posted or not ready, the run ends with
// nothing rather than falling back to another occurrence.
const eligible = all
.filter(s => new Date(s.meeting_start_time).getTime() >= cutoff)
.filter(s => config[String(s.meeting_id)] && !posted.has(s.meeting_uuid))
.filter(s => !triggerId || String(s.meeting_id) === triggerId)
.filter(s => !triggerId || (String(s.meeting_id) === triggerId && (!triggerUuid || s.meeting_uuid === triggerUuid)))
.sort((a, b) => new Date(b.meeting_start_time) - new Date(a.meeting_start_time));
// Prefer the exact occurrence that triggered the webhook; if the list doesn't show it yet, fall back to
// the newest unposted occurrence of the same meeting.
if (triggerUuid && eligible.some(s => s.meeting_uuid === triggerUuid)) eligible = eligible.filter(s => s.meeting_uuid === triggerUuid);

// Same test as the Gate (content present, summary not still being refined), asked here so an
// occurrence that fails it is passed over instead of ending the run. Any fetch error counts as not ready.
Expand Down
Loading