@pipedream/google_calendar 0.5.12 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import googleCalendar from "../../google_calendar.app.mjs";
|
|
2
|
+
import constants from "../../common/constants.mjs";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_CALENDAR_SAMPLE_LIMIT = 25;
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
key: "google_calendar-get-current-user",
|
|
8
|
+
name: "Get Current User",
|
|
9
|
+
description: "Retrieve information about the authenticated Google Calendar account, including the primary calendar (summary, timezone, ACL flags), a list of accessible calendars, user-level settings (timezone, locale, week start), and the color palette that controls events and calendars. Ideal for confirming which calendar account is in use, customizing downstream scheduling, or equipping LLMs with the user’s context (timezones, available calendars) prior to creating or updating events. [See the documentation](https://developers.google.com/calendar/api/v3/reference/calendars/get).",
|
|
10
|
+
version: "0.0.1",
|
|
11
|
+
type: "action",
|
|
12
|
+
annotations: {
|
|
13
|
+
destructiveHint: false,
|
|
14
|
+
openWorldHint: true,
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
googleCalendar,
|
|
19
|
+
},
|
|
20
|
+
async run({ $ }) {
|
|
21
|
+
const [
|
|
22
|
+
primaryCalendar,
|
|
23
|
+
calendarList,
|
|
24
|
+
settings,
|
|
25
|
+
colors,
|
|
26
|
+
] = await Promise.all([
|
|
27
|
+
this.googleCalendar.getCalendar({
|
|
28
|
+
calendarId: "primary",
|
|
29
|
+
}),
|
|
30
|
+
this.googleCalendar.listCalendars({
|
|
31
|
+
maxResults: DEFAULT_CALENDAR_SAMPLE_LIMIT,
|
|
32
|
+
}),
|
|
33
|
+
this.googleCalendar.requestHandler({
|
|
34
|
+
api: constants.API.SETTINGS.NAME,
|
|
35
|
+
method: constants.API.SETTINGS.METHOD.LIST,
|
|
36
|
+
}),
|
|
37
|
+
this.googleCalendar.requestHandler({
|
|
38
|
+
api: constants.API.COLORS.NAME,
|
|
39
|
+
method: constants.API.COLORS.METHOD.GET,
|
|
40
|
+
}),
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const timezoneSetting = settings?.items?.find?.((setting) => setting.id === "timezone")?.value;
|
|
44
|
+
const localeSetting = settings?.items?.find?.((setting) => setting.id === "locale")?.value;
|
|
45
|
+
|
|
46
|
+
const summaryName = primaryCalendar?.summary || primaryCalendar?.id;
|
|
47
|
+
$.export("$summary", `Retrieved Google Calendar user ${summaryName}`);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
primaryCalendar,
|
|
51
|
+
calendars: calendarList?.items ?? [],
|
|
52
|
+
settings: settings?.items ?? [],
|
|
53
|
+
timezone: timezoneSetting || primaryCalendar?.timeZone,
|
|
54
|
+
locale: localeSetting,
|
|
55
|
+
colors,
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipedream/google_calendar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Pipedream Google_calendar Components",
|
|
5
5
|
"main": "google_calendar.app.mjs",
|
|
6
6
|
"keywords": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@googleapis/calendar": "^1.0.2",
|
|
14
|
-
"@pipedream/platform": "^3.1.
|
|
14
|
+
"@pipedream/platform": "^3.1.1",
|
|
15
15
|
"color-2-name": "^1.4.4",
|
|
16
16
|
"lodash.get": "^4.4.2",
|
|
17
17
|
"moment-timezone": "^0.5.33",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
"kind": "calendar#event",
|
|
3
|
+
"etag": "\"3442838491454000\"",
|
|
4
|
+
"id": "0dip62r3f3d85o35jjnjcmqbmo",
|
|
5
|
+
"status": "confirmed",
|
|
6
|
+
"htmlLink": "https://www.google.com/calendar/event?eid=MGRpcDYycjNW8zNWgbWljaGVsbGUucGlwZWRyZWFtQG0",
|
|
7
|
+
"created": "2024-07-19T20:00:45.000Z",
|
|
8
|
+
"updated": "2024-07-19T20:00:45.727Z",
|
|
9
|
+
"summary": "Upcoming Meeting",
|
|
10
|
+
"creator": {
|
|
11
|
+
"email": "test@sample.com",
|
|
12
|
+
"self": true
|
|
13
|
+
},
|
|
14
|
+
"organizer": {
|
|
15
|
+
"email": "test@sample.com",
|
|
16
|
+
"self": true
|
|
17
|
+
},
|
|
18
|
+
"start": {
|
|
19
|
+
"dateTime": "2024-07-19T16:07:00-04:00",
|
|
20
|
+
"timeZone": "America/Detroit"
|
|
21
|
+
},
|
|
22
|
+
"end": {
|
|
23
|
+
"dateTime": "2024-07-19T17:07:00-04:00",
|
|
24
|
+
"timeZone": "America/Detroit"
|
|
25
|
+
},
|
|
26
|
+
"iCalUID": "0dip62r35jjnjcmqbmo@google.com",
|
|
27
|
+
"sequence": 0,
|
|
28
|
+
"reminders": {
|
|
29
|
+
"useDefault": true
|
|
30
|
+
},
|
|
31
|
+
"eventType": "default"
|
|
32
|
+
}
|
|
33
|
+
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import common from "../common/common.mjs";
|
|
2
|
+
import sampleEmit from "./test-event.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
...common,
|
|
6
|
+
key: "google_calendar-upcoming-event-alert-polling",
|
|
7
|
+
name: "New Upcoming Event Alert (Polling)",
|
|
8
|
+
description: "Emit new event based on a time interval before an upcoming event in the calendar. [See the documentation](https://developers.google.com/calendar/api/v3/reference/events/list)",
|
|
9
|
+
version: "0.0.1",
|
|
10
|
+
type: "source",
|
|
11
|
+
dedupe: "unique",
|
|
12
|
+
props: {
|
|
13
|
+
...common.props,
|
|
14
|
+
db: "$.service.db",
|
|
15
|
+
pollingInfo: {
|
|
16
|
+
type: "alert",
|
|
17
|
+
alertType: "info",
|
|
18
|
+
content: "Since this source executes based on a timer, event emission may be slightly delayed. For example, if the source runs every 5 minutes, the delay may be up to 5 minutes. You can use the `upcoming-event-alert` source for instant event emission.",
|
|
19
|
+
},
|
|
20
|
+
calendarId: {
|
|
21
|
+
propDefinition: [
|
|
22
|
+
common.props.googleCalendar,
|
|
23
|
+
"calendarId",
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
eventTypes: {
|
|
27
|
+
propDefinition: [
|
|
28
|
+
common.props.googleCalendar,
|
|
29
|
+
"eventTypes",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
minutesBefore: {
|
|
33
|
+
type: "integer",
|
|
34
|
+
label: "Minutes Before",
|
|
35
|
+
description: "Number of minutes to trigger before the start of the calendar event.",
|
|
36
|
+
min: 0,
|
|
37
|
+
default: 30,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
methods: {
|
|
41
|
+
...common.methods,
|
|
42
|
+
_getEmittedEvents() {
|
|
43
|
+
return this.db.get("emittedEvents") || {};
|
|
44
|
+
},
|
|
45
|
+
_setEmittedEvents(emittedEvents) {
|
|
46
|
+
this.db.set("emittedEvents", emittedEvents);
|
|
47
|
+
},
|
|
48
|
+
_cleanupEmittedEvents(now) {
|
|
49
|
+
const emittedEvents = this._getEmittedEvents();
|
|
50
|
+
const cleanedEvents = {};
|
|
51
|
+
let cleanedCount = 0;
|
|
52
|
+
|
|
53
|
+
// Keep only events that haven't passed yet
|
|
54
|
+
for (const [
|
|
55
|
+
eventId,
|
|
56
|
+
startTime,
|
|
57
|
+
] of Object.entries(emittedEvents)) {
|
|
58
|
+
if (startTime > now.getTime()) {
|
|
59
|
+
cleanedEvents[eventId] = startTime;
|
|
60
|
+
} else {
|
|
61
|
+
cleanedCount++;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (cleanedCount > 0) {
|
|
66
|
+
console.log(`Cleaned up ${cleanedCount} past event(s) from emitted events tracker`);
|
|
67
|
+
this._setEmittedEvents(cleanedEvents);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return cleanedEvents;
|
|
71
|
+
},
|
|
72
|
+
getConfig({ now }) {
|
|
73
|
+
// Get events starting from now up to the alert window
|
|
74
|
+
const timeMin = now.toISOString();
|
|
75
|
+
// Look ahead to find events within our alert window
|
|
76
|
+
const alertWindowMs = this.minutesBefore * 60 * 1000;
|
|
77
|
+
const timeMax = new Date(now.getTime() + alertWindowMs).toISOString();
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
calendarId: this.calendarId,
|
|
81
|
+
timeMin,
|
|
82
|
+
timeMax,
|
|
83
|
+
eventTypes: this.eventTypes,
|
|
84
|
+
singleEvents: true,
|
|
85
|
+
orderBy: "startTime",
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
isRelevant(event, { now }) {
|
|
89
|
+
// Skip cancelled events
|
|
90
|
+
if (event.status === "cancelled") {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Get event start time
|
|
95
|
+
const startTime = event.start
|
|
96
|
+
? new Date(event.start.dateTime || event.start.date)
|
|
97
|
+
: null;
|
|
98
|
+
|
|
99
|
+
if (!startTime) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Calculate time remaining until event starts (in milliseconds)
|
|
104
|
+
const timeRemaining = startTime.getTime() - now.getTime();
|
|
105
|
+
|
|
106
|
+
// Skip past events
|
|
107
|
+
if (timeRemaining < 0) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Convert minutesBefore to milliseconds
|
|
112
|
+
const alertThresholdMs = this.minutesBefore * 60 * 1000;
|
|
113
|
+
|
|
114
|
+
// Clean up old emitted events and get the current list
|
|
115
|
+
const emittedEvents = this._cleanupEmittedEvents(now);
|
|
116
|
+
|
|
117
|
+
// Check if we've already emitted this event
|
|
118
|
+
if (emittedEvents[event.id]) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Emit if time remaining is less than or equal to the alert threshold
|
|
123
|
+
if (timeRemaining <= alertThresholdMs) {
|
|
124
|
+
// Mark this event as emitted with its start time for future cleanup
|
|
125
|
+
emittedEvents[event.id] = startTime.getTime();
|
|
126
|
+
this._setEmittedEvents(emittedEvents);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return false;
|
|
131
|
+
},
|
|
132
|
+
generateMeta(event) {
|
|
133
|
+
const {
|
|
134
|
+
summary,
|
|
135
|
+
id,
|
|
136
|
+
} = event;
|
|
137
|
+
return {
|
|
138
|
+
summary: `Upcoming: ${summary || `Event ID: ${id}`}`,
|
|
139
|
+
id: `${id}-${Date.now()}`,
|
|
140
|
+
ts: Date.now(),
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
hooks: {
|
|
145
|
+
async deploy() {
|
|
146
|
+
// On initial deploy, don't emit historical events
|
|
147
|
+
// Just initialize the emitted events tracker
|
|
148
|
+
this._setEmittedEvents({});
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
sampleEmit,
|
|
152
|
+
};
|
|
153
|
+
|