A Flask-based web application that monitors Google Calendar events and sends instant notifications to Telegram using webhooks. The system uses Google Calendar's push notification API to deliver real-time alerts when events are created, updated, or deleted.
- Real-time Notifications: Uses Google Calendar webhooks for instant event notifications (no polling delays)
- Multiple Calendar Support: Monitor multiple Google Calendars simultaneously
- Telegram Integration: Send notifications to Telegram groups with topic support
- Web Dashboard: Easy-to-use interface for configuration and monitoring
- Automatic Webhook Renewal: Automatically renews webhook subscriptions before they expire (every 6 days)
- Calendar Statistics: View event activity statistics for the last 30 days
- Rate-Limiting Protection: Prevents Telegram flooding with queued message delivery (~1 msg/2 sec)
- Initial Sync Suppression: Silently stores past events on first scan to prevent notification floods on restart
This application uses Google Calendar's push notifications API rather than polling. When you add, modify, or delete calendar events, Google instantly sends a notification to your webhook endpoint, which then forwards the notification to Telegram.
Important Design Decision: The system uses webhooks as the primary notification mechanism. A scheduler runs only to renew webhook channels every 6 days (Google Calendar webhooks expire after 7 days). There is NO polling scheduler - all notifications are event-driven.
- Flask Web Application (
app.py): Main application with routes and initialization - Google Calendar Webhook Handler (
google_calendar_webhook.py): Manages webhook subscriptions and processes incoming notifications - Google Connector (
google_connector.py): Interfaces with Replit's Google Calendar connector for OAuth - Calendar Monitor (
calendar_monitor.py): Fetches calendar data and detects changes - Telegram Notifier (
telegram_notifier.py): Sends formatted messages to Telegram - Notification Dispatcher (
notification_dispatcher.py): Queues and dispatches notifications with rate limiting - Database Models (
models.py): SQLAlchemy models for settings, events, and notification queue
- A Replit account
- A Google account with Calendar access
- A Telegram bot token (get it from @BotFather)
- A Telegram group or supergroup
- Go to replit.com/new
- Click "Import from GitHub"
- Enter your repository URL
- Replit will automatically detect it's a Python/Flask application
- In your Repl, click the "Tools" section in the left sidebar
- Find and add the "Google Calendar" connector
- Click "Connect" and authenticate with your Google account
- Grant the necessary permissions (read-only calendar access)
Important: The Google Calendar connector must be configured for the application to work. Without it, webhook setup will fail.
The application uses PostgreSQL in production. Replit will automatically provision a database when you deploy.
Optional environment variable:
SESSION_SECRET: Flask session secret (auto-generated if not provided)
- Run the application (it will start automatically)
- Open the web interface
- Navigate to "Settings"
- Enter your Telegram configuration:
- Bot Token: Get from @BotFather
- Chat ID: Your Telegram group's chat ID (use @userinfobot to find it)
- Topic Mappings (optional): Map calendar names to Telegram topic IDs in JSON format
Example topic mappings:
{
"Work Calendar": 123,
"Personal": 456
}Critical for Webhooks: You MUST deploy your application for webhooks to work reliably!
- Click the "Deploy" button in Replit
- Choose your deployment tier:
- Reserved VM (recommended): Always-on, consistent performance
- Autoscale: Scales based on traffic
- Configure deployment settings (build/run commands are pre-configured)
- Click "Deploy"
Why deployment is required:
- Development Repls go to sleep after inactivity
- When asleep, Google can't reach your webhook endpoint
- Missed webhook notifications = no Telegram alerts
- Deployed apps run 24/7 and receive all webhook notifications
After deployment, your webhook URL will be: https://<your-deployment-url>/webhook/google-calendar
- Check the console logs for webhook setup messages:
β Created watch channel for <calendar> (expires ...) - Add a test event to one of your monitored calendars
- You should receive a Telegram notification within seconds
- Check the logs for incoming webhook notifications:
π₯ Received Google Calendar webhook notification
- Check if deployed: Development Repls that sleep won't receive webhooks
- Verify webhook setup: Look for "β Created watch channel" messages in logs
- Test the webhook endpoint: Visit
https://<your-url>/webhook/google-calendar- should return JSON - Check Telegram settings: Verify bot token and chat ID are correct
- Look for webhook notifications in logs: Search for "π₯ Received Google Calendar webhook"
- Make sure the connector is properly configured in Replit
- Check that you've granted calendar read permissions
- Re-authenticate if necessary
- Some calendars (like public holiday calendars) don't support webhooks
- Check logs for "Push notifications are not supported" errors
- These calendars will be skipped automatically
telegram_bot_token: Telegram bot authentication tokenchat_id: Telegram chat/group IDtopic_mappings: JSON mapping of calendar names to topic IDscheck_interval: Legacy field (not used in webhook mode)initial_sync_complete: Boolean flag indicating if initial sync has been performedinitial_sync_cutoff: Timestamp used to suppress past event notifications on initial sync
event_id: Google Calendar event IDcalendar_id: Source calendar IDcalendar_name: Human-readable calendar namesummary: Event titlestart_time: Event start timeend_time: Event end timedescription: Event descriptionlocation: Event locationstatus: Event status (confirmed/cancelled)last_updated: Last modification timestampfirst_seen_at: Timestamp when event was first discovered (for suppression logic)last_notified_at: Timestamp of last notification sent (prevents duplicate notifications)
channel_id: Unique webhook channel IDresource_id: Google Calendar resource IDcalendar_id: Associated calendar IDexpiration: When the webhook expirescreated_at: Channel creation timestamp
id: Auto-incremented primary keymessage: Notification message contentcalendar_name: Source calendar name for topic routingtopic_id: Telegram topic ID (optional)status: Queue status (pending/sent/failed)retry_count: Number of delivery attemptscreated_at: When notification was queuedsent_at: When notification was successfully sentevent_id: Associated calendar event ID
- Uses OAuth2 authentication via Replit connector
- Read-only access to calendar data
- Push notification webhooks for real-time updates
- Webhook channels expire after 7 days (auto-renewed every 6 days)
- Google Calendar detects an event change
- Google sends POST request to
/webhook/google-calendar - Application fetches updated event details
- Compares with stored event records to detect changes
- Formats notification message and adds to queue
- Background dispatcher sends queued messages at ~1 per 2 seconds
- Updates database with latest event data and notification timestamps
The system includes multiple safeguards against Telegram flooding:
-
Initial Sync Suppression: On first calendar scan (or after app restart):
- Past events are silently stored without notifications
- Only future events trigger notifications on initial sync
- Prevents notification floods when app restarts or is republished
-
Queued Notification Dispatch:
- All notifications go through a queue table
- Background dispatcher runs every 2 seconds
- Processes one message per cycle (~1 msg/2 sec)
- Respects Telegram's rate limits
-
Telegram 429 Error Handling:
- Detects "Too Many Requests" responses
- Parses
retry_aftervalue from error response - Automatically backs off and retries after the specified delay
- Failed notifications remain in queue with incremented retry count
Notifications include:
- Event type (New/Updated/Deleted)
- Past event indicator (βͺ Past event added/updated/deleted) for events that have already occurred
- Event title
- Start and end times
- Location (if specified)
- Description (if provided)
- Calendar name
Example past event notification:
βͺ Past event updated
π Event updated: Team Meeting
π
Date: December 5, 2025
...
Initially, the system used polling (checking every 5 minutes). We switched to webhooks for:
- Instant notifications: No 5-minute delay
- Reduced API calls: Google notifies us instead of us checking repeatedly
- Better efficiency: No wasted API quota on empty checks
The biggest gotcha: Webhooks require a deployed, always-on application. Development Repls that sleep will miss webhook notifications. This was discovered after testing showed no notifications despite successful webhook setup.
When the app restarts or is republished, it scans all calendar events (past 7 days + future 30 days). Without safeguards, this would send 800+ notifications in seconds, causing Telegram to block the bot. Solution:
- Initial sync suppression: Silently store past events, only notify for future events
- Queue-based delivery: Process notifications at ~1 per 2 seconds
- 429 error handling: Automatically back off when Telegram rate limits kick in
Not all calendars support webhooks:
- Public calendars (like holiday calendars) typically don't support push notifications
- The application gracefully handles these and continues with supported calendars
For Telegram supergroups with topics:
- Map calendar names to topic IDs via JSON configuration
- Allows organized notifications per calendar
- Falls back to main chat if no topic mapping exists
- All sensitive credentials are stored in environment variables
- Google OAuth tokens are managed by Replit connector
- Session data is encrypted with a secret key
- Database credentials are auto-managed by Replit's PostgreSQL integration
Key Python packages:
Flask: Web frameworkFlask-SQLAlchemy: ORM for databaseAPScheduler: Background task scheduling (webhook renewal only)google-auth: Google authenticationgoogle-api-python-client: Google Calendar APIrequests: HTTP client for Telegram APIgunicorn: Production WSGI server
Potential improvements:
- Event filtering by keywords or criteria
- Custom notification templates
- Multiple Telegram destinations per calendar
- Event reminder notifications before start time
- Web interface for viewing upcoming events
This project is intended for personal/organizational use with Google Calendar and Telegram integration.
For issues or questions:
- Check the troubleshooting section above
- Review console logs for error messages
- Verify Google Calendar connector is properly configured
- Ensure the application is deployed (not just running in dev mode)