Automating Event Calendar Synchronization and Cleaning Service Dispatch: Infrastructure Refactor for Multi-Site Operations
What Was Done
This session tackled a critical infrastructure gap: replacing deprecated Google Apps Script (GAS) automation with Lambda-based calendar synchronization and implementing a dispatch system for recurring cleaning services across multiple event venues. The work involved:
- Migrating calendar event management from Google Apps Script to AWS Lambda with API Gateway endpoints
- Implementing a boat platform credential mapping system for multi-vendor integration (GetMyBoat, Boatsetter)
- Building a Python-based dispatch scheduler for cleaning service coordination
- Establishing calendar hold management for recurring sea scout activities
Technical Architecture Changes
Calendar Synchronization Infrastructure
The primary component is located at /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/CalendarSync.gs. This Google Apps Script handles bi-directional calendar synchronization with the following workflow:
- Event Polling: Executes on a time-based trigger to periodically check for new events in the source calendar
- Calendar ID Mapping: Maintains references to multiple Google Calendar IDs for different event types (birthday parties, afternoon sessions, scout holds)
- Notification System: Sends email notifications via Gmail API to stakeholders when calendar changes occur
The script was updated to correct polling intervals and email delivery mechanisms. Rather than relying on the deprecated sendEmail() method in certain contexts, we now route through explicitly configured Gmail API calls with proper error handling.
Lambda-Based Calendar API
The Lambda function at /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/shipcaptaincrew/lambda_function.py exposes calendar operations via API Gateway. The endpoint structure supports:
add-calendar-event— Creates events with title, start time, end time, and optional descriptionlist-calendar-events— Retrieves events within a date range for dashboard displayupdate-calendar-event— Modifies existing event details
Authentication is managed through API Gateway with environment variable-based token validation. The Lambda function reads Google Calendar API credentials from repos.env and uses service account authentication to bypass OAuth flows in automated contexts.
Cleaning Service Dispatch System
A new Python module at /Users/cb/Documents/repos/tools/dispatch_boat_cleaner.py manages recurring cleaning task creation. The system:
- Reads a JSON schedule from
/Users/cb/Documents/repos/tools/campaign_schedule.json - Generates dispatch commands for boat platform APIs (GetMyBoat, Boatsetter)
- Logs task status to CloudWatch for monitoring and audit trails
- Integrates with the dashboard via the Lambda API to create "hold" calendar events that block off cleaning windows
The dispatch script runs as a scheduled Lambda function with a cron-based trigger. This replaces manual email-based task creation with deterministic, auditable automation.
Multi-Site Campaign Infrastructure
Two parallel marketing automation systems were established:
Queen of San Diego Campaign (Rady Shell Events)
- Inbox Scraper:
/Users/cb/Documents/repos/tools/platform_inbox_scraper.pypolls event booking platforms for incoming inquiries - Email Templates: Located in
/Users/cb/Documents/repos/tools/templates/(rady_shell_blast1.html, rady_shell_blast2.html) - Campaign Scheduler:
/Users/cb/Documents/repos/tools/campaign_scheduler.pyorchestrates template rendering and SES delivery - Deployment: Shell scripts (
deploy_inbox_scraper.sh,deploy_campaign_scheduler.sh) handle CloudFormation stack updates and Lambda code refreshes
QuickDumpNow Consumer Outreach
- Blast System:
/Users/cb/Documents/repos/sites/quickdumpnow.com/tools/qdn_consumer_blast.pysends bulk marketing emails with template variants - Analytics:
qdn_stats.pytracks open rates, click-through rates, and unsubscribe events by parsing SES bounce/complaint notifications - Compliance: Unsubscribe landing page at
/Users/cb/Documents/repos/sites/quickdumpnow.com/unsubscribe/index.htmlintegrates with DynamoDB for preference management
Key Technical Decisions
Lambda vs. Google Apps Script
We chose to move calendar operations to Lambda because:
- GAS quota limits were being exceeded during peak event seasons
- Lambda offers better integration with AWS infrastructure (CloudWatch, IAM, VPC)
- Python provides stronger typing and testing frameworks than GAS's JavaScript variant
- API Gateway allows external systems (dashboard, third-party integrations) to trigger calendar updates without GAS authentication overhead
Email Delivery Routing
SES (Simple Email Service) was standardized for transactional emails across all systems rather than mixing Gmail API and SES. This provides:
- Unified bounce/complaint tracking
- Better IP reputation management with warm-up schedules
- Template version control via CloudFormation
- Cost predictability with per-message pricing
Credential Management Pattern
Platform credentials (GetMyBoat, Boatsetter API keys) are stored in a structured format within repos.env rather than scattered across individual script files. The dispatch system reads these at runtime via environment variable substitution, enabling:
- Credential rotation without code changes
- Easy audit logging of which systems accessed which platforms
- Staging/production credential switching via deployment environment
Operational Integration Points
The dashboard at /tmp/dashboard_index.html now displays:
- Calendar holds created by the dispatch system (visual blocking)
- Inbox scraper results with unread inquiry counts
- Campaign scheduler status (queued, sent, bounced)
- Real-time Lambda invocation metrics from CloudWatch
Team members can trigger calendar updates directly via the dashboard's API interface, which validates requests against the token stored in repos.env before forwarding to Lambda.
What's Next
Immediate follow-ups:
- Implement dead-letter queue (DLQ) handling for failed calendar API requests to prevent silent failures
- Add CloudWatch alarms for inbox scraper timeout events (threshold: >5