Skip to content

Commit 332223d

Browse files
ShadterraMalaydewangan09
authored andcommitted
Adding Google Calendar "Event Created" Trigger - First Push
1 parent 67c5f75 commit 332223d

File tree

4 files changed

+923
-0
lines changed

4 files changed

+923
-0
lines changed

CALENDAR_TRIGGER_README.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Google Calendar Event Trigger
2+
3+
## Overview
4+
5+
The `EventCreatedTrigger` monitors Google Calendar for newly created events and triggers workflow executions when new events are detected.
6+
7+
## Features
8+
9+
- Monitor single or multiple calendars
10+
- Filter events by organizer, keywords, or status
11+
- Configurable polling intervals (minimum 1 minute)
12+
- Access to complete event data
13+
- Automatic duplicate prevention
14+
15+
## Configuration
16+
17+
### Required Parameters
18+
19+
- `serviceAccount`: Google Cloud service account JSON key with Calendar API access
20+
21+
### You can also set:
22+
- `calendarId`: Watch one specific calendar (like "primary" for your main calendar)
23+
- `calendarIds`: Watch multiple calendars (don't use both this and calendarId)
24+
- `interval`: How often to check for new events (default: 5 minutes, minimum: 1 minute)
25+
- `q`: Only trigger for events containing certain words
26+
- `organizerEmail`: Only trigger for events created by a specific person
27+
- `eventStatus`: Only trigger for events with specific status (confirmed, tentative, cancelled)
28+
- `maxEventsPerPoll`: Don't process more than this many events at once (default: 100, max: 2500)
29+
30+
## Examples
31+
32+
### Simple example: Watch your main calendar
33+
34+
This will log a message every time someone creates a new event in your primary calendar:
35+
36+
```yaml
37+
id: calendar_event_monitor
38+
namespace: company.team
39+
40+
tasks:
41+
- id: log_new_event
42+
type: io.kestra.plugin.core.log.Log
43+
message: "New event: {{ trigger.summary }} at {{ trigger.start.dateTime }}"
44+
45+
triggers:
46+
- id: watch_primary_calendar
47+
type: io.kestra.plugin.googleworkspace.calendar.EventCreatedTrigger
48+
serviceAccount: "{{ secret('GCP_SERVICE_ACCOUNT_JSON') }}"
49+
calendarId: primary
50+
interval: PT5M
51+
```
52+
53+
### More complex example: Multiple calendars with filtering
54+
55+
This watches team calendars and sends for example a Slack notification when someone creates a meeting with "[email protected]" as the organizer:
56+
57+
```yaml
58+
id: team_meeting_monitor
59+
namespace: company.team
60+
61+
tasks:
62+
- id: notify_slack
63+
type: io.kestra.plugin.notifications.slack.SlackIncomingWebhook
64+
url: "{{ secret('SLACK_WEBHOOK') }}"
65+
payload: |
66+
{
67+
"text": "New meeting: {{ trigger.summary }}\nOrganizer: {{ trigger.organizer.displayName }}\nTime: {{ trigger.start.dateTime }}"
68+
}
69+
70+
triggers:
71+
- id: watch_team_meetings
72+
type: io.kestra.plugin.googleworkspace.calendar.EventCreatedTrigger
73+
serviceAccount: "{{ secret('GCP_SERVICE_ACCOUNT_JSON') }}"
74+
calendarIds:
75+
76+
77+
q: "meeting"
78+
organizerEmail: "[email protected]"
79+
eventStatus: "confirmed"
80+
interval: PT10M
81+
```
82+
83+
## What data you get
84+
85+
When the trigger fires, your workflow gets all this information about the event:
86+
87+
```json
88+
{
89+
"id": "event-id-123",
90+
"summary": "Team Standup",
91+
"description": "Daily team standup meeting",
92+
"location": "Conference Room A",
93+
"status": "confirmed",
94+
"htmlLink": "https://calendar.google.com/event?eid=...",
95+
"created": "2025-10-13T10:30:00Z",
96+
"updated": "2025-10-13T10:35:00Z",
97+
"start": {
98+
"dateTime": "2025-10-14T09:00:00Z",
99+
"timeZone": "UTC"
100+
},
101+
"end": {
102+
"dateTime": "2025-10-14T09:30:00Z",
103+
"timeZone": "UTC"
104+
},
105+
"organizer": {
106+
"email": "[email protected]",
107+
"displayName": "Meeting Organizer"
108+
},
109+
"visibility": "default",
110+
"eventType": "default"
111+
}
112+
```
113+
114+
You can access this data in your workflows using `{{ trigger.summary }}`, `{{ trigger.organizer.email }}`, etc.
115+
116+
## Getting started
117+
118+
Before you can use this trigger, you need to set up Google Cloud:
119+
120+
1. **Create a Google Cloud project** and enable the Calendar API
121+
2. **Create a service account** with calendar permissions
122+
3. **Download the service account JSON key** and add it to Kestra as a secret
123+
124+
The service account needs the `https://www.googleapis.com/auth/calendar` scope and permission to read the calendars you want to monitor.
125+
126+
## Important details
127+
128+
### Performance tips
129+
- Checking calendars too frequently uses up your Google API quota faster
130+
- Each calendar you monitor requires a separate API call
131+
- Use filters (keywords, organizer, status) to reduce processing load
132+
- The `maxEventsPerPoll` setting prevents overwhelming your system
133+
134+
### Error handling
135+
The trigger is designed to be reliable:
136+
- If you configure it wrong, you'll get a clear error message
137+
- If Google API is temporarily down, it logs the error and tries again later
138+
- If one calendar fails, it continues checking other calendars
139+
- It automatically respects Google's rate limits
140+
141+
### Authentication notes
142+
- Use service account authentication (not OAuth user tokens)
143+
- Store your service account JSON key as a Kestra secret, never in plain text
144+
- The service account needs read access to any calendars you want to monitor
145+
- You can share specific calendars with your service account's email address
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.kestra.plugin.googleworkspace.calendar;
2+
3+
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
4+
import com.google.api.client.json.gson.GsonFactory;
5+
import com.google.api.services.calendar.Calendar;
6+
import com.google.api.services.calendar.CalendarScopes;
7+
import com.google.auth.http.HttpCredentialsAdapter;
8+
import com.google.auth.oauth2.GoogleCredentials;
9+
import io.kestra.core.models.property.Property;
10+
import io.kestra.core.models.triggers.AbstractTrigger;
11+
import io.kestra.core.runners.RunContext;
12+
import io.kestra.plugin.googleworkspace.GcpInterface;
13+
import lombok.EqualsAndHashCode;
14+
import lombok.Getter;
15+
import lombok.NoArgsConstructor;
16+
import lombok.ToString;
17+
import lombok.experimental.SuperBuilder;
18+
19+
import java.io.ByteArrayInputStream;
20+
import java.nio.charset.StandardCharsets;
21+
import java.util.Collections;
22+
import java.util.List;
23+
24+
@SuperBuilder
25+
@ToString
26+
@EqualsAndHashCode
27+
@Getter
28+
@NoArgsConstructor
29+
public abstract class AbstractCalendarTrigger extends AbstractTrigger implements GcpInterface {
30+
private static final String APPLICATION_NAME = "Kestra";
31+
32+
protected Property<String> serviceAccount;
33+
34+
protected Calendar connection(RunContext runContext) throws Exception {
35+
String renderedServiceAccount = runContext.render(this.serviceAccount).as(String.class).orElseThrow();
36+
37+
GoogleCredentials credentials = GoogleCredentials
38+
.fromStream(new ByteArrayInputStream(renderedServiceAccount.getBytes(StandardCharsets.UTF_8)))
39+
.createScoped(Collections.singletonList(CalendarScopes.CALENDAR));
40+
41+
return new Calendar.Builder(
42+
GoogleNetHttpTransport.newTrustedTransport(),
43+
GsonFactory.getDefaultInstance(),
44+
new HttpCredentialsAdapter(credentials)
45+
)
46+
.setApplicationName(APPLICATION_NAME)
47+
.build();
48+
}
49+
}

0 commit comments

Comments
 (0)