@guayaba/workflow-piece-google-calendar 0.9.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/.babelrc +3 -0
- package/.eslintrc.json +18 -0
- package/README.md +5 -0
- package/assets/logo.png +0 -0
- package/package.json +23 -0
- package/src/i18n/ca.json +71 -0
- package/src/i18n/de.json +151 -0
- package/src/i18n/es.json +151 -0
- package/src/i18n/fr.json +151 -0
- package/src/i18n/hi.json +71 -0
- package/src/i18n/id.json +71 -0
- package/src/i18n/ja.json +151 -0
- package/src/i18n/nl.json +151 -0
- package/src/i18n/pt.json +151 -0
- package/src/i18n/ru.json +71 -0
- package/src/i18n/translation.json +151 -0
- package/src/i18n/vi.json +71 -0
- package/src/i18n/zh.json +151 -0
- package/src/index.ts +78 -0
- package/src/lib/actions/add-attendees.action.ts +52 -0
- package/src/lib/actions/add-calendar-to-calendarlist.ts +33 -0
- package/src/lib/actions/create-event.ts +163 -0
- package/src/lib/actions/create-quick-event.ts +66 -0
- package/src/lib/actions/delete-event.action.ts +32 -0
- package/src/lib/actions/find-busy-free-periods.ts +97 -0
- package/src/lib/actions/get-event-by-id.ts +123 -0
- package/src/lib/actions/get-events.ts +111 -0
- package/src/lib/actions/update-event.action.ts +126 -0
- package/src/lib/auth.ts +81 -0
- package/src/lib/common/helper.ts +228 -0
- package/src/lib/common/index.ts +95 -0
- package/src/lib/common/types.ts +246 -0
- package/src/lib/google-calendar.mdx +25 -0
- package/src/lib/triggers/calendar-event.ts +139 -0
- package/src/lib/triggers/event-cancelled.ts +200 -0
- package/src/lib/triggers/event-ends.ts +201 -0
- package/src/lib/triggers/event-start-time-before.ts +201 -0
- package/src/lib/triggers/new-calendar.ts +203 -0
- package/src/lib/triggers/new-event-matching-search.ts +225 -0
- package/src/lib/triggers/new-event.ts +184 -0
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +15 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { createAction, Property } from '@guayaba/workflows-framework';
|
|
2
|
+
import { googleCalendarCommon, googleCalendarAuth, createGoogleClient } from '../common';
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import { google } from 'googleapis';
|
|
5
|
+
import { randomUUID } from 'crypto';
|
|
6
|
+
|
|
7
|
+
export const createEvent = createAction({
|
|
8
|
+
auth: googleCalendarAuth,
|
|
9
|
+
name: 'create_google_calendar_event',
|
|
10
|
+
description: 'Add Event',
|
|
11
|
+
displayName: 'Create Event',
|
|
12
|
+
props: {
|
|
13
|
+
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
|
|
14
|
+
title: Property.ShortText({
|
|
15
|
+
displayName: 'Title of the event',
|
|
16
|
+
required: true,
|
|
17
|
+
}),
|
|
18
|
+
start_date_time: Property.DateTime({
|
|
19
|
+
displayName: 'Start date time of the event',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
end_date_time: Property.DateTime({
|
|
23
|
+
displayName: 'End date time of the event',
|
|
24
|
+
description: "By default it'll be 30 min post start time",
|
|
25
|
+
required: false,
|
|
26
|
+
}),
|
|
27
|
+
location: Property.ShortText({
|
|
28
|
+
displayName: 'Location',
|
|
29
|
+
required: false,
|
|
30
|
+
}),
|
|
31
|
+
/*attachment: Property.ShortText({
|
|
32
|
+
displayName: 'Attachment',
|
|
33
|
+
description: 'URL of the file to be attached',
|
|
34
|
+
required: false,
|
|
35
|
+
}),*/
|
|
36
|
+
description: Property.LongText({
|
|
37
|
+
displayName: 'Description',
|
|
38
|
+
description: 'Description of the event. You can use HTML tags here.',
|
|
39
|
+
required: false,
|
|
40
|
+
}),
|
|
41
|
+
colorId: googleCalendarCommon.colorId,
|
|
42
|
+
attendees: Property.Array({
|
|
43
|
+
displayName: 'Attendees',
|
|
44
|
+
description: 'Emails of the attendees (guests)',
|
|
45
|
+
required: false,
|
|
46
|
+
}),
|
|
47
|
+
guests_can_modify: Property.Checkbox({
|
|
48
|
+
displayName: 'Guests can modify',
|
|
49
|
+
defaultValue: false,
|
|
50
|
+
required: false,
|
|
51
|
+
}),
|
|
52
|
+
guests_can_invite_others: Property.Checkbox({
|
|
53
|
+
displayName: 'Guests can invite others',
|
|
54
|
+
defaultValue: false,
|
|
55
|
+
required: false,
|
|
56
|
+
}),
|
|
57
|
+
guests_can_see_other_guests: Property.Checkbox({
|
|
58
|
+
displayName: 'Guests can see other guests',
|
|
59
|
+
defaultValue: false,
|
|
60
|
+
required: false,
|
|
61
|
+
}),
|
|
62
|
+
send_notifications: Property.StaticDropdown({
|
|
63
|
+
displayName: 'Send Notifications',
|
|
64
|
+
defaultValue: 'all',
|
|
65
|
+
options: {
|
|
66
|
+
options: [
|
|
67
|
+
{ label: 'Yes, to everyone', value: 'all' },
|
|
68
|
+
{
|
|
69
|
+
label: 'To non-Google Calendar guests only',
|
|
70
|
+
value: 'externalOnly',
|
|
71
|
+
},
|
|
72
|
+
{ label: 'To no one', value: 'none' },
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
required: true,
|
|
76
|
+
}),
|
|
77
|
+
create_meet_link: Property.Checkbox({
|
|
78
|
+
displayName: 'Create Google Meet Link',
|
|
79
|
+
description: 'Automatically create a Google Meet video conference link for this event',
|
|
80
|
+
defaultValue: false,
|
|
81
|
+
required: false,
|
|
82
|
+
}),
|
|
83
|
+
},
|
|
84
|
+
async run(configValue) {
|
|
85
|
+
// docs: https://developers.google.com/calendar/api/v3/reference/events/insert
|
|
86
|
+
const {
|
|
87
|
+
calendar_id: calendarId,
|
|
88
|
+
title: summary,
|
|
89
|
+
start_date_time,
|
|
90
|
+
end_date_time,
|
|
91
|
+
location,
|
|
92
|
+
description,
|
|
93
|
+
colorId,
|
|
94
|
+
guests_can_modify: guestsCanModify,
|
|
95
|
+
guests_can_invite_others: guestsCanInviteOthers,
|
|
96
|
+
guests_can_see_other_guests: guestsCanSeeOtherGuests,
|
|
97
|
+
create_meet_link: createMeetLink,
|
|
98
|
+
} = configValue.propsValue;
|
|
99
|
+
|
|
100
|
+
const start = {
|
|
101
|
+
dateTime: dayjs(start_date_time).format('YYYY-MM-DDTHH:mm:ss.sssZ'),
|
|
102
|
+
};
|
|
103
|
+
const endTime = end_date_time
|
|
104
|
+
? end_date_time
|
|
105
|
+
: dayjs(start_date_time).add(30, 'm');
|
|
106
|
+
const end = {
|
|
107
|
+
dateTime: dayjs(endTime).format('YYYY-MM-DDTHH:mm:ss.sssZ'),
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/*const attachment = {
|
|
111
|
+
fileUrl: configValue.propsValue.attachment,
|
|
112
|
+
};*/
|
|
113
|
+
|
|
114
|
+
const attendeesArray = configValue.propsValue.attendees as string[];
|
|
115
|
+
|
|
116
|
+
const sendNotifications = configValue.propsValue.send_notifications;
|
|
117
|
+
|
|
118
|
+
const attendeesObject = [];
|
|
119
|
+
if (attendeesArray) {
|
|
120
|
+
for (const attendee of attendeesArray) {
|
|
121
|
+
attendeesObject.push({ email: attendee });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const authClient = await createGoogleClient(configValue.auth);
|
|
126
|
+
|
|
127
|
+
const calendar = google.calendar({ version: 'v3', auth: authClient });
|
|
128
|
+
|
|
129
|
+
const requestBody: any = {
|
|
130
|
+
summary,
|
|
131
|
+
start,
|
|
132
|
+
end,
|
|
133
|
+
colorId,
|
|
134
|
+
//attachments: configValue.propsValue.attachment ? [attachment] : [],
|
|
135
|
+
location: location ?? '',
|
|
136
|
+
description: description ?? '',
|
|
137
|
+
attendees: attendeesObject,
|
|
138
|
+
guestsCanInviteOthers,
|
|
139
|
+
guestsCanModify,
|
|
140
|
+
guestsCanSeeOtherGuests,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
if (createMeetLink) {
|
|
144
|
+
requestBody.conferenceData = {
|
|
145
|
+
createRequest: {
|
|
146
|
+
conferenceSolutionKey: {
|
|
147
|
+
type: 'hangoutsMeet',
|
|
148
|
+
},
|
|
149
|
+
requestId: randomUUID(),
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const response = await calendar.events.insert({
|
|
155
|
+
calendarId,
|
|
156
|
+
sendUpdates: sendNotifications,
|
|
157
|
+
conferenceDataVersion: createMeetLink ? 1 : 0,
|
|
158
|
+
requestBody,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return response.data;
|
|
162
|
+
},
|
|
163
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createAction, Property } from '@guayaba/workflows-framework';
|
|
2
|
+
import {
|
|
3
|
+
HttpRequest,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
AuthenticationType,
|
|
6
|
+
httpClient,
|
|
7
|
+
} from '@guayaba/workflows-common';
|
|
8
|
+
import { googleCalendarCommon, googleCalendarAuth, getAccessToken } from '../common';
|
|
9
|
+
|
|
10
|
+
export const createQuickCalendarEvent = createAction({
|
|
11
|
+
auth: googleCalendarAuth,
|
|
12
|
+
name: 'create_quick_event',
|
|
13
|
+
description: 'Add Quick Calendar Event',
|
|
14
|
+
displayName: 'Create Quick Event',
|
|
15
|
+
props: {
|
|
16
|
+
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
|
|
17
|
+
text: Property.LongText({
|
|
18
|
+
displayName: 'Summary',
|
|
19
|
+
description: 'The text describing the event to be created',
|
|
20
|
+
required: true,
|
|
21
|
+
}),
|
|
22
|
+
send_updates: Property.StaticDropdown<string>({
|
|
23
|
+
displayName: 'Send Updates',
|
|
24
|
+
description:
|
|
25
|
+
'Guests who should receive notifications about the creation of the new event.',
|
|
26
|
+
required: false,
|
|
27
|
+
options: {
|
|
28
|
+
disabled: false,
|
|
29
|
+
options: [
|
|
30
|
+
{
|
|
31
|
+
label: 'All',
|
|
32
|
+
value: 'all',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'External Only',
|
|
36
|
+
value: 'externalOnly',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'none',
|
|
40
|
+
value: 'none',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
},
|
|
46
|
+
async run(configValue) {
|
|
47
|
+
// docs: https://developers.google.com/calendar/api/v3/reference/events/quickAdd
|
|
48
|
+
const calendarId = configValue.propsValue['calendar_id'];
|
|
49
|
+
const url = `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events/quickAdd`;
|
|
50
|
+
const qParams: Record<string, string> = {
|
|
51
|
+
text: configValue.propsValue['text'],
|
|
52
|
+
sendUpdates: configValue.propsValue['send_updates'] || 'none',
|
|
53
|
+
};
|
|
54
|
+
const request: HttpRequest<Record<string, unknown>> = {
|
|
55
|
+
method: HttpMethod.POST,
|
|
56
|
+
url,
|
|
57
|
+
body: {},
|
|
58
|
+
authentication: {
|
|
59
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
60
|
+
token: await getAccessToken(configValue.auth),
|
|
61
|
+
},
|
|
62
|
+
queryParams: qParams,
|
|
63
|
+
};
|
|
64
|
+
return await httpClient.sendRequest(request);
|
|
65
|
+
},
|
|
66
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Property, createAction } from '@guayaba/workflows-framework';
|
|
2
|
+
import { google } from 'googleapis';
|
|
3
|
+
import { googleCalendarCommon, googleCalendarAuth, createGoogleClient } from '../common';
|
|
4
|
+
|
|
5
|
+
export const deleteEventAction = createAction({
|
|
6
|
+
displayName: 'Delete Event',
|
|
7
|
+
auth: googleCalendarAuth,
|
|
8
|
+
name: 'delete_event',
|
|
9
|
+
description: 'Deletes an event from Google Calendar.',
|
|
10
|
+
props: {
|
|
11
|
+
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
|
|
12
|
+
eventId: Property.ShortText({
|
|
13
|
+
displayName: 'Event ID',
|
|
14
|
+
required: true,
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
17
|
+
async run(context) {
|
|
18
|
+
const authClient = await createGoogleClient(context.auth);
|
|
19
|
+
|
|
20
|
+
const calendarId = context.propsValue.calendar_id;
|
|
21
|
+
const eventId = context.propsValue.eventId;
|
|
22
|
+
|
|
23
|
+
const calendar = google.calendar({ version: 'v3', auth: authClient });
|
|
24
|
+
|
|
25
|
+
const response = await calendar.events.delete({
|
|
26
|
+
calendarId,
|
|
27
|
+
eventId,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return response.data;
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createAction, Property } from '@guayaba/workflows-framework';
|
|
2
|
+
import { HttpRequest, HttpMethod, AuthenticationType, httpClient } from '@guayaba/workflows-common';
|
|
3
|
+
import { googleCalendarCommon, googleCalendarAuth, getAccessToken, GoogleCalendarAuthValue } from '../common';
|
|
4
|
+
import { getCalendars } from '../common/helper';
|
|
5
|
+
import dayjs from 'dayjs';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
interface FreeBusyResponse {
|
|
9
|
+
kind: 'calendar#freeBusy';
|
|
10
|
+
timeMin: string;
|
|
11
|
+
timeMax: string;
|
|
12
|
+
calendars: {
|
|
13
|
+
[calendarId: string]: {
|
|
14
|
+
busy: {
|
|
15
|
+
start: string;
|
|
16
|
+
end: string;
|
|
17
|
+
}[];
|
|
18
|
+
errors?: {
|
|
19
|
+
domain: string;
|
|
20
|
+
reason: string;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const findFreeBusy = createAction({
|
|
27
|
+
auth: googleCalendarAuth,
|
|
28
|
+
name: 'google_calendar_find_busy_free_periods',
|
|
29
|
+
displayName: 'Find Busy/Free Periods in Calendar',
|
|
30
|
+
description: 'Finds free/busy calendar details from Google Calendar.',
|
|
31
|
+
props: {
|
|
32
|
+
calendar_ids: Property.MultiSelectDropdown({
|
|
33
|
+
auth: googleCalendarAuth,
|
|
34
|
+
displayName: 'Calendars',
|
|
35
|
+
description: 'Select the calendars to check for busy periods.',
|
|
36
|
+
required: true,
|
|
37
|
+
refreshers: [],
|
|
38
|
+
options: async ({ auth }) => {
|
|
39
|
+
if (!auth) {
|
|
40
|
+
return {
|
|
41
|
+
disabled: true,
|
|
42
|
+
placeholder: 'Connect your account first',
|
|
43
|
+
options: [],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const authProp = auth as GoogleCalendarAuthValue;
|
|
47
|
+
const calendars = await getCalendars(authProp);
|
|
48
|
+
return {
|
|
49
|
+
disabled: false,
|
|
50
|
+
options: calendars.map((calendar) => {
|
|
51
|
+
return {
|
|
52
|
+
label: calendar.summary,
|
|
53
|
+
value: calendar.id,
|
|
54
|
+
};
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
start_date: Property.DateTime({
|
|
60
|
+
displayName: 'Start Time',
|
|
61
|
+
description: 'The start of the time range to check.',
|
|
62
|
+
required: true,
|
|
63
|
+
}),
|
|
64
|
+
end_date: Property.DateTime({
|
|
65
|
+
displayName: 'End Time',
|
|
66
|
+
description: 'The end of the time range to check.',
|
|
67
|
+
required: true,
|
|
68
|
+
}),
|
|
69
|
+
},
|
|
70
|
+
async run(context) {
|
|
71
|
+
const { calendar_ids, start_date, end_date } = context.propsValue;
|
|
72
|
+
const access_token = await getAccessToken(context.auth);
|
|
73
|
+
|
|
74
|
+
const requestBody = {
|
|
75
|
+
|
|
76
|
+
timeMin: dayjs(start_date).toISOString(),
|
|
77
|
+
timeMax: dayjs(end_date).toISOString(),
|
|
78
|
+
|
|
79
|
+
items: calendar_ids.map((id) => ({ id })),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const request: HttpRequest = {
|
|
83
|
+
method: HttpMethod.POST,
|
|
84
|
+
url: `${googleCalendarCommon.baseUrl}/freeBusy`,
|
|
85
|
+
body: requestBody,
|
|
86
|
+
authentication: {
|
|
87
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
88
|
+
token: access_token,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const response = await httpClient.sendRequest<FreeBusyResponse>(request);
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
return response.body;
|
|
96
|
+
},
|
|
97
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createAction, Property } from '@guayaba/workflows-framework';
|
|
2
|
+
import {
|
|
3
|
+
HttpRequest,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
AuthenticationType,
|
|
6
|
+
httpClient,
|
|
7
|
+
} from '@guayaba/workflows-common';
|
|
8
|
+
import { googleCalendarCommon, googleCalendarAuth, getAccessToken } from '../common';
|
|
9
|
+
import { GoogleCalendarEvent } from '../common/types';
|
|
10
|
+
|
|
11
|
+
export const getEventById = createAction({
|
|
12
|
+
auth: googleCalendarAuth,
|
|
13
|
+
name: 'google_calendar_get_event_by_id',
|
|
14
|
+
displayName: 'Get Event by ID',
|
|
15
|
+
description: 'Fetch event details by its unique ID from Google Calendar.',
|
|
16
|
+
props: {
|
|
17
|
+
calendar_id: googleCalendarCommon.calendarDropdown(),
|
|
18
|
+
event_id: Property.ShortText({
|
|
19
|
+
displayName: 'Event ID',
|
|
20
|
+
description:
|
|
21
|
+
'The unique ID of the event (e.g., "abc123def456"). You can find this in the event URL or from other calendar actions.',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
max_attendees: Property.Number({
|
|
25
|
+
displayName: 'Max Attendees',
|
|
26
|
+
description:
|
|
27
|
+
'Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.',
|
|
28
|
+
required: false,
|
|
29
|
+
}),
|
|
30
|
+
time_zone: Property.ShortText({
|
|
31
|
+
displayName: 'Time Zone',
|
|
32
|
+
description:
|
|
33
|
+
'Time zone for the response (e.g., "America/New_York", "Europe/London"). Defaults to the calendar\'s time zone if not specified.',
|
|
34
|
+
required: false,
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
async run(context) {
|
|
38
|
+
const {
|
|
39
|
+
calendar_id: calendarId,
|
|
40
|
+
event_id: eventId,
|
|
41
|
+
max_attendees: maxAttendees,
|
|
42
|
+
time_zone: timeZone,
|
|
43
|
+
} = context.propsValue;
|
|
44
|
+
const token = await getAccessToken(context.auth);
|
|
45
|
+
|
|
46
|
+
if (
|
|
47
|
+
!calendarId ||
|
|
48
|
+
typeof calendarId !== 'string' ||
|
|
49
|
+
calendarId.trim().length === 0
|
|
50
|
+
) {
|
|
51
|
+
throw new Error('Calendar ID is required');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
!eventId ||
|
|
56
|
+
typeof eventId !== 'string' ||
|
|
57
|
+
eventId.trim().length === 0
|
|
58
|
+
) {
|
|
59
|
+
throw new Error('Event ID cannot be empty');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (eventId.length < 5 || eventId.length > 1024) {
|
|
63
|
+
throw new Error('Event ID must be between 5 and 1024 characters');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const queryParams: Record<string, string> = {};
|
|
67
|
+
|
|
68
|
+
if (maxAttendees !== undefined && maxAttendees > 0) {
|
|
69
|
+
queryParams.maxAttendees = maxAttendees.toString();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (
|
|
73
|
+
timeZone &&
|
|
74
|
+
typeof timeZone === 'string' &&
|
|
75
|
+
timeZone.trim().length > 0
|
|
76
|
+
) {
|
|
77
|
+
queryParams.timeZone = timeZone.trim();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const url = `${googleCalendarCommon.baseUrl}/calendars/${encodeURIComponent(
|
|
81
|
+
calendarId.trim()
|
|
82
|
+
)}/events/${encodeURIComponent(eventId.trim())}`;
|
|
83
|
+
|
|
84
|
+
const request: HttpRequest = {
|
|
85
|
+
method: HttpMethod.GET,
|
|
86
|
+
url: url,
|
|
87
|
+
queryParams: queryParams,
|
|
88
|
+
authentication: {
|
|
89
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
90
|
+
token: token,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const response = await httpClient.sendRequest<GoogleCalendarEvent>(
|
|
96
|
+
request
|
|
97
|
+
);
|
|
98
|
+
return response.body;
|
|
99
|
+
} catch (error: any) {
|
|
100
|
+
if (error.response?.status === 404) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Event with ID "${eventId}" not found in calendar "${calendarId}". Please verify the event ID and calendar selection.`
|
|
103
|
+
);
|
|
104
|
+
} else if (error.response?.status === 403) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Access denied to event "${eventId}" in calendar "${calendarId}". Please check your permissions.`
|
|
107
|
+
);
|
|
108
|
+
} else if (error.response?.status === 400) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Invalid request parameters. Please check the event ID format and other parameters.`
|
|
111
|
+
);
|
|
112
|
+
} else if (error.response?.status === 401) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
'Authentication failed. Please reconnect your Google Calendar account.'
|
|
115
|
+
);
|
|
116
|
+
} else {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`Failed to fetch event: ${error.message || 'Unknown error occurred'}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createAction, Property } from '@guayaba/workflows-framework';
|
|
2
|
+
import {
|
|
3
|
+
HttpRequest,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
AuthenticationType,
|
|
6
|
+
httpClient,
|
|
7
|
+
} from '@guayaba/workflows-common';
|
|
8
|
+
import { googleCalendarCommon, googleCalendarAuth, getAccessToken } from '../common';
|
|
9
|
+
import dayjs from 'dayjs';
|
|
10
|
+
|
|
11
|
+
export const getEvents = createAction({
|
|
12
|
+
auth: googleCalendarAuth,
|
|
13
|
+
name: 'google_calendar_get_events',
|
|
14
|
+
description: 'Get Events',
|
|
15
|
+
displayName: 'Get all Events',
|
|
16
|
+
props: {
|
|
17
|
+
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
|
|
18
|
+
event_types: Property.StaticMultiSelectDropdown({
|
|
19
|
+
displayName: 'Event types',
|
|
20
|
+
description: 'Select event types',
|
|
21
|
+
required: true,
|
|
22
|
+
defaultValue: ['default', 'focusTime', 'outOfOffice'],
|
|
23
|
+
options: {
|
|
24
|
+
options: [
|
|
25
|
+
{
|
|
26
|
+
label: 'Default',
|
|
27
|
+
value: 'default',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
label: 'Out Of Office',
|
|
31
|
+
value: 'outOfOffice',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Focus Time',
|
|
35
|
+
value: 'focusTime',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
label: 'Working Location',
|
|
39
|
+
value: 'workingLocation',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
}),
|
|
44
|
+
search: Property.ShortText({
|
|
45
|
+
displayName: 'Search Term',
|
|
46
|
+
required: false,
|
|
47
|
+
}),
|
|
48
|
+
start_date: Property.DateTime({
|
|
49
|
+
displayName: 'Date from',
|
|
50
|
+
required: false,
|
|
51
|
+
}),
|
|
52
|
+
end_date: Property.DateTime({
|
|
53
|
+
displayName: 'Date to',
|
|
54
|
+
required: false,
|
|
55
|
+
}),
|
|
56
|
+
singleEvents: Property.Checkbox({
|
|
57
|
+
displayName: 'Expand Recurring Event?',
|
|
58
|
+
description: "Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves.",
|
|
59
|
+
required: true,
|
|
60
|
+
defaultValue: false,
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
async run(configValue) {
|
|
64
|
+
// docs: https://developers.google.com/calendar/api/v3/reference/events/list
|
|
65
|
+
const {
|
|
66
|
+
calendar_id: calendarId,
|
|
67
|
+
start_date,
|
|
68
|
+
end_date,
|
|
69
|
+
search,
|
|
70
|
+
event_types,
|
|
71
|
+
singleEvents,
|
|
72
|
+
} = configValue.propsValue;
|
|
73
|
+
const token = await getAccessToken(configValue.auth);
|
|
74
|
+
const queryParams: Record<string, string> = { showDeleted: 'false' };
|
|
75
|
+
let url = `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events`;
|
|
76
|
+
|
|
77
|
+
if(singleEvents !== null) {
|
|
78
|
+
queryParams['singleEvents'] = singleEvents ? 'true' : 'false';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (search) {
|
|
82
|
+
queryParams['q'] = `"${search}"`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// date range
|
|
86
|
+
if (start_date) {
|
|
87
|
+
queryParams['timeMin'] = dayjs(start_date).format(
|
|
88
|
+
'YYYY-MM-DDTHH:mm:ss.sssZ'
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
if (start_date && end_date) {
|
|
92
|
+
queryParams['timeMax'] = dayjs(end_date).format(
|
|
93
|
+
'YYYY-MM-DDTHH:mm:ss.sssZ'
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
// filter by event type
|
|
97
|
+
if (event_types.length > 0) {
|
|
98
|
+
url += `?${event_types.map((type) => `eventTypes=${type}`).join('&')}`;
|
|
99
|
+
}
|
|
100
|
+
const request: HttpRequest<Record<string, unknown>> = {
|
|
101
|
+
method: HttpMethod.GET,
|
|
102
|
+
url,
|
|
103
|
+
queryParams,
|
|
104
|
+
authentication: {
|
|
105
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
106
|
+
token,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
return await httpClient.sendRequest(request);
|
|
110
|
+
},
|
|
111
|
+
});
|