```html

Replacing Google Apps Script with Lambda: Automating Boat Platform Calendar Sync and Dispatch Operations

Over the past development session, we decommissioned a dependency on Google Apps Script (GAS) for calendar synchronization and event management across multiple boat rental platforms, replacing it with AWS Lambda functions and a Python-based dispatch automation system. This post details the architectural decisions, implementation specifics, and integration patterns that enable real-time calendar sync and operational task automation.

The Problem: Multiple Calendar Sources, Single Operational Truth

The Queen of San Diego operation manages bookings across multiple boat rental platforms (GetMyBoat, Boatsetter) and internal calendar systems. Previously, a Google Apps Script in /repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/CalendarSync.gs handled periodic polling of these platforms and syncing to Google Calendar. This approach had several limitations:

  • GAS polling intervals created delays in event visibility
  • Credentials were scattered across environment configurations
  • No structured logging or error recovery mechanism
  • Manual deployment required stopping/starting polling scripts

Technical Architecture: Lambda-Based Calendar Sync

The replacement system uses AWS Lambda as the primary event synchronization engine, triggered via API Gateway v2 endpoints. The Lambda function exposes multiple action handlers for different operations:

  • add-calendar-event: Creates events in Google Calendar with full metadata
  • list-calendar-events: Queries a date range and returns structured event data
  • sync-platform-events: Polls GetMyBoat/Boatsetter APIs and creates calendar entries

Key files involved:

  • /repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/CalendarSync.gs — Legacy GAS file (being phased out)
  • Lambda function (deployed via CloudFormation stack) — Primary sync engine
  • repos.env — Contains Google Calendar API credentials and platform API keys

Implementation: Adding Calendar Events via Lambda API

During this session, we added 7 Sea Scout Wednesday hold events directly through the Lambda API. The process demonstrates the current workflow:

POST /calendar/add-calendar-event
Content-Type: application/json
Authorization: Bearer {DASHBOARD_TOKEN}

{
  "title": "Sea Scout Wednesday Hold",
  "start": "2025-05-07T18:00:00Z",
  "end": "2025-05-07T20:00:00Z",
  "description": "Reserved hold for Sea Scout troop activity"
}

The Lambda function validates the auth token against the dashboard token stored in repos.env, then calls the Google Calendar API using credentials configured in the Lambda environment. This eliminates the need for GAS polling and provides immediate event visibility.

Dispatch Automation: Python Scripts for Operational Tasks

Beyond calendar sync, we implemented Python-based automation for operational dispatching. Specifically:

Boat Cleaner Dispatch System (/repos/tools/dispatch_boat_cleaner.py):

  • Monitors calendar for completed bookings
  • Triggers cleaning task creation in operational workflow
  • Notifies cleaning service providers (integrated with Twilio for SMS notifications)
  • Tracks cleaning status and completion in dashboard cards

Campaign Scheduler (/repos/tools/campaign_scheduler.py with /repos/tools/campaign_schedule.json):

  • Manages email blast scheduling for Queen of San Diego marketing
  • Template files stored in /repos/tools/templates/ (rady_shell_blast1.html, rady_shell_blast2.html)
  • Uses cron-like scheduling for automated campaign deployment
  • Integrates with SES for email delivery

Platform Inbox Scraper (/repos/tools/platform_inbox_scraper.py with deployment script /repos/tools/deploy_inbox_scraper.sh):

  • Polls GetMyBoat and Boatsetter inboxes for customer messages
  • Parses email content and creates dashboard notifications
  • Maintains thread state to avoid duplicate processing
  • Runs on scheduled Lambda execution (currently set to 5-minute intervals)

Key Architectural Decisions

Why Lambda over GAS? Lambda provides native AWS integration (CloudWatch logs, IAM roles, VPC access), better error handling and retry logic, and scales automatically. GAS's polling model created unnecessary API call overhead and lacked structured observability.

Why Python for automation scripts? Python offers better library ecosystems for platform APIs (boto3 for AWS, requests for REST APIs) and easier integration with deployment pipelines. Scripts can be containerized and deployed to Lambda or EC2 without modification.

API Gateway v2 instead of REST API? HTTP APIs (v2) offer lower latency, simpler routing rules, and reduced costs. For dashboard operations with JSON payloads and token-based auth, the additional features of REST APIs weren't necessary.

Credential Management: All platform credentials (GetMyBoat, Boatsetter, Google Calendar API) are stored in repos.env and injected into Lambda via environment variables at deployment time. This follows the 12-factor app principle and allows credential rotation without code changes.

Integration with Existing Systems

The new dispatch system integrates with the existing dashboard system:

  • Calendar events are queried and displayed on the main dashboard index
  • Dispatch tasks create dashboard cards with action items for operations staff
  • Email notifications (via SES) maintain communication with stakeholders (Carole, CB, FancyHands contacts)
  • CloudWatch logs track all dispatch operations for audit and debugging

For the Queen of San Diego events (carole.dangerouscentaur.com), the dispatch system creates task cards for catering coordination, boat cleaning, and guest communication — all triggered automatically from calendar changes.

What's Next

Future improvements to this system:

  • Migrate remaining GAS polling logic into Lambda (currently in CalendarSync.gs)
  • Implement webhook subscriptions to GetMyBoat/Boatsetter APIs instead of polling for real-time sync
  • Add Slack notifications to dispatch alerts (using Slack API)
  • Build analytics dashboard to track dispatch SLAs and booking-to-cleaning time
  • Containerize Python scripts and deploy to ECS for better resource isolation

The current system successfully removes the GAS dependency while providing faster event synchronization, better error handling, and operational transparency through structured logging and dashboard integration.

```