@plotday/tool-google-calendar 0.1.1
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.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/google-api.d.ts +71 -0
- package/dist/google-api.d.ts.map +1 -0
- package/dist/google-api.js +195 -0
- package/dist/google-api.js.map +1 -0
- package/dist/google-calendar.d.ts +102 -0
- package/dist/google-calendar.d.ts.map +1 -0
- package/dist/google-calendar.js +365 -0
- package/dist/google-calendar.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Plot Technologies Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Google Calendar Tool
|
|
2
|
+
|
|
3
|
+
A Plot tool for syncing with Google Calendar.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @plotday/tool-google-calendar @plotday/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Agent, Tools } from "@plotday/sdk";
|
|
15
|
+
import { GoogleCalendar } from "@plotday/tool-google-calendar";
|
|
16
|
+
import { Auth, AuthLevel, AuthProvider } from "@plotday/sdk/tools/auth";
|
|
17
|
+
|
|
18
|
+
export default class extends Agent {
|
|
19
|
+
private googleCalendar: GoogleCalendar;
|
|
20
|
+
private auth: Auth;
|
|
21
|
+
|
|
22
|
+
constructor(tools: Tools) {
|
|
23
|
+
super();
|
|
24
|
+
this.googleCalendar = tools.get(GoogleCalendar);
|
|
25
|
+
this.auth = tools.get(Auth);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async activate(priority: { id: string }) {
|
|
29
|
+
// Request Google Calendar access
|
|
30
|
+
const authLink = await this.auth.request(
|
|
31
|
+
{
|
|
32
|
+
provider: AuthProvider.Google,
|
|
33
|
+
level: AuthLevel.User,
|
|
34
|
+
scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
functionName: "onAuthComplete",
|
|
38
|
+
context: { priorityId: priority.id },
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// User will authenticate via authLink
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async onAuthComplete(authorization: any, context: any) {
|
|
46
|
+
const authToken = await this.auth.get(authorization);
|
|
47
|
+
|
|
48
|
+
// Get available calendars
|
|
49
|
+
const calendars = await this.googleCalendar.getCalendars(authToken);
|
|
50
|
+
|
|
51
|
+
// Start syncing a calendar
|
|
52
|
+
await this.googleCalendar.startSync(
|
|
53
|
+
authToken,
|
|
54
|
+
calendars[0].id,
|
|
55
|
+
"onCalendarEvent"
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async onCalendarEvent(event: any) {
|
|
60
|
+
// Handle calendar events
|
|
61
|
+
console.log("New calendar event:", event.summary);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## API
|
|
67
|
+
|
|
68
|
+
### `getCalendars(authToken: string)`
|
|
69
|
+
|
|
70
|
+
Retrieves the list of calendars available to the authenticated user.
|
|
71
|
+
|
|
72
|
+
### `startSync(authToken: string, calendarId: string, callbackName: string, options?: object)`
|
|
73
|
+
|
|
74
|
+
Starts syncing events from a Google Calendar.
|
|
75
|
+
|
|
76
|
+
### `stopSync(authToken: string, calendarId: string)`
|
|
77
|
+
|
|
78
|
+
Stops syncing events from a Google Calendar.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT © Plot Technologies Inc.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Activity } from "@plotday/sdk";
|
|
2
|
+
export type GoogleEvent = {
|
|
3
|
+
id: string;
|
|
4
|
+
recurringEventId?: string;
|
|
5
|
+
originalStartTime?: {
|
|
6
|
+
dateTime?: string;
|
|
7
|
+
date?: string;
|
|
8
|
+
timeZone?: string;
|
|
9
|
+
};
|
|
10
|
+
summary?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
status: "confirmed" | "cancelled" | "tentative";
|
|
13
|
+
start?: {
|
|
14
|
+
dateTime?: string;
|
|
15
|
+
date?: string;
|
|
16
|
+
timeZone?: string;
|
|
17
|
+
};
|
|
18
|
+
end?: {
|
|
19
|
+
dateTime?: string;
|
|
20
|
+
date?: string;
|
|
21
|
+
timeZone?: string;
|
|
22
|
+
};
|
|
23
|
+
recurrence?: string[];
|
|
24
|
+
organizer?: {
|
|
25
|
+
email?: string;
|
|
26
|
+
displayName?: string;
|
|
27
|
+
self?: boolean;
|
|
28
|
+
};
|
|
29
|
+
attendees?: Array<{
|
|
30
|
+
email?: string;
|
|
31
|
+
displayName?: string;
|
|
32
|
+
responseStatus?: "accepted" | "declined" | "tentative" | "needsAction";
|
|
33
|
+
optional?: boolean;
|
|
34
|
+
organizer?: boolean;
|
|
35
|
+
self?: boolean;
|
|
36
|
+
resource?: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
location?: string;
|
|
39
|
+
hangoutLink?: string;
|
|
40
|
+
htmlLink?: string;
|
|
41
|
+
created?: string;
|
|
42
|
+
updated?: string;
|
|
43
|
+
};
|
|
44
|
+
export type SyncState = {
|
|
45
|
+
calendarId: string;
|
|
46
|
+
state?: string;
|
|
47
|
+
more?: boolean;
|
|
48
|
+
min?: Date;
|
|
49
|
+
max?: Date;
|
|
50
|
+
sequence?: number;
|
|
51
|
+
};
|
|
52
|
+
export declare class GoogleApi {
|
|
53
|
+
accessToken: string;
|
|
54
|
+
constructor(accessToken: string);
|
|
55
|
+
call(method: string, url: string, params?: {
|
|
56
|
+
[key: string]: any;
|
|
57
|
+
}, body?: {
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
}): Promise<any>;
|
|
60
|
+
}
|
|
61
|
+
export declare function parseRRule(recurrence?: string[]): string | undefined;
|
|
62
|
+
export declare function parseExDates(recurrence?: string[]): Date[];
|
|
63
|
+
export declare function parseRDates(recurrence?: string[]): Date[];
|
|
64
|
+
export declare function parseGoogleRecurrenceEnd(recurrence?: string[]): Date | string | null;
|
|
65
|
+
export declare function parseGoogleRecurrenceCount(recurrence?: string[]): number | null;
|
|
66
|
+
export declare function transformGoogleEvent(event: GoogleEvent, calendarId: string): Partial<Activity>;
|
|
67
|
+
export declare function syncGoogleCalendar(api: GoogleApi, calendarId: string, state: SyncState): Promise<{
|
|
68
|
+
events: GoogleEvent[];
|
|
69
|
+
state: SyncState;
|
|
70
|
+
}>;
|
|
71
|
+
//# sourceMappingURL=google-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-api.d.ts","sourceRoot":"","sources":["../src/google-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAChD,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,GAAG,CAAC,EAAE;QACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE;QACV,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;QACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,qBAAa,SAAS;IACD,WAAW,EAAE,MAAM;gBAAnB,WAAW,EAAE,MAAM;IAEzB,IAAI,CACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,EAC/B,IAAI,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE;CA+BhC;AAED,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAKpE;AAED,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CAS1D;AAED,wBAAgB,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,CASzD;AAED,wBAAgB,wBAAwB,CACtC,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,IAAI,GAAG,MAAM,GAAG,IAAI,CA0BtB;AAED,wBAAgB,0BAA0B,CACxC,UAAU,CAAC,EAAE,MAAM,EAAE,GACpB,MAAM,GAAG,IAAI,CAaf;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,QAAQ,CAAC,CA2DnB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,SAAS,EACd,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC;IACT,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC,CAiDD"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { ActivityType } from "@plotday/sdk";
|
|
2
|
+
export class GoogleApi {
|
|
3
|
+
accessToken;
|
|
4
|
+
constructor(accessToken) {
|
|
5
|
+
this.accessToken = accessToken;
|
|
6
|
+
}
|
|
7
|
+
async call(method, url, params, body) {
|
|
8
|
+
const query = params ? `?${new URLSearchParams(params)}` : "";
|
|
9
|
+
const headers = {
|
|
10
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
11
|
+
Accept: "application/json",
|
|
12
|
+
...(body ? { "Content-Type": "application/json" } : {}),
|
|
13
|
+
};
|
|
14
|
+
const response = await fetch(url + query, {
|
|
15
|
+
method,
|
|
16
|
+
headers,
|
|
17
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
18
|
+
});
|
|
19
|
+
switch (response.status) {
|
|
20
|
+
case 400:
|
|
21
|
+
const responseBody = await response.json();
|
|
22
|
+
if (responseBody.status === "FAILED_PRECONDITION") {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
throw new Error("Invalid request", { cause: responseBody });
|
|
26
|
+
case 401:
|
|
27
|
+
throw new Error("Authentication failed - token may be expired");
|
|
28
|
+
case 410:
|
|
29
|
+
return null;
|
|
30
|
+
case 200:
|
|
31
|
+
return await response.json();
|
|
32
|
+
default:
|
|
33
|
+
throw new Error(await response.text());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function parseRRule(recurrence) {
|
|
38
|
+
if (!recurrence?.length)
|
|
39
|
+
return undefined;
|
|
40
|
+
const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
|
|
41
|
+
return rrule ? rrule.substring(6) : undefined; // Remove 'RRULE:' prefix
|
|
42
|
+
}
|
|
43
|
+
export function parseExDates(recurrence) {
|
|
44
|
+
if (!recurrence?.length)
|
|
45
|
+
return [];
|
|
46
|
+
return recurrence
|
|
47
|
+
.filter((rule) => rule.startsWith("EXDATE"))
|
|
48
|
+
.flatMap((rule) => {
|
|
49
|
+
const dates = rule.split(":")[1];
|
|
50
|
+
return dates ? dates.split(",").map((d) => new Date(d)) : [];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function parseRDates(recurrence) {
|
|
54
|
+
if (!recurrence?.length)
|
|
55
|
+
return [];
|
|
56
|
+
return recurrence
|
|
57
|
+
.filter((rule) => rule.startsWith("RDATE"))
|
|
58
|
+
.flatMap((rule) => {
|
|
59
|
+
const dates = rule.split(":")[1];
|
|
60
|
+
return dates ? dates.split(",").map((d) => new Date(d)) : [];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function parseGoogleRecurrenceEnd(recurrence) {
|
|
64
|
+
if (!recurrence?.length)
|
|
65
|
+
return null;
|
|
66
|
+
const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
|
|
67
|
+
if (!rrule)
|
|
68
|
+
return null;
|
|
69
|
+
const untilMatch = rrule.match(/UNTIL=([^;]+)/);
|
|
70
|
+
if (untilMatch) {
|
|
71
|
+
const untilValue = untilMatch[1];
|
|
72
|
+
if (untilValue.includes("T")) {
|
|
73
|
+
const year = untilValue.slice(0, 4);
|
|
74
|
+
const month = untilValue.slice(4, 6);
|
|
75
|
+
const day = untilValue.slice(6, 8);
|
|
76
|
+
const hour = untilValue.slice(9, 11);
|
|
77
|
+
const minute = untilValue.slice(11, 13);
|
|
78
|
+
const second = untilValue.slice(13, 15);
|
|
79
|
+
return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}Z`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const year = untilValue.slice(0, 4);
|
|
83
|
+
const month = untilValue.slice(4, 6);
|
|
84
|
+
const day = untilValue.slice(6, 8);
|
|
85
|
+
return `${year}-${month}-${day}`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
export function parseGoogleRecurrenceCount(recurrence) {
|
|
91
|
+
if (!recurrence?.length)
|
|
92
|
+
return null;
|
|
93
|
+
const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
|
|
94
|
+
if (!rrule)
|
|
95
|
+
return null;
|
|
96
|
+
const countMatch = rrule.match(/COUNT=([^;]+)/);
|
|
97
|
+
if (countMatch) {
|
|
98
|
+
const count = parseInt(countMatch[1]);
|
|
99
|
+
return isNaN(count) ? null : count;
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
export function transformGoogleEvent(event, calendarId) {
|
|
104
|
+
// Determine if this is an all-day event
|
|
105
|
+
const isAllDay = event.start?.date && !event.start?.dateTime;
|
|
106
|
+
const start = isAllDay
|
|
107
|
+
? event.start?.date || null // All-day events use date strings
|
|
108
|
+
: event.start?.dateTime
|
|
109
|
+
? new Date(event.start?.dateTime)
|
|
110
|
+
: null; // Timed events use Date objects
|
|
111
|
+
const end = isAllDay
|
|
112
|
+
? event.end?.date || null // All-day events use date strings
|
|
113
|
+
: event.end?.dateTime
|
|
114
|
+
? new Date(event.end?.dateTime)
|
|
115
|
+
: null; // Timed events use Date objects
|
|
116
|
+
const activity = {
|
|
117
|
+
type: ActivityType.Event,
|
|
118
|
+
title: event.summary || null,
|
|
119
|
+
note: event.description || null,
|
|
120
|
+
start,
|
|
121
|
+
end,
|
|
122
|
+
source: {
|
|
123
|
+
type: "google-calendar-event",
|
|
124
|
+
id: event.id,
|
|
125
|
+
calendarId: calendarId,
|
|
126
|
+
htmlLink: event.htmlLink,
|
|
127
|
+
hangoutLink: event.hangoutLink,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
// Handle recurrence for master events (not instances)
|
|
131
|
+
if (event.recurrence && !event.recurringEventId) {
|
|
132
|
+
activity.recurrenceRule = parseRRule(event.recurrence);
|
|
133
|
+
// Parse recurrence count (takes precedence over UNTIL)
|
|
134
|
+
const recurrenceCount = parseGoogleRecurrenceCount(event.recurrence);
|
|
135
|
+
if (recurrenceCount) {
|
|
136
|
+
activity.recurrenceCount = recurrenceCount;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Parse recurrence end date for recurring activities if no count
|
|
140
|
+
const recurrenceUntil = parseGoogleRecurrenceEnd(event.recurrence);
|
|
141
|
+
if (recurrenceUntil) {
|
|
142
|
+
activity.recurrenceUntil = recurrenceUntil;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const exdates = parseExDates(event.recurrence);
|
|
146
|
+
if (exdates.length > 0) {
|
|
147
|
+
activity.recurrenceExdates = exdates;
|
|
148
|
+
}
|
|
149
|
+
const rdates = parseRDates(event.recurrence);
|
|
150
|
+
if (rdates.length > 0) {
|
|
151
|
+
activity.recurrenceDates = rdates;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return activity;
|
|
155
|
+
}
|
|
156
|
+
export async function syncGoogleCalendar(api, calendarId, state) {
|
|
157
|
+
const params = {
|
|
158
|
+
// Remove singleEvents to get recurring events as masters
|
|
159
|
+
singleEvents: false,
|
|
160
|
+
showDeleted: true,
|
|
161
|
+
};
|
|
162
|
+
if (state.state && state.more) {
|
|
163
|
+
params.pageToken = state.state;
|
|
164
|
+
}
|
|
165
|
+
else if (state.state && !state.more) {
|
|
166
|
+
params.syncToken = state.state;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
params.timeMin = state.min?.toISOString();
|
|
170
|
+
}
|
|
171
|
+
const data = (await api.call("GET", `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`, params));
|
|
172
|
+
if (!data) {
|
|
173
|
+
// Requires full sync
|
|
174
|
+
const newState = {
|
|
175
|
+
calendarId,
|
|
176
|
+
min: state.min,
|
|
177
|
+
max: state.max,
|
|
178
|
+
sequence: (state.sequence || 1) + 1,
|
|
179
|
+
};
|
|
180
|
+
return syncGoogleCalendar(api, calendarId, newState);
|
|
181
|
+
}
|
|
182
|
+
const nextState = {
|
|
183
|
+
calendarId,
|
|
184
|
+
state: data.nextPageToken || data.nextSyncToken,
|
|
185
|
+
more: !!data.nextPageToken,
|
|
186
|
+
min: state.min,
|
|
187
|
+
max: state.max,
|
|
188
|
+
sequence: state.sequence,
|
|
189
|
+
};
|
|
190
|
+
return {
|
|
191
|
+
events: data.items || [],
|
|
192
|
+
state: nextState,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=google-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-api.js","sourceRoot":"","sources":["../src/google-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { type ActivityLink, Tool, type Tools } from "@plotday/sdk";
|
|
2
|
+
import { type Authorization } from "@plotday/sdk/tools/auth";
|
|
3
|
+
import { type Calendar, type CalendarTool, type SyncOptions } from "@plotday/sdk/common/calendar";
|
|
4
|
+
import { type Callback } from "@plotday/sdk/tools/callback";
|
|
5
|
+
import { type WebhookRequest } from "@plotday/sdk/tools/webhook";
|
|
6
|
+
type AuthSuccessContext = {
|
|
7
|
+
authToken: string;
|
|
8
|
+
callbackToken: Callback;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Google Calendar integration tool.
|
|
12
|
+
*
|
|
13
|
+
* Provides seamless integration with Google Calendar, supporting event
|
|
14
|
+
* synchronization, real-time updates via webhooks, and comprehensive
|
|
15
|
+
* recurrence pattern handling.
|
|
16
|
+
*
|
|
17
|
+
* **Features:**
|
|
18
|
+
* - OAuth 2.0 authentication with Google
|
|
19
|
+
* - Real-time event synchronization
|
|
20
|
+
* - Webhook-based change notifications
|
|
21
|
+
* - Support for recurring events and exceptions
|
|
22
|
+
* - Batch processing for large calendars
|
|
23
|
+
* - Automatic retry on failures
|
|
24
|
+
*
|
|
25
|
+
* **Required OAuth Scopes:**
|
|
26
|
+
* - `https://www.googleapis.com/auth/calendar.calendarlist.readonly` - Read calendar list
|
|
27
|
+
* - `https://www.googleapis.com/auth/calendar.events` - Read/write calendar events
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* class EventsAgent extends Agent {
|
|
32
|
+
* private googleCalendar: GoogleCalendar;
|
|
33
|
+
*
|
|
34
|
+
* constructor(tools: Tools) {
|
|
35
|
+
* super();
|
|
36
|
+
* this.googleCalendar = tools.get(GoogleCalendar);
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* async activate() {
|
|
40
|
+
* const authLink = await this.googleCalendar.requestAuth("onGoogleAuth", {
|
|
41
|
+
* provider: "google"
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* await this.plot.createActivity({
|
|
45
|
+
* type: ActivityType.Task,
|
|
46
|
+
* title: "Connect Google Calendar",
|
|
47
|
+
* links: [authLink]
|
|
48
|
+
* });
|
|
49
|
+
* }
|
|
50
|
+
*
|
|
51
|
+
* async onGoogleAuth(auth: CalendarAuth, context: any) {
|
|
52
|
+
* const calendars = await this.googleCalendar.getCalendars(auth.authToken);
|
|
53
|
+
*
|
|
54
|
+
* // Start syncing primary calendar
|
|
55
|
+
* const primary = calendars.find(c => c.primary);
|
|
56
|
+
* if (primary) {
|
|
57
|
+
* await this.googleCalendar.startSync(
|
|
58
|
+
* auth.authToken,
|
|
59
|
+
* primary.id,
|
|
60
|
+
* "onCalendarEvent",
|
|
61
|
+
* {
|
|
62
|
+
* options: {
|
|
63
|
+
* timeMin: new Date(), // Only sync future events
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
* );
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
*
|
|
70
|
+
* async onCalendarEvent(activity: Activity, context: any) {
|
|
71
|
+
* // Process Google Calendar events
|
|
72
|
+
* await this.plot.createActivity(activity);
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare class GoogleCalendar extends Tool implements CalendarTool {
|
|
78
|
+
protected tools: Tools;
|
|
79
|
+
static readonly id = "google-calendar";
|
|
80
|
+
private auth;
|
|
81
|
+
private webhook;
|
|
82
|
+
constructor(tools: Tools);
|
|
83
|
+
requestAuth(callback: Callback): Promise<ActivityLink>;
|
|
84
|
+
private getApi;
|
|
85
|
+
getCalendars(authToken: string): Promise<Calendar[]>;
|
|
86
|
+
startSync(authToken: string, calendarId: string, callback: Callback, options?: SyncOptions): Promise<void>;
|
|
87
|
+
stopSync(authToken: string, calendarId: string): Promise<void>;
|
|
88
|
+
private setupCalendarWatch;
|
|
89
|
+
syncBatch({ calendarId, batchNumber, mode, authToken, }: {
|
|
90
|
+
calendarId: string;
|
|
91
|
+
batchNumber: number;
|
|
92
|
+
mode: "full" | "incremental";
|
|
93
|
+
authToken: string;
|
|
94
|
+
}): Promise<void>;
|
|
95
|
+
private processCalendarEvents;
|
|
96
|
+
private processEventException;
|
|
97
|
+
onCalendarWebhook(request: WebhookRequest, context: any): Promise<void>;
|
|
98
|
+
private startIncrementalSync;
|
|
99
|
+
onAuthSuccess(authResult: Authorization, context: AuthSuccessContext): Promise<void>;
|
|
100
|
+
}
|
|
101
|
+
export default GoogleCalendar;
|
|
102
|
+
//# sourceMappingURL=google-calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-calendar.d.ts","sourceRoot":"","sources":["../src/google-calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAEjB,IAAI,EACJ,KAAK,KAAK,EACX,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAS1E,KAAK,kBAAkB,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,QAAQ,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,qBAAa,cAAe,SAAQ,IAAK,YAAW,YAAY;IAMlD,SAAS,CAAC,KAAK,EAAE,KAAK;IALlC,MAAM,CAAC,QAAQ,CAAC,EAAE,qBAAqB;IAEvC,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,OAAO,CAAU;gBAEH,KAAK,EAAE,KAAK;IAM5B,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;YA6B9C,MAAM;IAgBd,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAsBpD,SAAS,CACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC;IA+BV,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAYtD,kBAAkB;IA4C1B,SAAS,CAAC,EACd,UAAU,EACV,WAAW,EACX,IAAI,EACJ,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC;YAyDH,qBAAqB;YAoDrB,qBAAqB;IA0C7B,iBAAiB,CACrB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,IAAI,CAAC;YAoCF,oBAAoB;IA2B5B,aAAa,CACjB,UAAU,EAAE,aAAa,EACzB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;CAYjB;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { Tool, } from "@plotday/sdk";
|
|
2
|
+
import { Auth, AuthLevel, AuthProvider, } from "@plotday/sdk/tools/auth";
|
|
3
|
+
import { Webhook } from "@plotday/sdk/tools/webhook";
|
|
4
|
+
import { GoogleApi, syncGoogleCalendar, transformGoogleEvent, } from "./google-api";
|
|
5
|
+
/**
|
|
6
|
+
* Google Calendar integration tool.
|
|
7
|
+
*
|
|
8
|
+
* Provides seamless integration with Google Calendar, supporting event
|
|
9
|
+
* synchronization, real-time updates via webhooks, and comprehensive
|
|
10
|
+
* recurrence pattern handling.
|
|
11
|
+
*
|
|
12
|
+
* **Features:**
|
|
13
|
+
* - OAuth 2.0 authentication with Google
|
|
14
|
+
* - Real-time event synchronization
|
|
15
|
+
* - Webhook-based change notifications
|
|
16
|
+
* - Support for recurring events and exceptions
|
|
17
|
+
* - Batch processing for large calendars
|
|
18
|
+
* - Automatic retry on failures
|
|
19
|
+
*
|
|
20
|
+
* **Required OAuth Scopes:**
|
|
21
|
+
* - `https://www.googleapis.com/auth/calendar.calendarlist.readonly` - Read calendar list
|
|
22
|
+
* - `https://www.googleapis.com/auth/calendar.events` - Read/write calendar events
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* class EventsAgent extends Agent {
|
|
27
|
+
* private googleCalendar: GoogleCalendar;
|
|
28
|
+
*
|
|
29
|
+
* constructor(tools: Tools) {
|
|
30
|
+
* super();
|
|
31
|
+
* this.googleCalendar = tools.get(GoogleCalendar);
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* async activate() {
|
|
35
|
+
* const authLink = await this.googleCalendar.requestAuth("onGoogleAuth", {
|
|
36
|
+
* provider: "google"
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* await this.plot.createActivity({
|
|
40
|
+
* type: ActivityType.Task,
|
|
41
|
+
* title: "Connect Google Calendar",
|
|
42
|
+
* links: [authLink]
|
|
43
|
+
* });
|
|
44
|
+
* }
|
|
45
|
+
*
|
|
46
|
+
* async onGoogleAuth(auth: CalendarAuth, context: any) {
|
|
47
|
+
* const calendars = await this.googleCalendar.getCalendars(auth.authToken);
|
|
48
|
+
*
|
|
49
|
+
* // Start syncing primary calendar
|
|
50
|
+
* const primary = calendars.find(c => c.primary);
|
|
51
|
+
* if (primary) {
|
|
52
|
+
* await this.googleCalendar.startSync(
|
|
53
|
+
* auth.authToken,
|
|
54
|
+
* primary.id,
|
|
55
|
+
* "onCalendarEvent",
|
|
56
|
+
* {
|
|
57
|
+
* options: {
|
|
58
|
+
* timeMin: new Date(), // Only sync future events
|
|
59
|
+
* }
|
|
60
|
+
* }
|
|
61
|
+
* );
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* async onCalendarEvent(activity: Activity, context: any) {
|
|
66
|
+
* // Process Google Calendar events
|
|
67
|
+
* await this.plot.createActivity(activity);
|
|
68
|
+
* }
|
|
69
|
+
* }
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export class GoogleCalendar extends Tool {
|
|
73
|
+
tools;
|
|
74
|
+
static id = "google-calendar";
|
|
75
|
+
auth;
|
|
76
|
+
webhook;
|
|
77
|
+
constructor(tools) {
|
|
78
|
+
super(tools);
|
|
79
|
+
this.tools = tools;
|
|
80
|
+
this.auth = tools.get(Auth);
|
|
81
|
+
this.webhook = tools.get(Webhook);
|
|
82
|
+
}
|
|
83
|
+
async requestAuth(callback) {
|
|
84
|
+
const calendarScopes = [
|
|
85
|
+
"https://www.googleapis.com/auth/calendar.calendarlist.readonly",
|
|
86
|
+
"https://www.googleapis.com/auth/calendar.events",
|
|
87
|
+
];
|
|
88
|
+
// Generate opaque token for this authorization
|
|
89
|
+
const authToken = crypto.randomUUID();
|
|
90
|
+
// Use the provided callback token
|
|
91
|
+
const callbackToken = callback;
|
|
92
|
+
// Create callback for auth completion
|
|
93
|
+
const authCallback = await this.callback("onAuthSuccess", {
|
|
94
|
+
authToken,
|
|
95
|
+
callbackToken,
|
|
96
|
+
});
|
|
97
|
+
// Request auth and return the activity link
|
|
98
|
+
return await this.auth.request({
|
|
99
|
+
provider: AuthProvider.Google,
|
|
100
|
+
level: AuthLevel.User,
|
|
101
|
+
scopes: calendarScopes,
|
|
102
|
+
}, authCallback);
|
|
103
|
+
}
|
|
104
|
+
async getApi(authToken) {
|
|
105
|
+
const authorization = await this.get(`authorization:${authToken}`);
|
|
106
|
+
if (!authorization) {
|
|
107
|
+
throw new Error("Authorization no longer available");
|
|
108
|
+
}
|
|
109
|
+
const token = await this.auth.get(authorization);
|
|
110
|
+
if (!token) {
|
|
111
|
+
throw new Error("Authorization no longer available");
|
|
112
|
+
}
|
|
113
|
+
return new GoogleApi(token.token);
|
|
114
|
+
}
|
|
115
|
+
async getCalendars(authToken) {
|
|
116
|
+
const api = await this.getApi(authToken);
|
|
117
|
+
const data = (await api.call("GET", "https://www.googleapis.com/calendar/v3/users/me/calendarList"));
|
|
118
|
+
return data.items.map((item) => ({
|
|
119
|
+
id: item.id,
|
|
120
|
+
name: item.summary,
|
|
121
|
+
description: item.description || null,
|
|
122
|
+
primary: item.primary || false,
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
async startSync(authToken, calendarId, callback, options) {
|
|
126
|
+
// Store the callback token
|
|
127
|
+
await this.set("event_callback_token", callback);
|
|
128
|
+
// Setup webhook for this calendar
|
|
129
|
+
await this.setupCalendarWatch(authToken, calendarId, authToken);
|
|
130
|
+
// Start initial sync
|
|
131
|
+
const now = new Date();
|
|
132
|
+
const min = options?.timeMin || new Date(now.getFullYear() - 2, 0, 1);
|
|
133
|
+
const max = options?.timeMax || new Date(now.getFullYear() + 1, 11, 31);
|
|
134
|
+
const initialState = {
|
|
135
|
+
calendarId,
|
|
136
|
+
min,
|
|
137
|
+
max,
|
|
138
|
+
sequence: 1,
|
|
139
|
+
};
|
|
140
|
+
await this.set(`sync_state_${calendarId}`, initialState);
|
|
141
|
+
// Start sync batch using run tool for long-running operation
|
|
142
|
+
const syncCallback = await this.callback("syncBatch", {
|
|
143
|
+
calendarId,
|
|
144
|
+
batchNumber: 1,
|
|
145
|
+
mode: "full",
|
|
146
|
+
authToken,
|
|
147
|
+
});
|
|
148
|
+
await this.run(syncCallback);
|
|
149
|
+
}
|
|
150
|
+
async stopSync(authToken, calendarId) {
|
|
151
|
+
// Stop webhook
|
|
152
|
+
const watchData = await this.get(`calendar_watch_${calendarId}`);
|
|
153
|
+
if (watchData) {
|
|
154
|
+
// Cancel the watch (would need Google API call)
|
|
155
|
+
await this.clear(`calendar_watch_${calendarId}`);
|
|
156
|
+
}
|
|
157
|
+
// Clear sync state
|
|
158
|
+
await this.clear(`sync_state_${calendarId}`);
|
|
159
|
+
}
|
|
160
|
+
async setupCalendarWatch(authToken, calendarId, opaqueAuthToken) {
|
|
161
|
+
const webhookUrl = await this.webhook.create("onCalendarWebhook", {
|
|
162
|
+
calendarId,
|
|
163
|
+
authToken: opaqueAuthToken,
|
|
164
|
+
});
|
|
165
|
+
// Check if webhook URL is localhost
|
|
166
|
+
if (URL.parse(webhookUrl)?.hostname === "localhost") {
|
|
167
|
+
console.log("Skipping webhook setup for localhost URL");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const api = await this.getApi(authToken);
|
|
171
|
+
// Setup watch for calendar
|
|
172
|
+
const watchId = crypto.randomUUID();
|
|
173
|
+
const secret = crypto.randomUUID();
|
|
174
|
+
const watchData = (await api.call("POST", `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/watch`, undefined, {
|
|
175
|
+
id: watchId,
|
|
176
|
+
type: "web_hook",
|
|
177
|
+
address: webhookUrl,
|
|
178
|
+
token: new URLSearchParams({ secret }).toString(),
|
|
179
|
+
}));
|
|
180
|
+
await this.set(`calendar_watch_${calendarId}`, {
|
|
181
|
+
watchId,
|
|
182
|
+
secret,
|
|
183
|
+
calendarId,
|
|
184
|
+
expiry: new Date(parseInt(watchData.expiration)),
|
|
185
|
+
});
|
|
186
|
+
console.log("Calendar watch setup complete", { watchId, calendarId });
|
|
187
|
+
}
|
|
188
|
+
async syncBatch({ calendarId, batchNumber, mode, authToken, }) {
|
|
189
|
+
console.log(`Starting Google Calendar sync batch ${batchNumber} (${mode}) for calendar ${calendarId}`);
|
|
190
|
+
try {
|
|
191
|
+
const state = await this.get(`sync_state_${calendarId}`);
|
|
192
|
+
if (!state) {
|
|
193
|
+
throw new Error("No sync state found");
|
|
194
|
+
}
|
|
195
|
+
// Convert date strings back to Date objects after deserialization
|
|
196
|
+
if (state.min && typeof state.min === "string") {
|
|
197
|
+
state.min = new Date(state.min);
|
|
198
|
+
}
|
|
199
|
+
if (state.max && typeof state.max === "string") {
|
|
200
|
+
state.max = new Date(state.max);
|
|
201
|
+
}
|
|
202
|
+
const api = await this.getApi(authToken);
|
|
203
|
+
const result = await syncGoogleCalendar(api, calendarId, state);
|
|
204
|
+
if (result.events.length > 0) {
|
|
205
|
+
await this.processCalendarEvents(result.events, calendarId);
|
|
206
|
+
console.log(`Synced ${result.events.length} events in batch ${batchNumber} for calendar ${calendarId}`);
|
|
207
|
+
}
|
|
208
|
+
await this.set(`sync_state_${calendarId}`, result.state);
|
|
209
|
+
if (result.state.more) {
|
|
210
|
+
const syncCallback = await this.callback("syncBatch", {
|
|
211
|
+
calendarId,
|
|
212
|
+
batchNumber: batchNumber + 1,
|
|
213
|
+
mode,
|
|
214
|
+
authToken,
|
|
215
|
+
});
|
|
216
|
+
await this.run(syncCallback);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
console.log(`Google Calendar ${mode} sync completed after ${batchNumber} batches for calendar ${calendarId}`);
|
|
220
|
+
if (mode === "full") {
|
|
221
|
+
await this.clear(`sync_state_${calendarId}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error(`Error in sync batch ${batchNumber} for calendar ${calendarId}:`, error);
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async processCalendarEvents(events, calendarId) {
|
|
231
|
+
for (const event of events) {
|
|
232
|
+
try {
|
|
233
|
+
if (event.status === "cancelled") {
|
|
234
|
+
// TODO: Handle event cancellation
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
// Check if this is a recurring event instance (exception)
|
|
238
|
+
if (event.recurringEventId && event.originalStartTime) {
|
|
239
|
+
await this.processEventException(event, calendarId);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
// Regular or master recurring event
|
|
243
|
+
const activityData = transformGoogleEvent(event, calendarId);
|
|
244
|
+
// Convert to full Activity and call callback
|
|
245
|
+
const callbackToken = await this.get("event_callback_token");
|
|
246
|
+
if (callbackToken && activityData.type) {
|
|
247
|
+
const activity = {
|
|
248
|
+
type: activityData.type,
|
|
249
|
+
start: activityData.start || null,
|
|
250
|
+
end: activityData.end || null,
|
|
251
|
+
recurrenceUntil: activityData.recurrenceUntil || null,
|
|
252
|
+
recurrenceCount: activityData.recurrenceCount || null,
|
|
253
|
+
doneAt: null,
|
|
254
|
+
note: activityData.note || null,
|
|
255
|
+
title: activityData.title || null,
|
|
256
|
+
parent: null,
|
|
257
|
+
links: null,
|
|
258
|
+
recurrenceRule: activityData.recurrenceRule || null,
|
|
259
|
+
recurrenceExdates: activityData.recurrenceExdates || null,
|
|
260
|
+
recurrenceDates: activityData.recurrenceDates || null,
|
|
261
|
+
recurrence: null,
|
|
262
|
+
occurrence: null,
|
|
263
|
+
source: activityData.source || null,
|
|
264
|
+
};
|
|
265
|
+
await this.call(callbackToken, activity);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
console.error(`Failed to process event ${event.id}:`, error);
|
|
271
|
+
// Continue processing other events
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async processEventException(event, calendarId) {
|
|
276
|
+
// Similar to processCalendarEvents but for exceptions
|
|
277
|
+
// This would find the master recurring activity and create an exception
|
|
278
|
+
const originalStartTime = event.originalStartTime?.dateTime || event.originalStartTime?.date;
|
|
279
|
+
if (!originalStartTime) {
|
|
280
|
+
console.warn(`No original start time for exception: ${event.id}`);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const activityData = transformGoogleEvent(event, calendarId);
|
|
284
|
+
const callbackToken = await this.get("event_callback_token");
|
|
285
|
+
if (callbackToken && activityData.type) {
|
|
286
|
+
const activity = {
|
|
287
|
+
type: activityData.type,
|
|
288
|
+
start: activityData.start || null,
|
|
289
|
+
end: activityData.end || null,
|
|
290
|
+
recurrenceUntil: activityData.recurrenceUntil || null,
|
|
291
|
+
recurrenceCount: activityData.recurrenceCount || null,
|
|
292
|
+
doneAt: null,
|
|
293
|
+
note: activityData.note || null,
|
|
294
|
+
title: activityData.title || null,
|
|
295
|
+
parent: null,
|
|
296
|
+
links: null,
|
|
297
|
+
recurrenceRule: null,
|
|
298
|
+
recurrenceExdates: null,
|
|
299
|
+
recurrenceDates: null,
|
|
300
|
+
recurrence: null, // Would need to find master activity
|
|
301
|
+
occurrence: new Date(originalStartTime),
|
|
302
|
+
source: activityData.source || null,
|
|
303
|
+
};
|
|
304
|
+
await this.call(callbackToken, activity);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
async onCalendarWebhook(request, context) {
|
|
308
|
+
console.log("Received calendar webhook notification", {
|
|
309
|
+
headers: request.headers,
|
|
310
|
+
params: request.params,
|
|
311
|
+
calendarId: context.calendarId,
|
|
312
|
+
});
|
|
313
|
+
// Validate webhook authenticity
|
|
314
|
+
const channelId = request.headers["X-Goog-Channel-ID"];
|
|
315
|
+
const channelToken = request.headers["X-Goog-Channel-Token"];
|
|
316
|
+
if (!channelId || !channelToken) {
|
|
317
|
+
throw new Error("Invalid webhook headers");
|
|
318
|
+
}
|
|
319
|
+
const watchData = await this.get(`calendar_watch_${context.calendarId}`);
|
|
320
|
+
if (!watchData || watchData.watchId !== channelId) {
|
|
321
|
+
console.warn("Unknown or expired webhook notification");
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const params = new URLSearchParams(channelToken);
|
|
325
|
+
const secret = params.get("secret");
|
|
326
|
+
if (!watchData || watchData.secret !== secret) {
|
|
327
|
+
console.warn("Invalid webhook secret");
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
// Trigger incremental sync
|
|
331
|
+
await this.startIncrementalSync(context.calendarId, context.authToken);
|
|
332
|
+
}
|
|
333
|
+
async startIncrementalSync(calendarId, authToken) {
|
|
334
|
+
const watchData = await this.get(`calendar_watch_${calendarId}`);
|
|
335
|
+
if (!watchData) {
|
|
336
|
+
console.error("No calendar watch data found");
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const incrementalState = {
|
|
340
|
+
calendarId: watchData.calendarId,
|
|
341
|
+
state: (await this.get(`last_sync_token_${calendarId}`)) ||
|
|
342
|
+
undefined,
|
|
343
|
+
};
|
|
344
|
+
await this.set(`sync_state_${calendarId}`, incrementalState);
|
|
345
|
+
const syncCallback = await this.callback("syncBatch", {
|
|
346
|
+
calendarId,
|
|
347
|
+
batchNumber: 1,
|
|
348
|
+
mode: "incremental",
|
|
349
|
+
authToken,
|
|
350
|
+
});
|
|
351
|
+
await this.run(syncCallback);
|
|
352
|
+
}
|
|
353
|
+
async onAuthSuccess(authResult, context) {
|
|
354
|
+
// Store the actual auth token using opaque token as key
|
|
355
|
+
await this.set(`authorization:${context.authToken}`, authResult);
|
|
356
|
+
const authSuccessResult = {
|
|
357
|
+
authToken: context.authToken,
|
|
358
|
+
};
|
|
359
|
+
await this.call(context.callbackToken, authSuccessResult);
|
|
360
|
+
// Clean up the callback token
|
|
361
|
+
await this.clear(`auth_callback_token:${context.authToken}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
export default GoogleCalendar;
|
|
365
|
+
//# sourceMappingURL=google-calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-calendar.js","sourceRoot":"","sources":["../src/google-calendar.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plotday/tool-google-calendar",
|
|
3
|
+
"displayName": "Google Calendar",
|
|
4
|
+
"description": "Sync with Google Calendar",
|
|
5
|
+
"author": "Plot <team@plot.day> (https://plot.day)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"version": "0.1.1",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@plotday/sdk": "^0.10.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"typescript": "^5.9.3"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/plotday/plot.git",
|
|
31
|
+
"directory": "tools/google-calendar"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://plot.day",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/plotday/plot/issues"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"plot",
|
|
39
|
+
"agent",
|
|
40
|
+
"tool",
|
|
41
|
+
"google-calendar",
|
|
42
|
+
"calendar"
|
|
43
|
+
],
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc --project tsconfig.build.json",
|
|
49
|
+
"clean": "rm -rf dist"
|
|
50
|
+
}
|
|
51
|
+
}
|