Automating Boat Cleaning Dispatch and Calendar Synchronization Across Multiple Platforms
This session focused on building an automated boat cleaning dispatch system and establishing reliable calendar synchronization between Google Calendar and external booking platforms (GetMyBoat and Boatsetter). The work involved creating Python dispatch automation, integrating with Google Apps Script, and establishing bidirectional calendar syncing to prevent double-bookings and manual coordination overhead.
Problem Statement
Manual boat cleaning coordination was creating operational friction:
- Event notifications came through multiple channels (email, platform notifications, calendar holds)
- Cleaning crew dispatch required manual intervention and context-switching
- Calendar events needed to be synchronized across Google Calendar, GetMyBoat, and Boatsetter platforms without duplicating or conflicting entries
- No centralized system tracked cleaning task status or completion
Solution Architecture
Dispatch System
Created a new Python dispatch script at /Users/cb/Documents/repos/tools/dispatch_boat_cleaner.py that handles the core workflow:
- Input sources: Monitors incoming booking notifications from GetMyBoat and Boatsetter APIs
- Processing logic: Parses event details, extracts date/time, location, and vessel information
- Output: Generates formatted dispatch messages and sends to cleaning crew via configured notification channels
- Status tracking: Logs dispatch attempts to a persistent data store for audit trail
The script uses environment variables to load platform credentials (stored in repos.env) and integrates with both GetMyBoat and Boatsetter's APIs to poll for new bookings.
Calendar Synchronization Engine
Enhanced the existing Google Apps Script file at /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/CalendarSync.gs with bidirectional sync capabilities:
- Polling mechanism: Runs on a configurable interval (default 15 minutes) to check for new events on GetMyBoat and Boatsetter
- Event mapping: Translates platform-specific event formats to Google Calendar Event objects with consistent naming conventions
- Duplicate detection: Checks for existing calendar entries before adding to prevent duplicate calendar events
- Calendar holds: Creates "hold" events in Google Calendar for unconfirmed bookings to block time and prevent overbooking
- Sync status tracking: Maintains metadata about which events have been synced and their source platform
The CalendarSync script was deployed to Google Apps Script via clasp, with the project ID stored in /Users/cb/Documents/repos/sites/queenofsandiego.com/rady-shell-events/apps-script-replacement/.clasp.json.
Technical Implementation Details
Deployment Strategy
Created deployment scripts to automate the push/pull cycle:
/Users/cb/Documents/repos/tools/deploy_inbox_scraper.sh— Deploys the inbox scraper that monitors booking notifications- Push to GAS via
clasp pushafter validating syntax - Triggers are set at the GAS project level to run on time-based intervals
The deployment strategy avoids direct credential handling in scripts by using Google Apps Script's built-in authentication and authorization model, which leverages the Service Account credentials stored in the GAS project settings.
Inbox Scraper for Booking Notifications
Built /Users/cb/Documents/repos/tools/platform_inbox_scraper.py to monitor Gmail for incoming booking notifications:
- Connects to Gmail API using OAuth2 flow
- Queries for emails from GetMyBoat and Boatsetter notification addresses
- Parses email content to extract booking details (date, vessel, renter name, contact info)
- Logs parsed data to a structured JSON format for downstream processing
This scraper feeds directly into the dispatch system, ensuring no booking notification is missed.
Integration with Existing Systems
Calendar Event Management
Calendar events are created via AWS Lambda API endpoints integrated with the dashboard. The Lambda function accepts event payloads and calls the Google Calendar API directly:
- Endpoint: API Gateway v2 route configured in Lambda function environment
- Authentication: Dashboard tokens validated against credentials stored in
repos.env - Event creation: Calls the
add-calendar-eventaction with booking details - Hold events: Creates calendar holds for unconfirmed bookings (e.g., "Sea Scout Wednesday Hold — 7 instances") to block calendar time
Seven Sea Scout Wednesday holds were added to Google Calendar via this API, ensuring recurring weekly holds don't get manually re-entered.
Multi-Site Campaign Automation
While building the boat system, also created campaign scheduling infrastructure reusable across properties:
/Users/cb/Documents/repos/tools/campaign_scheduler.py— Core scheduler that coordinates multi-site campaigns/Users/cb/Documents/repos/tools/campaign_schedule.json— Configuration file defining campaign timing, templates, and target audiences/Users/cb/Documents/repos/tools/deploy_campaign_scheduler.sh— Deployment script for Lambda or cron-based execution
This infrastructure was deployed identically to /Users/cb/Documents/repos/sites/quickdumpnow.com/tools/ for multi-property consistency.
Key Technical Decisions
Why Google Apps Script for Calendar Sync
GAS was chosen over a standalone Lambda function because:
- Direct OAuth2 access to Google Calendar API without managing service accounts separately
- Native integration with Apps Script triggers (time-based, event-based)
- Simpler credential rotation and secret management
- Lower latency for calendar operations (no cold starts)
Polling vs. Webhooks
Implemented polling-based sync instead of webhooks because:
- GetMyBoat and Boatsetter don't reliably support webhook delivery
- Polling allows us to control sync frequency and batch operations
- Easier to implement retry logic and handle transient API failures
- No need to expose inbound endpoints or manage webhook secrets
Dispatch Script in Python
Used Python for the dispatch system (instead of JavaScript) because:
- Complex string parsing and data transformation logic is cleaner in Python
- Rich ecosystem of HTTP client libraries and retry/backoff utilities
- Environment variable handling and secret management patterns are well-established
- Easy to add machine learning or statistical analysis to dispatch optimization later
Infrastructure and Configuration
All scripts use environment variable injection for