chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import { default as sdk, z } from '@botpress/sdk'
|
||||
import * as entities from './entities'
|
||||
|
||||
export const actions = {
|
||||
listEvents: {
|
||||
title: 'List Events',
|
||||
description: 'Retrieves events from the calendar.',
|
||||
input: {
|
||||
schema: z.object({
|
||||
count: z
|
||||
.number()
|
||||
.min(1)
|
||||
.max(2500)
|
||||
.default(100)
|
||||
.title('Number of events to retrieve')
|
||||
.describe('The maximum number of events to return. Defaults to 100.'),
|
||||
pageToken: z.string().title('Page token').optional().describe('Token specifying which result page to return.'),
|
||||
timeMin: z
|
||||
.string()
|
||||
.title('On or after')
|
||||
.optional()
|
||||
.describe(
|
||||
'Only return events occurring on or after this date. Must be in RFC3339 format. Defaults to now if not specified.'
|
||||
),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
events: z
|
||||
.array(entities.Event.schema.title('Event').describe('The calendar event data.'))
|
||||
.title('Events')
|
||||
.describe('The list of calendar events.'),
|
||||
nextPageToken: z
|
||||
.string()
|
||||
.title('Next page token')
|
||||
.optional()
|
||||
.describe('Token used to access the next page of this result. Omitted if no further results are available.'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
createEvent: {
|
||||
title: 'Create Event',
|
||||
description: 'Creates a new event in the calendar.',
|
||||
input: {
|
||||
schema: entities.Event.schema
|
||||
.omit({ eventType: true, htmlLink: true, id: true, conferenceLink: true })
|
||||
.extend({
|
||||
attendees: z
|
||||
.array(
|
||||
z.object({
|
||||
email: z.string().email().title('Email').describe('The email address of the attendee.'),
|
||||
displayName: z
|
||||
.string()
|
||||
.title('Display Name')
|
||||
.optional()
|
||||
.describe('The name of the attendee. Optional.'),
|
||||
optional: z
|
||||
.boolean()
|
||||
.title('Optional Attendee')
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe('Whether this is an optional attendee. Optional. The default is False.'),
|
||||
})
|
||||
)
|
||||
.title('Attendees')
|
||||
.optional()
|
||||
.describe('List of attendees for the event. Email invitations will be sent automatically.'),
|
||||
})
|
||||
.title('New Event')
|
||||
.describe('The definition of the new event.'),
|
||||
},
|
||||
output: {
|
||||
schema: entities.Event.schema.title('Created Event').describe('The data of the new event.'),
|
||||
},
|
||||
},
|
||||
|
||||
updateEvent: {
|
||||
title: 'Update Event',
|
||||
description: 'Updates an existing event in the calendar. Omitted properties are left unchanged.',
|
||||
input: {
|
||||
schema: entities.Event.schema.omit({ eventType: true, htmlLink: true, conferenceLink: true }).extend({
|
||||
id: z.string().title('Event ID').describe('The ID of the calendar event to update.'),
|
||||
attendees: z
|
||||
.array(
|
||||
z.object({
|
||||
email: z.string().email().title('Email').describe('The email address of the attendee.'),
|
||||
displayName: z.string().title('Display Name').optional().describe('The name of the attendee. Optional.'),
|
||||
optional: z
|
||||
.boolean()
|
||||
.title('Optional Attendee')
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe('Whether this is an optional attendee. Optional. The default is False.'),
|
||||
})
|
||||
)
|
||||
.title('Attendees')
|
||||
.optional()
|
||||
.describe('List of attendees for the event.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: entities.Event.schema.title('Updated Event').describe('The data of the event.'),
|
||||
},
|
||||
},
|
||||
|
||||
deleteEvent: {
|
||||
title: 'Delete Event',
|
||||
description: 'Deletes an event from the calendar.',
|
||||
input: {
|
||||
schema: z.object({
|
||||
eventId: z.string().title('Event ID').describe('The ID of the calendar event to delete.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
},
|
||||
checkAvailability: {
|
||||
title: 'Check Availability',
|
||||
description: 'Checks calendar availability and returns free time slots for the specified date range.',
|
||||
input: {
|
||||
schema: z.object({
|
||||
timeMin: z
|
||||
.string()
|
||||
.title('Start Time')
|
||||
.describe('Start of the time range to check (ISO 8601 format, e.g., "2025-11-05T09:00:00-04:00").'),
|
||||
timeMax: z
|
||||
.string()
|
||||
.title('End Time')
|
||||
.describe('End of the time range to check (ISO 8601 format, e.g., "2025-11-05T17:00:00-04:00").'),
|
||||
slotDurationMinutes: z
|
||||
.number()
|
||||
.min(15)
|
||||
.max(480)
|
||||
.default(45)
|
||||
.title('Slot Duration (minutes)')
|
||||
.describe('Duration of each time slot in minutes. Defaults to 45 minutes.'),
|
||||
timezone: z
|
||||
.string()
|
||||
.default('America/Toronto')
|
||||
.title('Timezone')
|
||||
.describe('Timezone for formatting output (e.g., "America/Toronto"). Defaults to America/Toronto.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
freeSlots: z
|
||||
.array(
|
||||
z.object({
|
||||
start: z.string().title('Start Time').describe('ISO 8601 formatted start time of the free slot.'),
|
||||
end: z.string().title('End Time').describe('ISO 8601 formatted end time of the free slot.'),
|
||||
})
|
||||
)
|
||||
.title('Free Slots')
|
||||
.describe('Array of available time slots in ISO format.'),
|
||||
formattedFreeSlots: z
|
||||
.array(z.string())
|
||||
.title('Formatted Free Slots')
|
||||
.describe('Array of human-readable formatted free slots (e.g., "9:00 AM – 9:45 AM").'),
|
||||
busySlots: z
|
||||
.array(
|
||||
z.object({
|
||||
start: z.string().title('Start Time').describe('ISO 8601 formatted start time of the busy slot.'),
|
||||
end: z.string().title('End Time').describe('ISO 8601 formatted end time of the busy slot.'),
|
||||
})
|
||||
)
|
||||
.title('Busy Slots')
|
||||
.describe('Array of busy time slots in ISO format.'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['actions']
|
||||
@@ -0,0 +1,45 @@
|
||||
import { default as sdk, z } from '@botpress/sdk'
|
||||
|
||||
const _commonConfig = {
|
||||
calendarId: z
|
||||
.string()
|
||||
.title('Calendar ID')
|
||||
.min(1)
|
||||
.describe('The ID of the Google Calendar to interact with. You can find it in your Google Calendar settings.'),
|
||||
} as const
|
||||
|
||||
export const configuration = {
|
||||
schema: z.object({
|
||||
..._commonConfig,
|
||||
}),
|
||||
identifier: { linkTemplateScript: 'linkTemplate.vrl', required: true },
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['configuration']
|
||||
|
||||
export const identifier = undefined satisfies sdk.IntegrationDefinitionProps['identifier']
|
||||
|
||||
export const configurations = {
|
||||
serviceAccountKey: {
|
||||
title: 'Manual configuration',
|
||||
description: 'Configure manually with a Service Account Key',
|
||||
schema: z.object({
|
||||
..._commonConfig,
|
||||
privateKey: z
|
||||
.string()
|
||||
.title('Service account private key')
|
||||
.min(1)
|
||||
.describe('The private key from the Google service account. You can get it from the downloaded JSON file.'),
|
||||
clientEmail: z
|
||||
.string()
|
||||
.title('Service account email')
|
||||
.email()
|
||||
.describe('The client email from the Google service account. You can get it from the downloaded JSON file.'),
|
||||
impersonateEmail: z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Impersonate email')
|
||||
.describe(
|
||||
"The email of the user to impersonate. This is the email of the user you want to impersonate. It's mandatory for inviting people or creating meetings."
|
||||
),
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['configurations']
|
||||
@@ -0,0 +1,117 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
// documentation: https://developers.google.com/calendar/api/v3/reference/events#resource
|
||||
|
||||
export namespace Event {
|
||||
const _fields = {
|
||||
id: z.string().title('Event ID').describe('Opaque identifier of the event.'),
|
||||
summary: z.string().title('Summary').describe('Title of the event.'),
|
||||
description: z
|
||||
.string()
|
||||
.title('Description')
|
||||
.optional()
|
||||
.describe('Description of the event. Can contain HTML. Optional.'),
|
||||
location: z
|
||||
.string()
|
||||
.title('Location')
|
||||
.optional()
|
||||
.describe('Geographic location of the event as free-form text. Optional. (e.g., "Meeting Room").'),
|
||||
startDateTime: z
|
||||
.string()
|
||||
.title('Start Date/Time')
|
||||
.describe('The start date and time in RFC3339 format (e.g., "2023-12-31T10:00:00.000Z").'),
|
||||
endDateTime: z
|
||||
.string()
|
||||
.title('End Date/Time')
|
||||
.describe('The end date and time in RFC3339 format (e.g., "2023-12-31T12:00:00.000Z").'),
|
||||
colorId: z.string().title('Color ID').optional().describe('The color ID of the event. Optional.'),
|
||||
eventType: z
|
||||
.enum(['default', 'birthday', 'focusTime', 'fromGmail', 'outOfOffice', 'workingLocation'])
|
||||
.title('Event Type')
|
||||
.describe('Specific type of the event. This cannot be modified after the event is created.'),
|
||||
guestsCanInviteOthers: z
|
||||
.boolean()
|
||||
.title('Guests Can Invite Others')
|
||||
.optional()
|
||||
.default(true)
|
||||
.describe(
|
||||
'Whether attendees other than the organizer can invite others to the event. Optional. The default is True.'
|
||||
),
|
||||
guestsCanSeeOtherGuests: z
|
||||
.boolean()
|
||||
.title('Guests Can See Other Guests')
|
||||
.optional()
|
||||
.default(true)
|
||||
.describe(
|
||||
"Whether attendees other than the organizer can see who the event's attendees are. Optional. The default is True."
|
||||
),
|
||||
htmlLink: z.string().title('HTML Link').describe('URL of the event page in the Google Calendar Web UI.'),
|
||||
recurrence: z
|
||||
.array(
|
||||
z
|
||||
.string()
|
||||
.title('RFC5545 line')
|
||||
.describe(
|
||||
'RRULE, EXRULE, RDATE or EXDATE line, as specified in RFC5545. Note that DTSTART and DTEND lines are not allowed in this field'
|
||||
)
|
||||
)
|
||||
.title('Recurrence')
|
||||
.optional()
|
||||
.describe(
|
||||
'List of RRULE, EXRULE, RDATE and EXDATE lines for a recurring event, as specified in RFC5545. This field is omitted for single events or instances of recurring events.'
|
||||
),
|
||||
status: z
|
||||
.enum(['confirmed', 'tentative', 'cancelled'])
|
||||
.title('Event Status')
|
||||
.optional()
|
||||
.default('confirmed')
|
||||
.describe('Status of the event. Optional. The default value is "confirmed".'),
|
||||
visibility: z
|
||||
.enum(['default', 'public', 'private', 'confidential'])
|
||||
.title('Event Visibility')
|
||||
.optional()
|
||||
.default('default')
|
||||
.describe('Visibility of the event. Optional. The default value is "default".'),
|
||||
enableGoogleMeet: z
|
||||
.boolean()
|
||||
.title('Enable Google Meet')
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe('Whether to enable Google Meet for the event. Optional. The default value is false.'),
|
||||
sendNotifications: z
|
||||
.boolean()
|
||||
.title('Send Notifications')
|
||||
.optional()
|
||||
.default(true)
|
||||
.describe('Whether to send notifications to attendees. Optional. The default value is true.'),
|
||||
attendees: z
|
||||
.array(
|
||||
z.object({
|
||||
email: z.string().title('Email').describe('The email address of the attendee.'),
|
||||
displayName: z.string().title('Display Name').optional().describe('The name of the attendee. Optional.'),
|
||||
optional: z
|
||||
.boolean()
|
||||
.title('Optional Attendee')
|
||||
.optional()
|
||||
.default(false)
|
||||
.describe('Whether this is an optional attendee. Optional. The default is False.'),
|
||||
responseStatus: z
|
||||
.enum(['needsAction', 'declined', 'tentative', 'accepted'])
|
||||
.title('Response Status')
|
||||
.optional()
|
||||
.describe("The attendee's response status. Read-only when creating events."),
|
||||
})
|
||||
)
|
||||
.title('Attendees')
|
||||
.optional()
|
||||
.describe('List of attendees for the event. Email invitations will be sent automatically.'),
|
||||
conferenceLink: z
|
||||
.string()
|
||||
.title('Conference Link')
|
||||
.optional()
|
||||
.describe('The Google Meet link for the event. This is automatically generated when enableGoogleMeet is true.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type inferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
import { Event } from './event'
|
||||
export { Event }
|
||||
|
||||
export const entities = {
|
||||
event: {
|
||||
title: 'Google Calendar Event',
|
||||
description: 'An event in a Google Calendar',
|
||||
schema: Event.schema,
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['entities']
|
||||
@@ -0,0 +1,3 @@
|
||||
import { default as sdk } from '@botpress/sdk'
|
||||
|
||||
export const events = {} as const satisfies sdk.IntegrationDefinitionProps['events']
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './actions'
|
||||
export * from './configuration'
|
||||
export * from './entities'
|
||||
export * from './events'
|
||||
export * from './secrets'
|
||||
export * from './states'
|
||||
@@ -0,0 +1,8 @@
|
||||
import { posthogHelper } from '@botpress/common'
|
||||
import { default as sdk } from '@botpress/sdk'
|
||||
|
||||
export const secrets = {
|
||||
...posthogHelper.COMMON_SECRET_NAMES,
|
||||
CLIENT_ID: { description: 'Google OAuth Client ID' },
|
||||
CLIENT_SECRET: { description: 'Google OAuth Client Secret' },
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['secrets']
|
||||
@@ -0,0 +1,13 @@
|
||||
import sdk, { z } from '@botpress/sdk'
|
||||
|
||||
export const states = {
|
||||
oAuthConfig: {
|
||||
type: 'integration',
|
||||
schema: z.object({
|
||||
refreshToken: z
|
||||
.string()
|
||||
.title('Refresh token')
|
||||
.describe('The refresh token to use to authenticate with Google APIs. It gets exchanged for a bearer token'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['states']
|
||||
Reference in New Issue
Block a user