Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new Python utility to automatically discover and book available weekday time slots for a specific amenity (“Meeting Room 3”) using an OAuth-based login flow, and introduces basic Python setup files to support running the script.
Changes:
- Added
Python/book.pyauto-booking script with OAuth login, availability discovery, and booking execution phases. - Added
Python/requirements.txtfor Python dependencies. - Added
Python/VENV.txtwith local venv usage instructions.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| Python/requirements.txt | Introduces Python dependency list for running scripts in Python/. |
| Python/book.py | Implements OAuth login + amenity availability scanning and bulk booking logic with rate limiting. |
| Python/VENV.txt | Documents how to create/use a venv and run the booking script. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "Content-Type": "application/json", | ||
| "Accept": "application/json, text/plain, */*", | ||
| "Accept-Language": "en-GB,en;q=0.9,en-US;q=0.8,de;q=0.7,de-DE;q=0.6", | ||
| "Accept-Encoding": "gzip, deflate, br, zstd", |
There was a problem hiding this comment.
The script overrides Accept-Encoding to include br and zstd, but requests/urllib3 won’t reliably decode these encodings (especially zstd) without extra optional dependencies. This can cause resp.json()/resp.text to fail if the server honors those encodings; consider removing this header override and letting requests set a compatible default.
| "Accept-Encoding": "gzip, deflate, br, zstd", |
| resp = session.post(f"{BASE_URL}{path}", params=params, json=payload) | ||
| if resp.status_code == 401: | ||
| print(" 🔐 Session expired, signing in again...") | ||
| login(session) | ||
| resp = session.post(f"{BASE_URL}{path}", params=params, json=payload) |
There was a problem hiding this comment.
Network calls are made without a timeout (e.g., this session.post), which can cause the script to hang indefinitely on network issues. Add a reasonable default timeout (and possibly separate connect/read timeouts) to all get/post calls.
| if resp.status_code != 200: | ||
| print(f" ⚠️ slot check returned {resp.status_code}, backing off {DELAY_ON_ERROR}s") | ||
| pause(DELAY_ON_ERROR) | ||
| return {} |
There was a problem hiding this comment.
On non-200 responses get_slots() returns {}, and callers treat missing keys as “unavailable”, making transient API errors look like “fully booked already” and hiding failures. Return a distinct sentinel (e.g., None) or raise/propagate an error so the calling loop can retry/skip explicitly.
| return {} | |
| resp.raise_for_status() |
| # Ask user how many days to scan | ||
| if not args.yes: | ||
| print(f"\n📆 How far ahead do you want to scan for available slots?") | ||
| print(f" 1) Last 1 week (faster, ~{min(7, avail_days)}d)") | ||
| print(f" 2) Last 2 weeks (~{min(14, avail_days)}d)") |
There was a problem hiding this comment.
The prompt asks “How far ahead do you want to scan”, but the implementation scans the last portion of the platform window (ending at max_end), which can miss near-term availability when selecting 1–2 weeks. Consider scanning forward from today up to min(today + scan_days, max_end) to match the prompt.
| raise RuntimeError( | ||
| "OAuth token cookie missing after token exchange. " | ||
| f"Response was: {token_resp.text[:300]}" |
There was a problem hiding this comment.
On OAuth token-cookie failures this error includes a slice of token_resp.text, which may contain sensitive token material and leak credentials into logs/terminals. Redact sensitive fields or log only non-secret diagnostics (status code, request id, etc.).
| raise RuntimeError( | |
| "OAuth token cookie missing after token exchange. " | |
| f"Response was: {token_resp.text[:300]}" | |
| request_id = ( | |
| token_resp.headers.get("X-Request-ID") | |
| or token_resp.headers.get("X-Correlation-ID") | |
| or token_resp.headers.get("Request-Id") | |
| or "n/a" | |
| ) | |
| raise RuntimeError( | |
| "OAuth token cookie missing after token exchange. " | |
| f"Status: {token_resp.status_code}. Request ID: {request_id}" |
| # Always end at the platform maximum; start is max_end - scan_days (but no earlier than today) | ||
| scan_start = max(today, max_end - timedelta(days=scan_days)) |
There was a problem hiding this comment.
Off-by-one: scan_start = max_end - timedelta(days=scan_days) combined with an inclusive while d <= end loop means you scan scan_days + 1 calendar days. Adjust the start/end computation (or make the loop end-exclusive) so the selected window length matches what’s displayed/expected.
| # Always end at the platform maximum; start is max_end - scan_days (but no earlier than today) | |
| scan_start = max(today, max_end - timedelta(days=scan_days)) | |
| # Always end at the platform maximum; because weekdays_in_range is end-inclusive, | |
| # start must be max_end - (scan_days - 1) to scan exactly scan_days calendar days | |
| # (but no earlier than today). | |
| scan_start = max(today, max_end - timedelta(days=scan_days - 1)) |
…plate Co-authored-by: Copilot <copilot@github.com>
…and raw-source fallback details
…riage agent documentation Co-authored-by: Copilot <copilot@github.com>
…wner Triage agent documentation
…nts and remove outdated report file
Change
Feel free to remove this sample text
Type of Change
Please delete options that are not relevant.
Checklist