"""Lambda handler — updates 3CX queue routing based on who's on shift. Triggered by EventBridge at 8am ET daily and 5pm ET on weekends. Also invoked directly by the Slack bot for same-day shift changes. """ import json import logging import os from datetime import datetime from zoneinfo import ZoneInfo import shared.sentry_init # noqa: F401 from shared.ring_scheduler import update_queue_routing from shared.schedule import ( FALLBACK_EXTENSION, WEEKEND_DAYS, ShiftSchedule, determine_shift_type, ) from shared.secrets import get_secret logger = logging.getLogger() logger.setLevel(logging.INFO) EASTERN = ZoneInfo("America/New_York") def handler(event, context): now = datetime.now(EASTERN) current_hour = now.hour day_name = now.strftime("%A") logger.info("Running queue scheduler at %s", now.isoformat()) force = event.get("force", False) valid_hours = {8, 17} if day_name in WEEKEND_DAYS else {8} if not force and current_hour not in valid_hours: logger.info( "ET hour is %d on %s — skipping (wrong DST rule fired)", current_hour, day_name, ) return {"skipped": True} shift_type = determine_shift_type(now) if event.get("override_extension"): extension = event["override_extension"] else: schedule = ShiftSchedule() date_str = now.strftime("%Y-%m-%d") ext, _name, source = schedule.resolve_shift(date_str, day_name, shift_type) extension = ext if source != "available" else FALLBACK_EXTENSION secret_prefix = os.environ["TCX_SECRET_PREFIX"] try: result = update_queue_routing( extension=extension, queue_number=os.environ["QUEUE_NUMBER"], domain=get_secret(f"{secret_prefix}domain"), client_id=get_secret(f"{secret_prefix}client-id"), client_secret=get_secret(f"{secret_prefix}client-secret"), ) except Exception: logger.exception("Failed to update 3CX queue routing") return {"error": True, "date": now.strftime("%Y-%m-%d"), "day": day_name} result.update( { "date": now.strftime("%Y-%m-%d"), "day": day_name, "shift_type": shift_type, } ) logger.info("Result: %s", json.dumps(result)) return result