Skip to content

Commit a1f4f8c

Browse files
committed
acdbot: upcoming call report tweaks
1 parent adaa8a5 commit a1f4f8c

File tree

2 files changed

+81
-34
lines changed

2 files changed

+81
-34
lines changed

.github/ACDbot/scripts/upcoming_calls.py

Lines changed: 79 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import requests
2020
import sys
2121
from datetime import datetime, timedelta, timezone
22+
from dateutil import parser as date_parser
2223

2324
# Resolve paths relative to this script
2425
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -258,6 +259,38 @@ def find_expected_missing_calls(mapping, days_ahead=7):
258259
return missing
259260

260261

262+
def extract_date_from_title(title):
263+
"""Extract date from YouTube title using various common patterns.
264+
265+
Returns datetime object or None if no date found.
266+
"""
267+
if not title:
268+
return None
269+
270+
# Try various date patterns commonly found in stream titles
271+
patterns = [
272+
# "February 13, 2026" or "Feb 13, 2026"
273+
r'([A-Za-z]+)\s+(\d{1,2}),?\s+(\d{4})',
274+
# "2026-02-13" or "2026/02/13"
275+
r'(\d{4})[-/](\d{1,2})[-/](\d{1,2})',
276+
# "13 February 2026" or "13 Feb 2026"
277+
r'(\d{1,2})\s+([A-Za-z]+)\s+(\d{4})',
278+
]
279+
280+
for pattern in patterns:
281+
match = re.search(pattern, title)
282+
if match:
283+
try:
284+
# Try to parse the matched string
285+
date_str = match.group(0)
286+
dt = date_parser.parse(date_str, fuzzy=True)
287+
return dt.replace(tzinfo=timezone.utc)
288+
except (ValueError, TypeError):
289+
continue
290+
291+
return None
292+
293+
261294
def check_warnings(upcoming_calls, youtube_cache, youtube_enabled=True, youtube_error=None, missing_calls=None):
262295
"""Check for potential issues and return a list of warning strings."""
263296
warnings = []
@@ -306,6 +339,18 @@ def check_warnings(upcoming_calls, youtube_cache, youtube_enabled=True, youtube_
306339
f"{label}: YouTube scheduled time ({yt_time}) differs from meeting time ({call_time})"
307340
)
308341

342+
# Check: YouTube title contains a stale/mismatched date
343+
if yt["title"] and call["start_time"]:
344+
title_date = extract_date_from_title(yt["title"])
345+
if title_date:
346+
# Compare dates (ignoring time)
347+
title_date_only = title_date.date()
348+
call_date_only = call["start_time"].date()
349+
if title_date_only != call_date_only:
350+
warnings.append(
351+
f"{label}: YouTube title contains date {title_date.strftime('%B %d, %Y')} but meeting is scheduled for {call['start_time'].strftime('%B %d, %Y')} - STALE STREAM TITLE"
352+
)
353+
309354
# Check: stream not in "upcoming" status
310355
status = yt.get("broadcast_status", "unknown")
311356
if status == "none":
@@ -326,11 +371,27 @@ def build_markdown(upcoming_calls, zoom_details_cache, youtube_cache, days_ahead
326371
now_str = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
327372
lines = []
328373

374+
lines.append(f"#### Upcoming Calls — Next {days_ahead} Days")
375+
lines.append(f"*Generated: {now_str}*")
376+
377+
# Warnings at the top
378+
warnings = check_warnings(
379+
upcoming_calls, youtube_cache,
380+
youtube_enabled=youtube_enabled, youtube_error=youtube_error,
381+
missing_calls=missing_calls,
382+
)
383+
if warnings:
384+
lines.append("")
385+
lines.append("---")
386+
lines.append(f"**:warning: Warnings ({len(warnings)})**")
387+
for w in warnings:
388+
lines.append(f"- {w}")
389+
329390
if not upcoming_calls:
330-
lines.append(f"No upcoming calls found in the next {days_ahead} days (as of {now_str}).")
391+
lines.append("")
392+
lines.append("---")
393+
lines.append(f"No upcoming calls found in the next {days_ahead} days.")
331394
else:
332-
lines.append(f"#### Upcoming Calls — Next {days_ahead} Days")
333-
lines.append(f"*Generated: {now_str}*")
334395

335396
for call in upcoming_calls:
336397
# Title linked to issue
@@ -378,19 +439,6 @@ def build_markdown(upcoming_calls, zoom_details_cache, youtube_cache, days_ahead
378439
else:
379440
lines.append("- **YouTube:** No stream scheduled")
380441

381-
# Warnings
382-
warnings = check_warnings(
383-
upcoming_calls, youtube_cache,
384-
youtube_enabled=youtube_enabled, youtube_error=youtube_error,
385-
missing_calls=missing_calls,
386-
)
387-
if warnings:
388-
lines.append("")
389-
lines.append("---")
390-
lines.append(f"**:warning: Warnings ({len(warnings)})**")
391-
for w in warnings:
392-
lines.append(f"- {w}")
393-
394442
lines.append("")
395443
lines.append("---")
396444
lines.append(f"*{len(upcoming_calls)} call(s) in the next {days_ahead} days*")
@@ -421,15 +469,23 @@ def print_report(upcoming_calls, zoom_details_cache, youtube_cache, days_ahead=7
421469
"""Print a plain-text report to the terminal."""
422470
now_str = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
423471

472+
print(f"{'=' * 60}")
473+
print(f" UPCOMING CALLS - Next {days_ahead} Days")
474+
print(f" Generated: {now_str}")
475+
print(f"{'=' * 60}")
476+
477+
# Warnings at the top
478+
warnings = check_warnings(upcoming_calls, youtube_cache, youtube_enabled=youtube_enabled, youtube_error=youtube_error, missing_calls=missing_calls)
479+
if warnings:
480+
print(f"\n{'=' * 60}")
481+
print(f" WARNINGS ({len(warnings)})")
482+
print(f"{'=' * 60}")
483+
for w in warnings:
484+
print(f" ! {w}")
485+
424486
if not upcoming_calls:
425-
print(
426-
f"No upcoming calls found in the next {days_ahead} days (as of {now_str})."
427-
)
487+
print(f"\nNo upcoming calls found in the next {days_ahead} days.")
428488
else:
429-
print(f"{'=' * 60}")
430-
print(f" UPCOMING CALLS - Next {days_ahead} Days")
431-
print(f" Generated: {now_str}")
432-
print(f"{'=' * 60}")
433489

434490
for call in upcoming_calls:
435491
# Flag first occurrence of a new call series
@@ -475,15 +531,6 @@ def print_report(upcoming_calls, zoom_details_cache, youtube_cache, days_ahead=7
475531
else:
476532
print(f" YouTube: No stream scheduled")
477533

478-
# Warnings section
479-
warnings = check_warnings(upcoming_calls, youtube_cache, youtube_enabled=youtube_enabled, youtube_error=youtube_error, missing_calls=missing_calls)
480-
if warnings:
481-
print(f"\n{'=' * 60}")
482-
print(f" WARNINGS ({len(warnings)})")
483-
print(f"{'=' * 60}")
484-
for w in warnings:
485-
print(f" ! {w}")
486-
487534
print(f"\n{'=' * 60}")
488535
print(f" Total: {len(upcoming_calls)} call(s) in the next {days_ahead} days")
489536
print(f"{'=' * 60}")

.github/workflows/upcoming-calls.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Upcoming Calls Report
22

33
on:
44
schedule:
5-
- cron: '0 8 * * 5' # Every Friday at 08:00 UTC
5+
- cron: '0 8 * * *' # Daily at 08:00 UTC
66
workflow_dispatch: # Allow manual triggering from GitHub UI
77

88
jobs:
@@ -15,7 +15,7 @@ jobs:
1515
with:
1616
python-version: '3.10'
1717
- name: Install dependencies
18-
run: pip install requests pyyaml pytz google-api-python-client google-auth-oauthlib
18+
run: pip install requests pyyaml pytz google-api-python-client google-auth-oauthlib python-dateutil
1919
- name: Generate upcoming calls report
2020
env:
2121
ZOOM_CLIENT_ID: ${{ secrets.ZOOM_CLIENT_ID }}

0 commit comments

Comments
 (0)