Add Activepieces integration for workflow automation

- Add Activepieces fork with SmoothSchedule custom piece
- Create integrations app with Activepieces service layer
- Add embed token endpoint for iframe integration
- Create Automations page with embedded workflow builder
- Add sidebar visibility fix for embed mode
- Add list inactive customers endpoint to Public API
- Include SmoothSchedule triggers: event created/updated/cancelled
- Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,3 @@
{
"presets": [["@nx/js/babel", { "useBuiltIns": "usage" }]]
}

View File

@@ -0,0 +1,18 @@
{
"extends": ["../../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@@ -0,0 +1,7 @@
# pieces-google-calendar
This library was generated with [Nx](https://nx.dev).
## Running lint
Run `nx lint pieces-google-calendar` to execute the lint via [ESLint](https://eslint.org/).

View File

@@ -0,0 +1,7 @@
{
"name": "@activepieces/piece-google-calendar",
"version": "0.7.4",
"dependencies": {
"googleapis": "129.0.0"
}
}

View File

@@ -0,0 +1,51 @@
{
"name": "pieces-google-calendar",
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/pieces/community/google-calendar/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/packages/pieces/community/google-calendar",
"tsConfig": "packages/pieces/community/google-calendar/tsconfig.lib.json",
"packageJson": "packages/pieces/community/google-calendar/package.json",
"main": "packages/pieces/community/google-calendar/src/index.ts",
"assets": [
"packages/pieces/community/google-calendar/*.md",
{
"input": "packages/pieces/community/google-calendar/src/i18n",
"output": "./src/i18n",
"glob": "**/!(i18n.json)"
}
],
"buildableProjectDepsInPackageJsonType": "dependencies",
"updateBuildableProjectDepsInPackageJson": true
},
"dependsOn": [
"^build",
"prebuild"
]
},
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
]
},
"prebuild": {
"executor": "nx:run-commands",
"options": {
"cwd": "packages/pieces/community/google-calendar",
"command": "bun install --no-save --silent"
},
"dependsOn": [
"^build"
]
}
},
"tags": []
}

View File

@@ -0,0 +1,71 @@
{
"Google Calendar": "Google Calendar",
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "Description",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Select event types": "Select event types",
"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.": "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.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"All": "All",
"External Only": "External Only",
"none": "none",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "New or Updated Event",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event."
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Organisieren Sie sich und bleiben Sie planmäßig",
"Add Attendees to Event": "Teilnehmer zum Event hinzufügen",
"Create Quick Event": "Schnellereignis erstellen",
"Create Event": "Ereignis erstellen",
"Get all Events": "Alle Events abrufen",
"Update Event": "Ereignis aktualisieren",
"Delete Event": "Ereignis löschen",
"Find Busy/Free Periods in Calendar": "Kostenlose Perioden im Kalender finden",
"Get Event by ID": "Event per ID abrufen",
"Custom API Call": "Eigener API-Aufruf",
"Add one or more person to existing event.": "Fügen Sie eine oder mehrere Personen zu einem bestehenden Ereignis hinzu.",
"Add Quick Calendar Event": "Schnellkalenderereignis hinzufügen",
"Add Event": "Neuer Termin",
"Get Events": "Events abrufen",
"Updates an event in Google Calendar.": "Aktualisiert ein Ereignis in Google Kalender.",
"Deletes an event from Google Calendar.": "Löscht ein Ereignis aus Google Kalender.",
"Finds free/busy calendar details from Google Calendar.": "Findet freie/belegte Kalenderdetails aus Google Kalender.",
"Fetch event details by its unique ID from Google Calendar.": "Ereignisdetails anhand seiner eindeutigen ID aus dem Google Kalender abrufen.",
"Make a custom API call to a specific endpoint": "Einen benutzerdefinierten API-Aufruf an einen bestimmten Endpunkt machen",
"Calendar": "Kalender",
"Event ID": "Event-ID",
"Attendees": "Teilnehmer",
"Summary": "Summary",
"Send Updates": "Updates senden",
"Title of the event": "Titel des Ereignisses",
"Start date time of the event": "Startdatum des Ereignisses",
"End date time of the event": "Enddatum des Ereignisses",
"Location": "Standort",
"Description": "Beschreibung",
"Color": "Farbe",
"Guests can modify": "Gäste können ändern",
"Guests can invite others": "Gäste können andere einladen",
"Guests can see other guests": "Gäste können andere Gäste sehen",
"Send Notifications": "Benachrichtigungen senden",
"Create Google Meet Link": "Google-Meet-Link erstellen",
"Event types": "Ereignistypen",
"Search Term": "Suchbegriff",
"Date from": "Datum ab",
"Date to": "Datum bis",
"Expand Recurring Event?": "Wiederkehrendes Ereignis aufklappen?",
"Calendars": "Kalender",
"Start Time": "Startzeit",
"End Time": "Endzeit",
"Max Attendees": "Max. Teilnehmer",
"Time Zone": "Zeitzone",
"Method": "Methode",
"Headers": "Kopfzeilen",
"Query Parameters": "Abfrageparameter",
"Body": "Körper",
"Response is Binary ?": "Antwort ist binär?",
"No Error on Failure": "Kein Fehler bei Fehler",
"Timeout (in seconds)": "Timeout (in Sekunden)",
"Emails of the attendees (guests)": "E-Mails der Teilnehmer (Gäste)",
"The text describing the event to be created": "Der Text, der das zu erstellende Ereignis beschreibt",
"Guests who should receive notifications about the creation of the new event.": "Gäste, die Benachrichtigungen über die Erstellung der neuen Veranstaltung erhalten sollten.",
"By default it'll be 30 min post start time": "Standardmäßig ist es 30 Minuten Beitragsstartzeit",
"Description of the event. You can use HTML tags here.": "Beschreibung des Ereignisses. Hier können HTML-Tags verwendet werden.",
"Automatically create a Google Meet video conference link for this event": "Automatisch einen Google Meet Video-Konferenz-Link für dieses Ereignis erstellen",
"Select event types": "Ereignistypen auswählen",
"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.": "Ob wiederkehrende Ereignisse auf Instanzen ausgedehnt werden und nur einmalige Ereignisse und Fälle wiederkehrender Ereignisse zurückgegeben werden sollen, aber nicht die zugrunde liegenden wiederkehrenden Ereignisse selbst.",
"Select the calendars to check for busy periods.": "Wählen Sie die Kalender, die auf belebte Zeiträume überprüft werden sollen.",
"The start of the time range to check.": "Der Beginn des zu überprüfenden Zeitraums.",
"The end of the time range to check.": "Das Ende des zu überprüfenden Zeitraums.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "Die eindeutige ID des Ereignisses (z.B. \"abc123def456\"). Diese finden Sie in der Ereignis-URL oder von anderen Kalender-Aktionen.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Maximale Teilnehmeranzahl, die in der Antwort aufgenommen werden soll. Wenn es mehr Teilnehmer gibt, wird nur der Teilnehmer zurückgegeben.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Zeitzone für die Antwort (z.B. \"America/New_York\", \"Europe/London\"). Standardmäßig wird die Zeitzone des Kalenders angegeben.",
"Authorization headers are injected automatically from your connection.": "Autorisierungs-Header werden automatisch von Ihrer Verbindung injiziert.",
"Enable for files like PDFs, images, etc..": "Aktivieren für Dateien wie PDFs, Bilder, etc..",
"All": "Alle",
"External Only": "Nur Externe",
"none": "keine",
"Yes, to everyone": "Ja, an alle",
"To non-Google Calendar guests only": "Nur für Gäste ohne Google Kalender",
"To no one": "An niemand",
"Default": "Standard",
"Out Of Office": "Außerhalb des Amtes",
"Focus Time": "Fokuszeit",
"Working Location": "Arbeitsort",
"GET": "ERHALTEN",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "LÖSCHEN",
"HEAD": "HEAD",
"New or Updated Event": "Neues oder aktualisiertes Ereignis",
"New Event": "Neues Ereignis",
"Event Ends": "Event endet",
"Event Start (Time Before)": "Event-Start (Vorzeige)",
"New Event Matching Search": "Neue Event-Matching Suche",
"Event Cancelled": "Ereignis abgebrochen",
"New Calendar": "Neuer Kalender",
"Triggers when an event is added or updated": "Wird ausgelöst, wenn ein Ereignis hinzugefügt oder aktualisiert wird",
"Fires when a new event is created in a calendar.": "Feuert ab, wenn ein neues Ereignis in einem Kalender erstellt wird.",
"Fires when an event ends.": "Feuert ab, wenn ein Ereignis endet.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Löscht eine bestimmte Zeit vor Beginn eines Ereignisses ab (z.B. eine Erinnerung).",
"Fires when a new event is created that matches a specified search term.": "Feuert ab, wenn ein neues Ereignis erstellt wird, das mit einem bestimmten Suchbegriff übereinstimmt.",
"Fires when an event is canceled or deleted.": "Feuer, wenn ein Ereignis abgebrochen oder gelöscht wird.",
"Fires when a new calendar is created or becomes accessible.": "Feuert ab, wenn ein neuer Kalender erstellt oder zugänglich wird.",
"Event Types to Monitor": "Zu überwachende Ereignistypen",
"Search Filter": "Suchfilter",
"Exclude All-Day Events": "Ganztägige Events ausschließen",
"Target Specific Event": "Zielspezifisches Ereignis",
"Event": "Ereignis",
"Time Before": "Zeit davor",
"Time Unit": "Zeiteinheit",
"Event Types": "Ereignistypen",
"Search In Fields": "Suche in Feldern",
"Cancellation Reasons": "Stornierungsgründe",
"Access Role Filter": "Rollenfilter",
"Calendar Name Filter": "Kalendername Filter",
"Exclude Shared Calendars": "Geteilte Kalender ausschließen",
"If true, the trigger will activate for every occurrence of a recurring event.": "Falls aktiviert, wird der Trigger für jedes Auftreten eines wiederkehrenden Ereignisses aktiviert.",
"Filter by specific event types (leave empty to monitor all event types)": "Nach bestimmten Ereignistypen filtern (leer lassen, um alle Ereignistypen zu überwachen)",
"Only trigger for events containing this text in title, description, or location (optional)": "Trigger nur für Ereignisse, die diesen Text in Titel, Beschreibung oder Ort enthalten (optional)",
"Skip triggering for all-day events": "Auslösen für ganztägige Events überspringen",
"Enable to monitor a specific event instead of all events in the calendar.": "Aktivieren, um ein bestimmtes Ereignis anstelle aller Ereignisse im Kalender zu überwachen.",
"The amount of time before the event starts.": "Die Zeitspanne bevor das Ereignis beginnt.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "Das Schlüsselwort(e) nach dem in neuen Events gesucht werden soll (sucht standardmäßig über Titel, Beschreibung, Ort und Teilnehmer).",
"Filter by specific event types (optional)": "Nach bestimmten Ereignistypen filtern (optional)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Geben Sie die zu durchsuchenden Felder an (lassen Sie leer um die Standardsuche von Google in allen Feldern zu verwenden)",
"Filter by specific types of cancellations (optional)": "Nach bestimmten Arten von Stornierungen filtern (optional)",
"Only trigger for calendars with specific access roles (optional)": "Nur für Kalender mit spezifischen Zugriffsrollen auslösen (optional)",
"Only trigger for calendars containing this text in name or description (optional)": "Trigger nur für Kalender, die diesen Text in Name oder Beschreibung enthalten (optional)",
"Only trigger for calendars you own, not shared calendars": "Nur auslösen für Ihre eigenen Kalender, keine freigegebenen Kalender",
"Default Events": "Standardereignisse",
"Birthday Events": "Geburtstagsereignisse",
"Out of Office": "Außerhalb des Büros",
"From Gmail": "Von Gmail",
"Minutes": "Minuten",
"Hours": "Stunden",
"Days": "Tage",
"Event Title/Summary": "Ereignis-Titel/Zusammenfassung",
"Event Description": "Ereignisbeschreibung",
"Event Location": "Veranstaltungsort",
"Attendee Names/Emails": "Teilnehmernamen/E-Mails",
"Event Deleted": "Ereignis gelöscht",
"Attendee Declined": "Teilnehmer abgelehnt",
"Event Rescheduled": "Event neu geplant",
"Other Cancellations": "Andere Stornierungen",
"Owner": "Besitzer",
"Writer": "Schriftsteller",
"Reader": "Leser",
"Free/Busy Reader": "Kostenlose/Besetzter Reader"
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Organiza y permanece según horario",
"Add Attendees to Event": "Añadir asistentes al evento",
"Create Quick Event": "Crear evento rápido",
"Create Event": "Crear Evento",
"Get all Events": "Obtener todos los eventos",
"Update Event": "Actualizar evento",
"Delete Event": "Eliminar evento",
"Find Busy/Free Periods in Calendar": "Encontrar Períodos ocupados/gratuitos en el calendario",
"Get Event by ID": "Obtener Evento por ID",
"Custom API Call": "Llamada API personalizada",
"Add one or more person to existing event.": "Añadir una o más personas al evento existente.",
"Add Quick Calendar Event": "Añadir evento de calendario rápido",
"Add Event": "Añadir evento",
"Get Events": "Obtener Eventos",
"Updates an event in Google Calendar.": "Actualiza un evento en Google Calendar.",
"Deletes an event from Google Calendar.": "Elimina un evento de Google Calendar.",
"Finds free/busy calendar details from Google Calendar.": "Encuentra información sobre el calendario libre o ocupado en Google Calendar.",
"Fetch event details by its unique ID from Google Calendar.": "Obtener detalles del evento por su ID única de Google Calendar.",
"Make a custom API call to a specific endpoint": "Hacer una llamada API personalizada a un extremo específico",
"Calendar": "Calendario",
"Event ID": "Evento ID",
"Attendees": "Asistentes",
"Summary": "Summary",
"Send Updates": "Enviar actualizaciones",
"Title of the event": "Título del evento",
"Start date time of the event": "Fecha de inicio del evento",
"End date time of the event": "Fecha de fin del evento",
"Location": "Ubicación",
"Description": "Descripción",
"Color": "Color",
"Guests can modify": "Los invitados pueden modificar",
"Guests can invite others": "Los invitados pueden invitar a otros",
"Guests can see other guests": "Los invitados pueden ver a otros invitados",
"Send Notifications": "Enviar notificaciones",
"Create Google Meet Link": "Crear enlace de Google Meet",
"Event types": "Tipos de eventos",
"Search Term": "Buscar término",
"Date from": "Fecha de",
"Date to": "Fecha hasta",
"Expand Recurring Event?": "¿Expandir Evento recurriente?",
"Calendars": "Calendarios",
"Start Time": "Hora de inicio",
"End Time": "Hora de fin",
"Max Attendees": "Máx. asistentes",
"Time Zone": "Zona horaria",
"Method": "Método",
"Headers": "Encabezados",
"Query Parameters": "Parámetros de consulta",
"Body": "Cuerpo",
"Response is Binary ?": "¿Respuesta es binaria?",
"No Error on Failure": "No hay ningún error en fallo",
"Timeout (in seconds)": "Tiempo de espera (en segundos)",
"Emails of the attendees (guests)": "Correos electrónicos de los asistentes (invitados)",
"The text describing the event to be created": "El texto que describe el evento a crear",
"Guests who should receive notifications about the creation of the new event.": "Invitados que deben recibir notificaciones sobre la creación del nuevo evento.",
"By default it'll be 30 min post start time": "Por defecto será 30 minutos de inicio del post",
"Description of the event. You can use HTML tags here.": "Descripción del evento. Puedes usar etiquetas HTML aquí.",
"Automatically create a Google Meet video conference link for this event": "Crear automáticamente un enlace de videoconferencia de Google Meet para este evento",
"Select event types": "Seleccionar tipos de evento",
"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.": "Si expandir o no los eventos recurrentes en instancias y sólo retornar eventos únicos e instancias de eventos recurrentes, pero no los eventos recurrentes subyacentes ellos mismos.",
"Select the calendars to check for busy periods.": "Seleccione los calendarios para comprobar los periodos ocupados.",
"The start of the time range to check.": "El inicio del intervalo de tiempo a comprobar.",
"The end of the time range to check.": "El final del intervalo de tiempo a comprobar.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "El ID único del evento (por ejemplo, \"abc123def456\"). Puede encontrar esto en la URL del evento o en otras acciones del calendario.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Número máximo de asistentes a incluir en la respuesta. Si hay más asistentes, sólo se devuelve el participante.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Zona horaria para la respuesta (por ejemplo, \"América/Nuevo_Izquierda\", \"Europa/Londres\"). Por defecto se indica la zona horaria del calendario si no se especifica.",
"Authorization headers are injected automatically from your connection.": "Las cabeceras de autorización se inyectan automáticamente desde tu conexión.",
"Enable for files like PDFs, images, etc..": "Activar para archivos como PDFs, imágenes, etc.",
"All": "Todos",
"External Only": "Sólo externo",
"none": "ninguna",
"Yes, to everyone": "Sí, a todos",
"To non-Google Calendar guests only": "Sólo para los invitados que no son Google Calendar",
"To no one": "A nadie",
"Default": "Por defecto",
"Out Of Office": "Fuera de la oficina",
"Focus Time": "Tiempo de Enfoque",
"Working Location": "Ubicación laboral",
"GET": "RECOGER",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "BORRAR",
"HEAD": "LIMPIO",
"New or Updated Event": "Evento nuevo o actualizado",
"New Event": "Nuevo evento",
"Event Ends": "Fin del evento",
"Event Start (Time Before)": "Inicio del evento (Time Before)",
"New Event Matching Search": "Búsqueda de nuevo evento coincidente",
"Event Cancelled": "Evento cancelado",
"New Calendar": "Nuevo calendario",
"Triggers when an event is added or updated": "Dispara cuando se agrega o actualiza un evento",
"Fires when a new event is created in a calendar.": "Dispara cuando se crea un nuevo evento en un calendario.",
"Fires when an event ends.": "Dispara cuando un evento termina.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Dispara a una cantidad específica de tiempo antes de que un evento comience (por ejemplo, un recordatorio).",
"Fires when a new event is created that matches a specified search term.": "Dispara cuando se crea un nuevo evento que coincida con un término de búsqueda especificado.",
"Fires when an event is canceled or deleted.": "Dispara cuando un evento es cancelado o eliminado.",
"Fires when a new calendar is created or becomes accessible.": "Dispara cuando se crea un nuevo calendario o se vuelve accesible.",
"Event Types to Monitor": "Tipos de Evento a Monitorizar",
"Search Filter": "Filtro de búsqueda",
"Exclude All-Day Events": "Excluir eventos de todo el día",
"Target Specific Event": "Evento específico de destino",
"Event": "Evento",
"Time Before": "Tiempo antes",
"Time Unit": "Unidad de tiempo",
"Event Types": "Tipos de Evento",
"Search In Fields": "Buscar en campos",
"Cancellation Reasons": "Razones de cancelación",
"Access Role Filter": "Filtro de Rol de Acceso",
"Calendar Name Filter": "Filtro de nombre del calendario",
"Exclude Shared Calendars": "Excluir Calendarios Compartidos",
"If true, the trigger will activate for every occurrence of a recurring event.": "Si es verdadero, el disparador se activará para cada ocurrencia de un evento recurrente.",
"Filter by specific event types (leave empty to monitor all event types)": "Filtrar por tipos de eventos específicos (dejar vacío para supervisar todos los tipos de eventos)",
"Only trigger for events containing this text in title, description, or location (optional)": "Sólo para eventos que contengan este texto en título, descripción o ubicación (opcional)",
"Skip triggering for all-day events": "Saltar activación para eventos de todo el día",
"Enable to monitor a specific event instead of all events in the calendar.": "Activar para monitorear un evento específico en lugar de todos los eventos del calendario.",
"The amount of time before the event starts.": "La cantidad de tiempo antes de que comience el evento.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "Palabra(s) clave(s) a buscar en nuevos eventos (busca por defecto en el título, descripción, ubicación y asistentes).",
"Filter by specific event types (optional)": "Filtrar por tipos de evento específicos (opcional)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Especifique en qué campos buscar (dejar vacío para usar la búsqueda por defecto de Google en todos los campos)",
"Filter by specific types of cancellations (optional)": "Filtrar por tipos específicos de cancelaciones (opcional)",
"Only trigger for calendars with specific access roles (optional)": "Sólo disparador para calendarios con roles de acceso específicos (opcional)",
"Only trigger for calendars containing this text in name or description (optional)": "Sólo para calendarios que contengan este texto en nombre o descripción (opcional)",
"Only trigger for calendars you own, not shared calendars": "Disparador solo para los calendarios que posees, no para los calendarios compartidos",
"Default Events": "Eventos por defecto",
"Birthday Events": "Eventos de cumpleaños",
"Out of Office": "Fuera de la oficina",
"From Gmail": "Desde Gmail",
"Minutes": "Minutos",
"Hours": "Horas",
"Days": "Días",
"Event Title/Summary": "Título del evento/Resumen",
"Event Description": "Descripción del evento",
"Event Location": "Lugar del evento",
"Attendee Names/Emails": "Nombres/Correos de Asistentes",
"Event Deleted": "Evento eliminado",
"Attendee Declined": "Asistente rechazado",
"Event Rescheduled": "Evento Reprogramado",
"Other Cancellations": "Otras cancelaciones",
"Owner": "Propietario",
"Writer": "Escritor",
"Reader": "Lector",
"Free/Busy Reader": "Lector libre/ocupado"
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Organisez-vous et tenez les délais",
"Add Attendees to Event": "Ajouter des participants à l'événement",
"Create Quick Event": "Créer un événement rapide",
"Create Event": "Créer un événement",
"Get all Events": "Obtenir tous les événements",
"Update Event": "Mettre à jour l'événement",
"Delete Event": "Supprimer l'événement",
"Find Busy/Free Periods in Calendar": "Trouver des périodes occupées/gratuites dans le calendrier",
"Get Event by ID": "Obtenir un événement par ID",
"Custom API Call": "Appel API personnalisé",
"Add one or more person to existing event.": "Ajouter une ou plusieurs personnes à un événement existant.",
"Add Quick Calendar Event": "Ajouter un événement de calendrier rapide",
"Add Event": "Ajouter un événement",
"Get Events": "Obtenir des événements",
"Updates an event in Google Calendar.": "Met à jour un événement dans Google Agenda.",
"Deletes an event from Google Calendar.": "Supprime un événement de Google Agenda.",
"Finds free/busy calendar details from Google Calendar.": "Trouve les détails du calendrier libre/occupé depuis Google Agenda.",
"Fetch event details by its unique ID from Google Calendar.": "Récupérer les détails de l'événement par son ID unique depuis Google Agenda.",
"Make a custom API call to a specific endpoint": "Passez un appel API personnalisé à un point de terminaison spécifique",
"Calendar": "Calendrier",
"Event ID": "ID de l'événement",
"Attendees": "Participants",
"Summary": "Résumé",
"Send Updates": "Envoyer les mises à jour",
"Title of the event": "Titre de l'événement",
"Start date time of the event": "Date de début de l'événement",
"End date time of the event": "Date de fin de l'événement",
"Location": "Lieu",
"Description": "Libellé",
"Color": "Couleur",
"Guests can modify": "Les invités peuvent modifier",
"Guests can invite others": "Les invités peuvent inviter d'autres personnes",
"Guests can see other guests": "Les invités peuvent voir les autres invités",
"Send Notifications": "Envoyer des notifications",
"Create Google Meet Link": "Créer un lien Google Meet",
"Event types": "Types d'événements",
"Search Term": "Terme de recherche",
"Date from": "Date de début",
"Date to": "Date de fin",
"Expand Recurring Event?": "Développer l'événement récurrent ?",
"Calendars": "Calendriers",
"Start Time": "Start Time",
"End Time": "Heure de fin",
"Max Attendees": "Nombre maximum de participants",
"Time Zone": "Fuseau horaire",
"Method": "Méthode",
"Headers": "En-têtes",
"Query Parameters": "Paramètres de requête",
"Body": "Corps",
"Response is Binary ?": "La réponse est Binaire ?",
"No Error on Failure": "Aucune erreur en cas d'échec",
"Timeout (in seconds)": "Délai d'attente (en secondes)",
"Emails of the attendees (guests)": "E-mails des participants (invités)",
"The text describing the event to be created": "Le texte décrivant l'événement à créer",
"Guests who should receive notifications about the creation of the new event.": "Les invités qui devraient recevoir des notifications sur la création de l'événement.",
"By default it'll be 30 min post start time": "Par défaut, il sera de 30 mn après le début",
"Description of the event. You can use HTML tags here.": "Description de l'événement. Vous pouvez utiliser des balises HTML ici.",
"Automatically create a Google Meet video conference link for this event": "Créer automatiquement un lien de vidéoconférence Google Meet pour cet événement",
"Select event types": "Sélectionnez les types d'événements",
"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.": "S'il faut étendre les événements récurrents dans des instances et ne retourner que des événements uniques et des instances d'événements récurrents, mais pas les événements récurrents sous-jacents eux-mêmes.",
"Select the calendars to check for busy periods.": "Sélectionnez les calendriers à vérifier pour les périodes occupées.",
"The start of the time range to check.": "Le début de l'intervalle de temps à vérifier.",
"The end of the time range to check.": "Fin de la plage de temps à vérifier.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "L'ID unique de l'événement (par exemple, \"abc123def456\"). Vous pouvez le trouver dans l'URL de l'événement ou à partir d'autres actions de calendrier.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Le nombre maximum de participants à inclure dans la réponse. S'il y a plus de participants, seul le participant est retourné.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Le fuseau horaire de la réponse (par exemple, \"Amérique/New_York\", \"Europe/Londres\"). Le fuseau horaire du calendrier n'est pas spécifié par défaut.",
"Authorization headers are injected automatically from your connection.": "Les en-têtes d'autorisation sont injectés automatiquement à partir de votre connexion.",
"Enable for files like PDFs, images, etc..": "Activer pour les fichiers comme les PDFs, les images, etc.",
"All": "Tous",
"External Only": "Externe uniquement",
"none": "aucun",
"Yes, to everyone": "Oui, à tout le monde",
"To non-Google Calendar guests only": "Seulement pour les invités qui ne sont pas sur Google Agenda",
"To no one": "À personne",
"Default": "Par défaut",
"Out Of Office": "Hors du bureau",
"Focus Time": "Temps de concentration",
"Working Location": "Lieu de travail",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "Nouvel événement ou mise à jour",
"New Event": "Nouvel événement",
"Event Ends": "Fin de l'événement",
"Event Start (Time Before)": "Début de l'événement (avant le temps)",
"New Event Matching Search": "Recherche de nouvel événement correspondant",
"Event Cancelled": "Événement annulé",
"New Calendar": "Nouveau calendrier",
"Triggers when an event is added or updated": "Se déclenche lorsqu'un événement est ajouté ou mis à jour",
"Fires when a new event is created in a calendar.": "Se déclenche lorsqu'un nouvel événement est créé dans un calendrier.",
"Fires when an event ends.": "Tire quand un événement se termine.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Tire à un certain temps avant le début d'un événement (par exemple, un rappel).",
"Fires when a new event is created that matches a specified search term.": "Déclenche lorsqu'un nouvel événement est créé qui correspond à un terme de recherche spécifié.",
"Fires when an event is canceled or deleted.": "Se déclenche lorsqu'un événement est annulé ou supprimé.",
"Fires when a new calendar is created or becomes accessible.": "Se déclenche lorsqu'un nouveau calendrier est créé ou devient accessible.",
"Event Types to Monitor": "Types d'événements à surveiller",
"Search Filter": "Filtre de recherche",
"Exclude All-Day Events": "Exclure les événements de toute la journée",
"Target Specific Event": "Evénement spécifique de la cible",
"Event": "Evénement",
"Time Before": "Temps avant",
"Time Unit": "Unité de temps",
"Event Types": "Types d'événements",
"Search In Fields": "Rechercher dans les champs",
"Cancellation Reasons": "Raisons d'annulation",
"Access Role Filter": "Filtre d'accès aux rôles",
"Calendar Name Filter": "Filtre du nom du calendrier",
"Exclude Shared Calendars": "Exclure les calendriers partagés",
"If true, the trigger will activate for every occurrence of a recurring event.": "Si vrai, le déclencheur s'activera pour chaque occurrence d'un événement récurrent.",
"Filter by specific event types (leave empty to monitor all event types)": "Filtrer par type dévénement spécifique (laisser vide pour surveiller tous les types dévénements)",
"Only trigger for events containing this text in title, description, or location (optional)": "Déclenche uniquement les événements contenant ce texte dans le titre, la description ou l'emplacement (facultatif)",
"Skip triggering for all-day events": "Ignorer le déclenchement pour les événements de toute la journée",
"Enable to monitor a specific event instead of all events in the calendar.": "Activer pour surveiller un événement spécifique au lieu de tous les événements du calendrier.",
"The amount of time before the event starts.": "Le temps avant le début de l'événement.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "Le ou les mots-clés à rechercher dans de nouveaux événements (recherche par titre, description, lieu et participants par défaut).",
"Filter by specific event types (optional)": "Filtrer par type dévénement spécifique (facultatif)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Spécifier les champs à rechercher (laisser vide pour utiliser la recherche par défaut de Google dans tous les champs)",
"Filter by specific types of cancellations (optional)": "Filtrer par types spécifiques d'annulations (optionnel)",
"Only trigger for calendars with specific access roles (optional)": "Déclenche uniquement les calendriers avec des rôles d'accès spécifiques (facultatif)",
"Only trigger for calendars containing this text in name or description (optional)": "Déclenche uniquement les calendriers contenant ce texte dans le nom ou la description (facultatif)",
"Only trigger for calendars you own, not shared calendars": "Déclenche uniquement les calendriers que vous possédez, pas les calendriers partagés",
"Default Events": "Événements par défaut",
"Birthday Events": "Événements d'anniversaire",
"Out of Office": "Hors du bureau",
"From Gmail": "Depuis Gmail",
"Minutes": "Minutes",
"Hours": "Heures",
"Days": "Jours",
"Event Title/Summary": "Titre/Résumé de l'événement",
"Event Description": "Description de l'événement",
"Event Location": "Lieu de l'événement",
"Attendee Names/Emails": "Noms/E-mails des participants",
"Event Deleted": "Événement supprimé",
"Attendee Declined": "Participants refusés",
"Event Rescheduled": "Événement reprogrammé",
"Other Cancellations": "Autres annulations",
"Owner": "Propriétaire",
"Writer": "Écrivain",
"Reader": "Lecteur",
"Free/Busy Reader": "Lecteur Gratuit/Occupé"
}

View File

@@ -0,0 +1,71 @@
{
"Google Calendar": "Google Calendar",
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "Description",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Select event types": "Select event types",
"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.": "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.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"All": "All",
"External Only": "External Only",
"none": "none",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "New or Updated Event",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event."
}

View File

@@ -0,0 +1,71 @@
{
"Google Calendar": "Google Calendar",
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "Description",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Select event types": "Select event types",
"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.": "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.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"All": "Semua",
"External Only": "External Only",
"none": "none",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "New or Updated Event",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event."
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "整理してスケジュールを維持する",
"Add Attendees to Event": "参加者をイベントに追加",
"Create Quick Event": "クイックイベントを作成",
"Create Event": "イベントを作成",
"Get all Events": "すべてのイベントを取得",
"Update Event": "予定を更新",
"Delete Event": "イベントを削除",
"Find Busy/Free Periods in Calendar": "カレンダー内の予定/無料期間を検索",
"Get Event by ID": "イベントをIDで取得",
"Custom API Call": "カスタムAPI通話",
"Add one or more person to existing event.": "既存のイベントに人を追加します。",
"Add Quick Calendar Event": "クイックカレンダーイベントを追加",
"Add Event": "イベントを追加",
"Get Events": "イベントを取得する",
"Updates an event in Google Calendar.": "Google カレンダーのイベントを更新します。",
"Deletes an event from Google Calendar.": "Google カレンダーからイベントを削除します。",
"Finds free/busy calendar details from Google Calendar.": "無料/忙しいカレンダーの詳細を Google カレンダーから検索します。",
"Fetch event details by its unique ID from Google Calendar.": "Google カレンダーから一意の ID でイベントの詳細を取得します。",
"Make a custom API call to a specific endpoint": "特定のエンドポイントへのカスタム API コールを実行します。",
"Calendar": "カレンダー",
"Event ID": "イベントID",
"Attendees": "参加者",
"Summary": "Summary",
"Send Updates": "更新を送信",
"Title of the event": "イベントのタイトル",
"Start date time of the event": "イベントの開始日時",
"End date time of the event": "イベントの終了日時",
"Location": "場所",
"Description": "Description",
"Color": "色",
"Guests can modify": "ゲストは変更できます",
"Guests can invite others": "ゲストは他のユーザーを招待できます",
"Guests can see other guests": "ゲストは他のゲストを閲覧できます",
"Send Notifications": "通知を送信",
"Create Google Meet Link": "Google Meetのリンクを作成",
"Event types": "イベントの種類",
"Search Term": "検索用語",
"Date from": "開始日",
"Date to": "終了日",
"Expand Recurring Event?": "繰り返しイベントを展開しますか?",
"Calendars": "カレンダー",
"Start Time": "開始時刻",
"End Time": "終了時刻",
"Max Attendees": "最大参加者数",
"Time Zone": "タイムゾーン",
"Method": "方法",
"Headers": "ヘッダー",
"Query Parameters": "クエリパラメータ",
"Body": "本文",
"Response is Binary ?": "応答はバイナリですか?",
"No Error on Failure": "失敗時にエラーはありません",
"Timeout (in seconds)": "タイムアウト(秒)",
"Emails of the attendees (guests)": "出席者のメール(ゲスト)",
"The text describing the event to be created": "作成される予定を説明するテキスト",
"Guests who should receive notifications about the creation of the new event.": "新しいイベントの作成に関する通知を受け取るゲスト。",
"By default it'll be 30 min post start time": "デフォルトでは投稿開始時間は30分です",
"Description of the event. You can use HTML tags here.": "イベントの説明。ここではHTMLタグを使用できます。",
"Automatically create a Google Meet video conference link for this event": "このイベントのGoogle Meetビデオ会議リンクを自動的に作成する",
"Select event types": "イベントの種類を選択",
"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.": "繰り返しイベントをインスタンスに展開し、単一オフイベントと繰り返しイベントのインスタンスのみを返すかどうかを設定しますが、元の繰り返しイベント自体は返しません。",
"Select the calendars to check for busy periods.": "カレンダーを選択して、忙しい期間を確認します。",
"The start of the time range to check.": "チェックする時間範囲の開始。",
"The end of the time range to check.": "チェックする時間範囲の終了。",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "イベントの固有ID\"abc123def456\"。イベントURLまたは他のカレンダーアクションからこれを見つけることができます。",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "回答に含める出席者の最大数. より多くの出席者がある場合, 参加者のみが返されます.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "応答のタイムゾーン(例: \"アメリカ/ニュー_ヨーク\"、\"ヨーロッパ/ロンドン\")。指定されていない場合はカレンダーのタイムゾーンがデフォルトです。",
"Authorization headers are injected automatically from your connection.": "認証ヘッダは接続から自動的に注入されます。",
"Enable for files like PDFs, images, etc..": "PDF、画像などのファイルを有効にします。",
"All": "すべて",
"External Only": "外部のみ",
"none": "なし",
"Yes, to everyone": "はい、全員に",
"To non-Google Calendar guests only": "Googleカレンダー以外のゲストへのみ表示",
"To no one": "誰にも",
"Default": "デフォルト",
"Out Of Office": "Office外",
"Focus Time": "フォーカス時間",
"Working Location": "作業場所",
"GET": "取得",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "削除",
"HEAD": "頭",
"New or Updated Event": "新規または更新されたイベント",
"New Event": "新しいイベント",
"Event Ends": "イベント終了",
"Event Start (Time Before)": "イベント開始(時間が経過)",
"New Event Matching Search": "新しいイベント一致検索",
"Event Cancelled": "イベントがキャンセルされました",
"New Calendar": "新しいカレンダー",
"Triggers when an event is added or updated": "イベントが追加または更新されたときにトリガーします",
"Fires when a new event is created in a calendar.": "カレンダーに新しいイベントが作成されたときに発生します。",
"Fires when an event ends.": "イベントが終了したときに発生します。",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "イベントが開始される前に指定された時間(たとえばリマインダー)で発生します。",
"Fires when a new event is created that matches a specified search term.": "指定した検索語に一致する新しいイベントが作成されたときに発生します。",
"Fires when an event is canceled or deleted.": "イベントがキャンセルまたは削除されたときに発生します。",
"Fires when a new calendar is created or becomes accessible.": "新しいカレンダーが作成された時、またはアクセス可能になったときに発火します。",
"Event Types to Monitor": "モニタリングするイベントタイプ",
"Search Filter": "検索フィルタ",
"Exclude All-Day Events": "終日イベントを除外",
"Target Specific Event": "ターゲット特定のイベント",
"Event": "イベント",
"Time Before": "時刻",
"Time Unit": "時間単位",
"Event Types": "イベントタイプ",
"Search In Fields": "フィールドを検索",
"Cancellation Reasons": "キャンセルの理由",
"Access Role Filter": "アクセス権限フィルター",
"Calendar Name Filter": "カレンダー名フィルタ",
"Exclude Shared Calendars": "共有カレンダーを除外",
"If true, the trigger will activate for every occurrence of a recurring event.": "true の場合、トリガーは繰り返しイベントの発生ごとに有効になります。",
"Filter by specific event types (leave empty to monitor all event types)": "特定のイベントタイプでフィルター (すべてのイベントタイプを監視するには空白のままにしてください)",
"Only trigger for events containing this text in title, description, or location (optional)": "タイトル、説明、または場所にこのテキストを含むイベントのみトリガー(オプション)",
"Skip triggering for all-day events": "終日の予定のトリガーをスキップ",
"Enable to monitor a specific event instead of all events in the calendar.": "カレンダー内のすべてのイベントではなく、特定のイベントを監視することを有効にします。",
"The amount of time before the event starts.": "イベントが開始されるまでの時間。",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "新しいイベントで検索するキーワード (デフォルトではタイトル、説明、場所、出席者を検索します)",
"Filter by specific event types (optional)": "特定のイベントタイプでフィルター (オプション)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "検索対象のフィールドを指定します。(すべてのフィールドでGoogleのデフォルト検索を使用する場合は空白のままにします)",
"Filter by specific types of cancellations (optional)": "特定の種類のキャンセルでフィルター (オプション)",
"Only trigger for calendars with specific access roles (optional)": "特定のアクセスロールを持つカレンダーのみトリガー(オプション)",
"Only trigger for calendars containing this text in name or description (optional)": "名前または説明にこのテキストを含むカレンダーのみトリガーします (オプション)",
"Only trigger for calendars you own, not shared calendars": "共有カレンダーではなく、所有しているカレンダーのみトリガーします",
"Default Events": "デフォルトのイベント",
"Birthday Events": "誕生日イベント",
"Out of Office": "Office外",
"From Gmail": "Gmail から",
"Minutes": "分",
"Hours": "時間",
"Days": "日数",
"Event Title/Summary": "イベントのタイトル/概要",
"Event Description": "イベントの説明",
"Event Location": "イベントの場所",
"Attendee Names/Emails": "出席者の名前/メール",
"Event Deleted": "イベントが削除されました",
"Attendee Declined": "出席者が拒否されました",
"Event Rescheduled": "イベントのスケジュールを変更しました",
"Other Cancellations": "その他のキャンセル",
"Owner": "所有者",
"Writer": "Writer",
"Reader": "リーダー",
"Free/Busy Reader": "無料/ビジーリーダー"
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Organiseer en blijf op schema",
"Add Attendees to Event": "Deelnemers toevoegen aan gebeurtenis",
"Create Quick Event": "Maak Snel Evenement",
"Create Event": "Gebeurtenis aanmaken",
"Get all Events": "Alle gebeurtenissen ontvangen",
"Update Event": "Gebeurtenis bijwerken",
"Delete Event": "Afspraak verwijderen",
"Find Busy/Free Periods in Calendar": "Vind Busy/Gratis Perioden in de kalender",
"Get Event by ID": "Verkrijg Event via ID",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Een of meer personen toevoegen aan bestaande gebeurtenis.",
"Add Quick Calendar Event": "Snelle Agenda-gebeurtenis toevoegen",
"Add Event": "Afspraak toevoegen",
"Get Events": "Haal Evenementen op",
"Updates an event in Google Calendar.": "Werkt een gebeurtenis bij in Google Agenda.",
"Deletes an event from Google Calendar.": "Verwijdert een event van Google kalender.",
"Finds free/busy calendar details from Google Calendar.": "Vindt vrije/drukke kalendergegevens van Google Agenda.",
"Fetch event details by its unique ID from Google Calendar.": "Haal event details op met zijn unieke ID van Google Agenda.",
"Make a custom API call to a specific endpoint": "Maak een aangepaste API call naar een specifiek eindpunt",
"Calendar": "Kalender",
"Event ID": "Gebeurtenis ID",
"Attendees": "Aanwezigen",
"Summary": "Summary",
"Send Updates": "Updates verzenden",
"Title of the event": "Titel van de gebeurtenis",
"Start date time of the event": "Startdatum van de gebeurtenis",
"End date time of the event": "Einddatum van de gebeurtenis",
"Location": "Locatie",
"Description": "Beschrijving",
"Color": "Kleur",
"Guests can modify": "Gasten kunnen aanpassen",
"Guests can invite others": "Gasten kunnen anderen uitnodigen",
"Guests can see other guests": "Gasten kunnen andere gasten zien",
"Send Notifications": "Stuur meldingen",
"Create Google Meet Link": "Creëer Google ontmoeting link",
"Event types": "Event types",
"Search Term": "Zoek term",
"Date from": "Datum van",
"Date to": "Datum tot",
"Expand Recurring Event?": "Terugkerende gebeurtenis uitbreiden?",
"Calendars": "Kalenders",
"Start Time": "Starttijd",
"End Time": "Eind Tijd",
"Max Attendees": "Maximaal aantal aanwezigen",
"Time Zone": "Tijd Zone",
"Method": "Methode",
"Headers": "Kopteksten",
"Query Parameters": "Query parameters",
"Body": "Lichaam",
"Response is Binary ?": "Antwoord is binair?",
"No Error on Failure": "Geen fout bij fout",
"Timeout (in seconds)": "Time-out (in seconden)",
"Emails of the attendees (guests)": "Emails van de deelnemers (gasten)",
"The text describing the event to be created": "De tekst die de te maken gebeurtenis beschrijft",
"Guests who should receive notifications about the creation of the new event.": "Gasten die meldingen moeten ontvangen over de creatie van het nieuwe evenement.",
"By default it'll be 30 min post start time": "Standaard is het 30 minuten begintijd van het bericht",
"Description of the event. You can use HTML tags here.": "Beschrijving van de gebeurtenis. U kunt hier HTML-tags gebruiken.",
"Automatically create a Google Meet video conference link for this event": "Maak automatisch een videoconferentielink aan voor dit evenement op Google",
"Select event types": "Afspraaktypes selecteren",
"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.": "Of u terugkerende gebeurtenissen wilt uitbreiden naar instanties en alleen individuele evenementen en herhalende evenementen teruggeven, maar niet de onderliggende terugkerende evenementen zelf.",
"Select the calendars to check for busy periods.": "Selecteer de agenda's om te controleren op drukke periodes.",
"The start of the time range to check.": "Het begin van het tijdsbereik om te controleren.",
"The end of the time range to check.": "Het einde van het tijdsbereik om te controleren.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "De unieke ID van de gebeurtenis (bijv. \"abc123def456\"). U kunt dit vinden in de gebeurtenis-URL of in andere kalenderacties.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Maximum aantal deelnemers om op te nemen in de reactie. Als er meer deelnemers zijn, wordt alleen de gebruiker geretourneerd.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Tijdzone voor het antwoord (bijv. \"Amerika/New_York\", \"Europa/London\"). Standaard ingesteld op de tijdzone van de kalender indien niet gespecificeerd.",
"Authorization headers are injected automatically from your connection.": "Autorisatie headers worden automatisch geïnjecteerd vanuit uw verbinding.",
"Enable for files like PDFs, images, etc..": "Inschakelen voor bestanden zoals PDF's, afbeeldingen etc..",
"All": "Allemaal",
"External Only": "Alleen externe",
"none": "geen",
"Yes, to everyone": "Ja, tegen iedereen",
"To non-Google Calendar guests only": "Alleen naar niet-Google Agenda gasten",
"To no one": "Naar niemand",
"Default": "Standaard",
"Out Of Office": "Buiten kantoor",
"Focus Time": "Focus Tijd",
"Working Location": "Werk locatie",
"GET": "KRIJG",
"POST": "POSTE",
"PATCH": "BEKIJK",
"PUT": "PUT",
"DELETE": "VERWIJDEREN",
"HEAD": "HOOFD",
"New or Updated Event": "Nieuwe of Bijgewerkte gebeurtenis",
"New Event": "Nieuwe gebeurtenis",
"Event Ends": "Einde van evenement",
"Event Start (Time Before)": "Start event (tijd voorheen)",
"New Event Matching Search": "Nieuwe overeenkomende zoekopdracht",
"Event Cancelled": "Afspraak geannuleerd",
"New Calendar": "Nieuwe kalender",
"Triggers when an event is added or updated": "Triggert wanneer een gebeurtenis wordt toegevoegd of bijgewerkt",
"Fires when a new event is created in a calendar.": "Vuurt wanneer een nieuwe afspraak wordt gemaakt in een kalender.",
"Fires when an event ends.": "Vuurt af wanneer een gebeurtenis eindigt.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Vuurt op een bepaalde tijd voordat een afspraak begint (bijv. een herinnering).",
"Fires when a new event is created that matches a specified search term.": "Vuurt wanneer een nieuwe gebeurtenis wordt gemaakt die overeenkomt met een gespecificeerde zoekterm.",
"Fires when an event is canceled or deleted.": "Vuurt wanneer een event is geannuleerd of verwijderd.",
"Fires when a new calendar is created or becomes accessible.": "Vuurt wanneer een nieuwe kalender wordt gemaakt of toegankelijk wordt.",
"Event Types to Monitor": "Te monitoren event typen",
"Search Filter": "Zoek filter",
"Exclude All-Day Events": "All-Day Gebeurtenissen uitsluiten",
"Target Specific Event": "Specifieke doelgebeurtenis",
"Event": "Gebeurtenis",
"Time Before": "Tijd voor",
"Time Unit": "Eenheid van tijd",
"Event Types": "Event Types",
"Search In Fields": "Zoeken in velden",
"Cancellation Reasons": "Reden van annulering",
"Access Role Filter": "Toegang Rol Filter",
"Calendar Name Filter": "Kalender naam filter",
"Exclude Shared Calendars": "Gedeelde kalenders uitsluiten",
"If true, the trigger will activate for every occurrence of a recurring event.": "Indien waar, dan zal de trigger activeren voor elke gebeurtenis van een terugkerende gebeurtenis.",
"Filter by specific event types (leave empty to monitor all event types)": "Filter op specifieke event types (laat leeg om alle event types te controleren)",
"Only trigger for events containing this text in title, description, or location (optional)": "Alleen trigger voor afspraken die deze tekst bevatten in titel, beschrijving of locatie (optioneel)",
"Skip triggering for all-day events": "Trigeren voor dagelijkse afspraken overslaan",
"Enable to monitor a specific event instead of all events in the calendar.": "Inschakelen om een specifieke gebeurtenis bij te houden in plaats van alle afspraken in de kalender.",
"The amount of time before the event starts.": "De hoeveelheid tijd voordat het evenement begint.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "De trefwoorden om te zoeken in nieuwe afspraken (zoekt standaard tussen titel, beschrijving, locatie en deelnemers).",
"Filter by specific event types (optional)": "Filter op specifieke event types (optioneel)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Specificeer in welke velden gezocht moeten worden (laat leeg om de standaard zoekopdracht van Google te gebruiken voor alle velden)",
"Filter by specific types of cancellations (optional)": "Filter op specifieke soorten annuleringen (optioneel)",
"Only trigger for calendars with specific access roles (optional)": "Alleen activeren voor kalenders met specifieke toegangsrollen (optioneel)",
"Only trigger for calendars containing this text in name or description (optional)": "Alleen trigger voor kalenders die deze tekst in naam of beschrijving (optioneel)",
"Only trigger for calendars you own, not shared calendars": "Alleen voor kalenders die u eist, niet gedeelde kalenders",
"Default Events": "Standaard Gebeurtenissen",
"Birthday Events": "Verjaardag Evenementen",
"Out of Office": "Buiten kantoor",
"From Gmail": "Van Gmail",
"Minutes": "minuten",
"Hours": "Uren",
"Days": "dagen",
"Event Title/Summary": "Event Titel/Samenvatting",
"Event Description": "Beschrijving gebeurtenis",
"Event Location": "Locatie van gebeurtenis",
"Attendee Names/Emails": "Aanwezige Naam/Emails",
"Event Deleted": "Afspraak verwijderd",
"Attendee Declined": "Deelnemer geweigerd",
"Event Rescheduled": "Evenement verplaatst",
"Other Cancellations": "Andere annuleringen",
"Owner": "Eigenaar",
"Writer": "Schrijver",
"Reader": "Lezer",
"Free/Busy Reader": "Gratis/Busy Reader"
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Organize-se e mantenha o horário",
"Add Attendees to Event": "Adicionar participantes ao evento",
"Create Quick Event": "Criar Evento Rápido",
"Create Event": "Criar evento",
"Get all Events": "Receber todos os eventos",
"Update Event": "Atualizar Evento",
"Delete Event": "Apagar Evento",
"Find Busy/Free Periods in Calendar": "Encontre Períodos Ocupados/Gratuitos no Calendário",
"Get Event by ID": "Obter evento por ID",
"Custom API Call": "Chamada de API personalizada",
"Add one or more person to existing event.": "Adicione uma ou mais pessoas ao evento existente.",
"Add Quick Calendar Event": "Adicionar evento ao calendário rápido",
"Add Event": "Adicionar evento",
"Get Events": "Obter Eventos",
"Updates an event in Google Calendar.": "Atualiza um evento no Google Calendar.",
"Deletes an event from Google Calendar.": "Exclui um evento do Google Agenda.",
"Finds free/busy calendar details from Google Calendar.": "Localiza detalhes da agenda livre/ocupada no Google Calendar.",
"Fetch event details by its unique ID from Google Calendar.": "Obter os detalhes do evento por seu ID exclusivo do Google Calendar.",
"Make a custom API call to a specific endpoint": "Faça uma chamada de API personalizada para um ponto de extremidade específico",
"Calendar": "calendário",
"Event ID": "Código do evento",
"Attendees": "Participantes",
"Summary": "Summary",
"Send Updates": "Enviar Atualizações",
"Title of the event": "Título do evento",
"Start date time of the event": "Data de início do evento",
"End date time of the event": "Data de término do evento",
"Location": "Local:",
"Description": "Descrição",
"Color": "Cor",
"Guests can modify": "Os convidados podem modificar",
"Guests can invite others": "Os convidados podem convidar outros",
"Guests can see other guests": "Os convidados podem ver outros convidados",
"Send Notifications": "Enviar Notificações",
"Create Google Meet Link": "Criar link do Google Meet",
"Event types": "Tipos de evento",
"Search Term": "Termo para pesquisa",
"Date from": "Data inicial",
"Date to": "Data final",
"Expand Recurring Event?": "Expandir Evento Recorrente?",
"Calendars": "Calendários",
"Start Time": "Hora de início",
"End Time": "Hora de término",
"Max Attendees": "Máximo de participantes",
"Time Zone": "Fuso Horário",
"Method": "Método",
"Headers": "Cabeçalhos",
"Query Parameters": "Parâmetros da consulta",
"Body": "Conteúdo",
"Response is Binary ?": "A resposta é binária ?",
"No Error on Failure": "Nenhum erro no Failure",
"Timeout (in seconds)": "Tempo limite (em segundos)",
"Emails of the attendees (guests)": "E-mails dos participantes (convidados)",
"The text describing the event to be created": "O texto descrevendo o evento a ser criado",
"Guests who should receive notifications about the creation of the new event.": "Convidados que devem receber notificações sobre a criação do novo evento.",
"By default it'll be 30 min post start time": "Por padrão será 30 min hora de início da postagem",
"Description of the event. You can use HTML tags here.": "Descrição do evento. Você pode usar tags HTML aqui.",
"Automatically create a Google Meet video conference link for this event": "Criar automaticamente um link de videoconferência do Google Meet para este evento",
"Select event types": "Selecione os tipos de eventos",
"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.": "Expandir os eventos recorrentes para instâncias e apenas retornar eventos únicos e instâncias de eventos recorrentes, mas não os próprios eventos recorrentes subjacentes.",
"Select the calendars to check for busy periods.": "Selecione os calendários para verificar se há períodos ocupados.",
"The start of the time range to check.": "O início do intervalo de tempo para verificar.",
"The end of the time range to check.": "O fim do intervalo de tempo para verificar.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "O ID exclusivo do evento (por exemplo, \"abc123def456\"). Você pode encontrar isso na URL do evento ou em outras ações do calendário.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "O número máximo de participantes para incluir na resposta. Se houver mais participantes, apenas o participante será devolvido.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Fuso horário para a resposta (por exemplo, \"América/New_York\", \"Europa/Londres\"). O padrão é o fuso horário do calendário se não for especificado.",
"Authorization headers are injected automatically from your connection.": "Os cabeçalhos de autorização são inseridos automaticamente a partir da sua conexão.",
"Enable for files like PDFs, images, etc..": "Habilitar para arquivos como PDFs, imagens, etc..",
"All": "TODOS",
"External Only": "Apenas externo",
"none": "nenhuma",
"Yes, to everyone": "Sim, para todos",
"To non-Google Calendar guests only": "Apenas para participantes não-do Google Agenda",
"To no one": "Para ninguém",
"Default": "Padrão",
"Out Of Office": "Fora de Escritório",
"Focus Time": "Hora de Foco",
"Working Location": "Local de trabalho",
"GET": "OBTER",
"POST": "POSTAR",
"PATCH": "COMPRAR",
"PUT": "COLOCAR",
"DELETE": "EXCLUIR",
"HEAD": "CABEÇA",
"New or Updated Event": "Evento novo ou atualizado",
"New Event": "Novo evento",
"Event Ends": "Fim do Evento",
"Event Start (Time Before)": "Início do Evento (Tempo Anterior)",
"New Event Matching Search": "Pesquisa de Correspondência de Novo Evento",
"Event Cancelled": "Evento cancelado",
"New Calendar": "Novo calendário",
"Triggers when an event is added or updated": "Dispara quando um evento é adicionado ou atualizado",
"Fires when a new event is created in a calendar.": "aciona quando um novo evento é criado em um calendário.",
"Fires when an event ends.": "Atira quando um evento terminar.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Atira a uma quantidade especificada de tempo antes do início de um evento (por exemplo, um lembrete).",
"Fires when a new event is created that matches a specified search term.": "Atira quando um novo evento é criado que corresponde a um termo de pesquisa especificado.",
"Fires when an event is canceled or deleted.": "Atira quando um evento é cancelado ou excluído.",
"Fires when a new calendar is created or becomes accessible.": "Atira quando um novo calendário é criado ou se torna acessível.",
"Event Types to Monitor": "Tipos de Evento para Monitorar",
"Search Filter": "Filtro de Busca",
"Exclude All-Day Events": "Excluir eventos do dia inteiro",
"Target Specific Event": "Evento Específico do alvo",
"Event": "Evento",
"Time Before": "Tempo Antes",
"Time Unit": "Unidade de tempo",
"Event Types": "Tipos de Evento",
"Search In Fields": "Pesquisar em Campos",
"Cancellation Reasons": "Motivos de cancelamento",
"Access Role Filter": "Filtro Função de Acesso",
"Calendar Name Filter": "Nome do calendário",
"Exclude Shared Calendars": "Excluir calendários compartilhados",
"If true, the trigger will activate for every occurrence of a recurring event.": "Se verdadeiro, o gatilho será ativado para cada ocorrência de um evento recorrente.",
"Filter by specific event types (leave empty to monitor all event types)": "Filtrar por tipos de evento específicos (deixe em branco para monitorar todos os tipos de eventos)",
"Only trigger for events containing this text in title, description, or location (optional)": "Ativar apenas eventos que contenham este texto em título, descrição ou localização (opcional)",
"Skip triggering for all-day events": "Pular disparo para eventos de dia inteiro",
"Enable to monitor a specific event instead of all events in the calendar.": "Habilite para monitorar um evento específico em vez de todos os eventos na agenda.",
"The amount of time before the event starts.": "O tempo antes do início do evento.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "A palavra-chave para procurar em novos eventos (pesquisa por título, descrição, localização e participantes por padrão).",
"Filter by specific event types (optional)": "Filtrar por tipos de evento específicos (opcional)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Especifique quais campos para pesquisar (deixe em branco para usar a pesquisa padrão do Google em todos os campos)",
"Filter by specific types of cancellations (optional)": "Filtrar por tipos específicos de cancelamentos (opcional)",
"Only trigger for calendars with specific access roles (optional)": "Selecionar calendários com papéis de acesso específicos (opcional)",
"Only trigger for calendars containing this text in name or description (optional)": "Apenas gatilho para calendários que contenham este texto no nome ou descrição (opcional)",
"Only trigger for calendars you own, not shared calendars": "Apenas gatilho para os calendários que você possui, não compartilhados",
"Default Events": "Eventos Padrão",
"Birthday Events": "Eventos de aniversário",
"Out of Office": "Fora de Escritório",
"From Gmail": "Do Gmail",
"Minutes": "minutos",
"Hours": "horas",
"Days": "dias",
"Event Title/Summary": "Título do Evento/Resumo",
"Event Description": "Descrição do Evento",
"Event Location": "Local do evento",
"Attendee Names/Emails": "Nomes dos participantes/E-mails",
"Event Deleted": "Evento excluído",
"Attendee Declined": "Participante recusado",
"Event Rescheduled": "Evento reagendado",
"Other Cancellations": "Outros cancelamentos",
"Owner": "Proprietário",
"Writer": "Escritor",
"Reader": "Leitor",
"Free/Busy Reader": "Leitor Livre/Ocupado"
}

View File

@@ -0,0 +1,71 @@
{
"Google Calendar": "Календарь Google",
"Get organized and stay on schedule": "Организуйте и оставайтесь в расписании",
"Add Attendees to Event": "Добавить участников к событию",
"Create Quick Event": "Создать быстрое событие",
"Create Event": "Создать событие",
"Get all Events": "Получить все события",
"Update Event": "Обновить событие",
"Delete Event": "Удалить событие",
"Custom API Call": "Пользовательский вызов API",
"Add one or more person to existing event.": "Добавьте одного или нескольких людей к существующему событию.",
"Add Quick Calendar Event": "Добавить событие быстрого календаря",
"Add Event": "Добавить событие",
"Get Events": "Получить события",
"Updates an event in Google Calendar.": "Обновляет событие в календаре Google.",
"Deletes an event from Google Calendar.": "Удаляет событие из Календаря Google.",
"Make a custom API call to a specific endpoint": "Сделать пользовательский API вызов к определенной конечной точке",
"Calendar": "Календарь",
"Event ID": "ID события",
"Attendees": "Участники",
"Summary": "Summary",
"Send Updates": "Отправить обновления",
"Title of the event": "Название события",
"Start date time of the event": "Дата начала события",
"End date time of the event": "Дата окончания события",
"Location": "Местоположение",
"Description": "Описание",
"Color": "Цвет",
"Guests can modify": "Гости могут изменять",
"Guests can invite others": "Гости могут пригласить других",
"Guests can see other guests": "Гости могут видеть других гостей",
"Send Notifications": "Отправить уведомления",
"Event types": "Типы событий",
"Search Term": "Поиск термина",
"Date from": "Дата с",
"Date to": "Дата до",
"Expand Recurring Event?": "Развернуть повторяющееся событие?",
"Method": "Метод",
"Headers": "Заголовки",
"Query Parameters": "Параметры запроса",
"Body": "Тело",
"No Error on Failure": "Нет ошибок при ошибке",
"Timeout (in seconds)": "Таймаут (в секундах)",
"Emails of the attendees (guests)": "Письма участников (гостей)",
"The text describing the event to be created": "Текст, описывающий создаваемый событие",
"Guests who should receive notifications about the creation of the new event.": "Гости, которые должны получать уведомления о создании нового события.",
"By default it'll be 30 min post start time": "По умолчанию он будет равен 30 минутам времени начала записи",
"Description of the event. You can use HTML tags here.": "Описание события. Вы можете использовать HTML теги здесь.",
"Select event types": "Выберите типы событий",
"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.": "Распределять повторяющиеся события в экземпляры и возвращать только разовые и повторяющиеся события, но не сами по себе.",
"Authorization headers are injected automatically from your connection.": "Заголовки авторизации включаются автоматически из вашего соединения.",
"All": "Все",
"External Only": "Только внешние",
"none": "нет",
"Yes, to everyone": "Да, всем",
"To non-Google Calendar guests only": "Только гостям не Google Календаря",
"To no one": "Никому",
"Default": "По умолчанию",
"Out Of Office": "Вне офиса",
"Focus Time": "Время фокусировки",
"Working Location": "Место работы",
"GET": "ПОЛУЧИТЬ",
"POST": "ПОСТ",
"PATCH": "ПАТЧ",
"PUT": "ПОКУПИТЬ",
"DELETE": "УДАЛИТЬ",
"HEAD": "HEAD",
"New or Updated Event": "Новое или обновленное событие",
"Triggers when an event is added or updated": "Триггеры при добавлении или обновлении события",
"If true, the trigger will activate for every occurrence of a recurring event.": "Если включено, то триггер будет активирован для каждого вхождения повторяющегося события."
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Find Busy/Free Periods in Calendar": "Find Busy/Free Periods in Calendar",
"Get Event by ID": "Get Event by ID",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Finds free/busy calendar details from Google Calendar.": "Finds free/busy calendar details from Google Calendar.",
"Fetch event details by its unique ID from Google Calendar.": "Fetch event details by its unique ID from Google Calendar.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "Description",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Create Google Meet Link": "Create Google Meet Link",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Calendars": "Calendars",
"Start Time": "Start Time",
"End Time": "End Time",
"Max Attendees": "Max Attendees",
"Time Zone": "Time Zone",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Automatically create a Google Meet video conference link for this event": "Automatically create a Google Meet video conference link for this event",
"Select event types": "Select event types",
"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.": "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.",
"Select the calendars to check for busy periods.": "Select the calendars to check for busy periods.",
"The start of the time range to check.": "The start of the time range to check.",
"The end of the time range to check.": "The end of the time range to check.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"All": "All",
"External Only": "External Only",
"none": "none",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "New or Updated Event",
"New Event": "New Event",
"Event Ends": "Event Ends",
"Event Start (Time Before)": "Event Start (Time Before)",
"New Event Matching Search": "New Event Matching Search",
"Event Cancelled": "Event Cancelled",
"New Calendar": "New Calendar",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"Fires when a new event is created in a calendar.": "Fires when a new event is created in a calendar.",
"Fires when an event ends.": "Fires when an event ends.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Fires at a specified amount of time before an event starts (e.g., a reminder).",
"Fires when a new event is created that matches a specified search term.": "Fires when a new event is created that matches a specified search term.",
"Fires when an event is canceled or deleted.": "Fires when an event is canceled or deleted.",
"Fires when a new calendar is created or becomes accessible.": "Fires when a new calendar is created or becomes accessible.",
"Event Types to Monitor": "Event Types to Monitor",
"Search Filter": "Search Filter",
"Exclude All-Day Events": "Exclude All-Day Events",
"Target Specific Event": "Target Specific Event",
"Event": "Event",
"Time Before": "Time Before",
"Time Unit": "Time Unit",
"Event Types": "Event Types",
"Search In Fields": "Search In Fields",
"Cancellation Reasons": "Cancellation Reasons",
"Access Role Filter": "Access Role Filter",
"Calendar Name Filter": "Calendar Name Filter",
"Exclude Shared Calendars": "Exclude Shared Calendars",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event.",
"Filter by specific event types (leave empty to monitor all event types)": "Filter by specific event types (leave empty to monitor all event types)",
"Only trigger for events containing this text in title, description, or location (optional)": "Only trigger for events containing this text in title, description, or location (optional)",
"Skip triggering for all-day events": "Skip triggering for all-day events",
"Enable to monitor a specific event instead of all events in the calendar.": "Enable to monitor a specific event instead of all events in the calendar.",
"The amount of time before the event starts.": "The amount of time before the event starts.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).",
"Filter by specific event types (optional)": "Filter by specific event types (optional)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Specify which fields to search in (leave empty to use Google's default search across all fields)",
"Filter by specific types of cancellations (optional)": "Filter by specific types of cancellations (optional)",
"Only trigger for calendars with specific access roles (optional)": "Only trigger for calendars with specific access roles (optional)",
"Only trigger for calendars containing this text in name or description (optional)": "Only trigger for calendars containing this text in name or description (optional)",
"Only trigger for calendars you own, not shared calendars": "Only trigger for calendars you own, not shared calendars",
"Default Events": "Default Events",
"Birthday Events": "Birthday Events",
"Out of Office": "Out of Office",
"From Gmail": "From Gmail",
"Minutes": "Minutes",
"Hours": "Hours",
"Days": "Days",
"Event Title/Summary": "Event Title/Summary",
"Event Description": "Event Description",
"Event Location": "Event Location",
"Attendee Names/Emails": "Attendee Names/Emails",
"Event Deleted": "Event Deleted",
"Attendee Declined": "Attendee Declined",
"Event Rescheduled": "Event Rescheduled",
"Other Cancellations": "Other Cancellations",
"Owner": "Owner",
"Writer": "Writer",
"Reader": "Reader",
"Free/Busy Reader": "Free/Busy Reader"
}

View File

@@ -0,0 +1,71 @@
{
"Google Calendar": "Google Calendar",
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Custom API Call": "Custom API Call",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Make a custom API call to a specific endpoint": "Make a custom API call to a specific endpoint",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "Description",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Method": "Method",
"Headers": "Headers",
"Query Parameters": "Query Parameters",
"Body": "Body",
"No Error on Failure": "No Error on Failure",
"Timeout (in seconds)": "Timeout (in seconds)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Select event types": "Select event types",
"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.": "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.",
"Authorization headers are injected automatically from your connection.": "Authorization headers are injected automatically from your connection.",
"All": "Tất cả",
"External Only": "External Only",
"none": "none",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "GET",
"POST": "POST",
"PATCH": "PATCH",
"PUT": "PUT",
"DELETE": "DELETE",
"HEAD": "HEAD",
"New or Updated Event": "New or Updated Event",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event."
}

View File

@@ -0,0 +1,145 @@
{
"Get organized and stay on schedule": "Get organized and stay on schedule",
"Add Attendees to Event": "Add Attendees to Event",
"Create Quick Event": "Create Quick Event",
"Create Event": "Create Event",
"Get all Events": "Get all Events",
"Update Event": "Update Event",
"Delete Event": "Delete Event",
"Find Busy/Free Periods in Calendar": "Find Busy/Free Periods in Calendar",
"Get Event by ID": "Get Event by ID",
"Custom API Call": "自定义 API 呼叫",
"Add one or more person to existing event.": "Add one or more person to existing event.",
"Add Quick Calendar Event": "Add Quick Calendar Event",
"Add Event": "Add Event",
"Get Events": "Get Events",
"Updates an event in Google Calendar.": "Updates an event in Google Calendar.",
"Deletes an event from Google Calendar.": "Deletes an event from Google Calendar.",
"Finds free/busy calendar details from Google Calendar.": "Finds free/busy calendar details from Google Calendar.",
"Fetch event details by its unique ID from Google Calendar.": "Fetch event details by its unique ID from Google Calendar.",
"Make a custom API call to a specific endpoint": "将一个自定义 API 调用到一个特定的终点",
"Calendar": "Calendar",
"Event ID": "Event ID",
"Attendees": "Attendees",
"Summary": "Summary",
"Send Updates": "Send Updates",
"Title of the event": "Title of the event",
"Start date time of the event": "Start date time of the event",
"End date time of the event": "End date time of the event",
"Location": "Location",
"Description": "描述",
"Color": "Color",
"Guests can modify": "Guests can modify",
"Guests can invite others": "Guests can invite others",
"Guests can see other guests": "Guests can see other guests",
"Send Notifications": "Send Notifications",
"Create Google Meet Link": "Create Google Meet Link",
"Event types": "Event types",
"Search Term": "Search Term",
"Date from": "Date from",
"Date to": "Date to",
"Expand Recurring Event?": "Expand Recurring Event?",
"Calendars": "Calendars",
"Start Time": "开始时间",
"End Time": "End Time",
"Max Attendees": "Max Attendees",
"Time Zone": "Time Zone",
"Method": "方法",
"Headers": "信头",
"Query Parameters": "查询参数",
"Body": "正文内容",
"Response is Binary ?": "Response is Binary ?",
"No Error on Failure": "失败时没有错误",
"Timeout (in seconds)": "超时(秒)",
"Emails of the attendees (guests)": "Emails of the attendees (guests)",
"The text describing the event to be created": "The text describing the event to be created",
"Guests who should receive notifications about the creation of the new event.": "Guests who should receive notifications about the creation of the new event.",
"By default it'll be 30 min post start time": "By default it'll be 30 min post start time",
"Description of the event. You can use HTML tags here.": "Description of the event. You can use HTML tags here.",
"Automatically create a Google Meet video conference link for this event": "Automatically create a Google Meet video conference link for this event",
"Select event types": "Select event types",
"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.": "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.",
"Select the calendars to check for busy periods.": "Select the calendars to check for busy periods.",
"The start of the time range to check.": "The start of the time range to check.",
"The end of the time range to check.": "The end of the time range to check.",
"The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.": "The unique ID of the event (e.g., \"abc123def456\"). You can find this in the event URL or from other calendar actions.",
"Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.": "Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.",
"Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.": "Time zone for the response (e.g., \"America/New_York\", \"Europe/London\"). Defaults to the calendar's time zone if not specified.",
"Authorization headers are injected automatically from your connection.": "授权头自动从您的连接中注入。",
"Enable for files like PDFs, images, etc..": "Enable for files like PDFs, images, etc..",
"All": "所有的",
"External Only": "External Only",
"none": "无",
"Yes, to everyone": "Yes, to everyone",
"To non-Google Calendar guests only": "To non-Google Calendar guests only",
"To no one": "To no one",
"Default": "Default",
"Out Of Office": "Out Of Office",
"Focus Time": "Focus Time",
"Working Location": "Working Location",
"GET": "获取",
"POST": "帖子",
"PATCH": "PATCH",
"PUT": "弹出",
"DELETE": "删除",
"HEAD": "黑色",
"New or Updated Event": "New or Updated Event",
"New Event": "New Event",
"Event Ends": "Event Ends",
"Event Start (Time Before)": "Event Start (Time Before)",
"New Event Matching Search": "New Event Matching Search",
"Event Cancelled": "Event Cancelled",
"New Calendar": "New Calendar",
"Triggers when an event is added or updated": "Triggers when an event is added or updated",
"Fires when a new event is created in a calendar.": "Fires when a new event is created in a calendar.",
"Fires when an event ends.": "Fires when an event ends.",
"Fires at a specified amount of time before an event starts (e.g., a reminder).": "Fires at a specified amount of time before an event starts (e.g., a reminder).",
"Fires when a new event is created that matches a specified search term.": "Fires when a new event is created that matches a specified search term.",
"Fires when an event is canceled or deleted.": "Fires when an event is canceled or deleted.",
"Fires when a new calendar is created or becomes accessible.": "Fires when a new calendar is created or becomes accessible.",
"Event Types to Monitor": "Event Types to Monitor",
"Search Filter": "Search Filter",
"Exclude All-Day Events": "Exclude All-Day Events",
"Target Specific Event": "Target Specific Event",
"Event": "Event",
"Time Before": "Time Before",
"Time Unit": "Time Unit",
"Event Types": "Event Types",
"Search In Fields": "Search In Fields",
"Cancellation Reasons": "Cancellation Reasons",
"Access Role Filter": "Access Role Filter",
"Calendar Name Filter": "Calendar Name Filter",
"Exclude Shared Calendars": "Exclude Shared Calendars",
"If true, the trigger will activate for every occurrence of a recurring event.": "If true, the trigger will activate for every occurrence of a recurring event.",
"Filter by specific event types (leave empty to monitor all event types)": "Filter by specific event types (leave empty to monitor all event types)",
"Only trigger for events containing this text in title, description, or location (optional)": "Only trigger for events containing this text in title, description, or location (optional)",
"Skip triggering for all-day events": "Skip triggering for all-day events",
"Enable to monitor a specific event instead of all events in the calendar.": "Enable to monitor a specific event instead of all events in the calendar.",
"The amount of time before the event starts.": "The amount of time before the event starts.",
"The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).": "The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).",
"Filter by specific event types (optional)": "Filter by specific event types (optional)",
"Specify which fields to search in (leave empty to use Google's default search across all fields)": "Specify which fields to search in (leave empty to use Google's default search across all fields)",
"Filter by specific types of cancellations (optional)": "Filter by specific types of cancellations (optional)",
"Only trigger for calendars with specific access roles (optional)": "Only trigger for calendars with specific access roles (optional)",
"Only trigger for calendars containing this text in name or description (optional)": "Only trigger for calendars containing this text in name or description (optional)",
"Only trigger for calendars you own, not shared calendars": "Only trigger for calendars you own, not shared calendars",
"Default Events": "Default Events",
"Birthday Events": "Birthday Events",
"Out of Office": "Out of Office",
"From Gmail": "From Gmail",
"Minutes": "Minutes",
"Hours": "Hours",
"Days": "Days",
"Event Title/Summary": "Event Title/Summary",
"Event Description": "Event Description",
"Event Location": "Event Location",
"Attendee Names/Emails": "Attendee Names/Emails",
"Event Deleted": "Event Deleted",
"Attendee Declined": "Attendee Declined",
"Event Rescheduled": "Event Rescheduled",
"Other Cancellations": "Other Cancellations",
"Owner": "所有者",
"Writer": "Writer",
"Reader": "Reader",
"Free/Busy Reader": "Free/Busy Reader"
}

View File

@@ -0,0 +1,92 @@
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import {
OAuth2PropertyValue,
PieceAuth,
createPiece,
} from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import { createEvent } from './lib/actions/create-event';
import { createQuickCalendarEvent } from './lib/actions/create-quick-event';
import { deleteEventAction } from './lib/actions/delete-event.action';
import { getEvents } from './lib/actions/get-events';
import { updateEventAction } from './lib/actions/update-event.action';
import { googleCalendarCommon } from './lib/common';
import { calendarEventChanged } from './lib/triggers/calendar-event';
import { addAttendeesToEventAction } from './lib/actions/add-attendees.action';
import { findFreeBusy } from './lib/actions/find-busy-free-periods';
import { getEventById } from './lib/actions/get-event-by-id';
import { newEvent } from './lib/triggers/new-event';
import { eventEnds } from './lib/triggers/event-ends';
import { eventStartTimeBefore } from './lib/triggers/event-start-time-before';
import { newEventMatchingSearch } from './lib/triggers/new-event-matching-search';
import { eventCancelled } from './lib/triggers/event-cancelled';
import { newCalendar } from './lib/triggers/new-calendar';
export const googleCalendarAuth = PieceAuth.OAuth2({
description: '',
authUrl: 'https://accounts.google.com/o/oauth2/auth',
tokenUrl: 'https://oauth2.googleapis.com/token',
required: true,
pkce: true,
scope: [
'https://www.googleapis.com/auth/calendar.events',
'https://www.googleapis.com/auth/calendar.readonly',
// TODO: Add the scope after Google App Verification
// 'https://www.googleapis.com/auth/calendar.calendarlist'
],
});
export const googleCalendar = createPiece({
minimumSupportedRelease: '0.30.0',
logoUrl: 'https://cdn.activepieces.com/pieces/google-calendar.png',
categories: [PieceCategory.PRODUCTIVITY],
displayName: 'Google Calendar',
description: 'Get organized and stay on schedule',
authors: [
'OsamaHaikal',
'bibhuty-did-this',
'Vitalini',
'pfernandez98',
'kishanprmr',
'MoShizzle',
'khaledmashaly',
'abuaboud',
'ikus060',
'Cloudieunnie',
'sanket-a11y',
'geekyme'
],
auth: googleCalendarAuth,
actions: [
addAttendeesToEventAction,
createQuickCalendarEvent,
createEvent,
getEvents,
updateEventAction,
deleteEventAction,
findFreeBusy,
getEventById,
// TODO: add action after calendarList scope is verified
// addCalendarToCalendarlist,
createCustomApiCallAction({
auth: googleCalendarAuth,
baseUrl() {
return googleCalendarCommon.baseUrl;
},
authMapping: async (auth) => {
return {
Authorization: `Bearer ${(auth).access_token}`,
};
},
}),
],
triggers: [calendarEventChanged,
newEvent,
eventEnds,
eventStartTimeBefore,
newEventMatchingSearch,
eventCancelled,
newCalendar
],
});

View File

@@ -0,0 +1,55 @@
import { googleCalendarAuth } from '../../';
import { createAction, Property } from '@activepieces/pieces-framework';
import { google, calendar_v3 } from 'googleapis';
import { OAuth2Client } from 'googleapis-common';
import { googleCalendarCommon } from '../common';
export const addAttendeesToEventAction = createAction({
auth: googleCalendarAuth,
name: 'google-calendar-add-attendees',
displayName: 'Add Attendees to Event',
description: 'Add one or more person to existing event.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
eventId: Property.ShortText({
displayName: 'Event ID',
required: true,
}),
attendees: Property.Array({
displayName: 'Attendees',
description: 'Emails of the attendees (guests)',
required: true,
}),
},
async run(context) {
const { calendar_id, eventId } = context.propsValue;
const attendeesInput = context.propsValue.attendees as string[];
const authClient = new OAuth2Client();
authClient.setCredentials(context.auth);
const calendar = google.calendar({ version: 'v3', auth: authClient });
// Note that each patch request consumes three quota units;
// prefer using a get followed by an update
const currentEvent = await calendar.events.get({
calendarId: calendar_id,
eventId: eventId,
});
const currentAttendees = currentEvent.data.attendees ?? [];
const attendeeFormattedList: calendar_v3.Schema$EventAttendee[] = [];
attendeeFormattedList.push(...currentAttendees);
attendeeFormattedList.push(...attendeesInput.map((email) => ({ email })));
const response = await calendar.events.update({
calendarId: calendar_id!,
eventId,
requestBody: {
...currentEvent.data,
attendees: attendeeFormattedList,
},
});
return response.data;
},
});

View File

@@ -0,0 +1,36 @@
import { googleCalendarAuth } from '../../index';
import { createAction, Property } from '@activepieces/pieces-framework';
import { OAuth2Client } from 'googleapis-common';
import { google } from 'googleapis';
import { googleCalendarCommon } from '../common';
export const addCalendarToCalendarlist = createAction({
auth: googleCalendarAuth,
name: 'addCalendarToCalendarlist',
displayName: 'Add Calendar to calendarList',
description: "Adds other people's calendars to your calendarList",
props: {
id: Property.ShortText({
displayName: "Calendar Id",
description: "Find calendar id by going to calendar settings",
required: true
})
},
async run(context) {
const id = context.propsValue.id;
const authClient = new OAuth2Client();
authClient.setCredentials(context.auth);
const calendar = google.calendar({ version: 'v3', auth: authClient});
const response = await calendar.calendarList.insert({
requestBody: {
id: id
}
})
return response.data;
},
});

View File

@@ -0,0 +1,166 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import dayjs from 'dayjs';
import { googleCalendarAuth } from '../../';
import { google } from 'googleapis';
import { OAuth2Client } from 'googleapis-common';
import { randomUUID } from 'crypto';
export const createEvent = createAction({
auth: googleCalendarAuth,
name: 'create_google_calendar_event',
description: 'Add Event',
displayName: 'Create Event',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
title: Property.ShortText({
displayName: 'Title of the event',
required: true,
}),
start_date_time: Property.DateTime({
displayName: 'Start date time of the event',
required: true,
}),
end_date_time: Property.DateTime({
displayName: 'End date time of the event',
description: "By default it'll be 30 min post start time",
required: false,
}),
location: Property.ShortText({
displayName: 'Location',
required: false,
}),
/*attachment: Property.ShortText({
displayName: 'Attachment',
description: 'URL of the file to be attached',
required: false,
}),*/
description: Property.LongText({
displayName: 'Description',
description: 'Description of the event. You can use HTML tags here.',
required: false,
}),
colorId: googleCalendarCommon.colorId,
attendees: Property.Array({
displayName: 'Attendees',
description: 'Emails of the attendees (guests)',
required: false,
}),
guests_can_modify: Property.Checkbox({
displayName: 'Guests can modify',
defaultValue: false,
required: false,
}),
guests_can_invite_others: Property.Checkbox({
displayName: 'Guests can invite others',
defaultValue: false,
required: false,
}),
guests_can_see_other_guests: Property.Checkbox({
displayName: 'Guests can see other guests',
defaultValue: false,
required: false,
}),
send_notifications: Property.StaticDropdown({
displayName: 'Send Notifications',
defaultValue: 'all',
options: {
options: [
{ label: 'Yes, to everyone', value: 'all' },
{
label: 'To non-Google Calendar guests only',
value: 'externalOnly',
},
{ label: 'To no one', value: 'none' },
],
},
required: true,
}),
create_meet_link: Property.Checkbox({
displayName: 'Create Google Meet Link',
description: 'Automatically create a Google Meet video conference link for this event',
defaultValue: false,
required: false,
}),
},
async run(configValue) {
// docs: https://developers.google.com/calendar/api/v3/reference/events/insert
const {
calendar_id: calendarId,
title: summary,
start_date_time,
end_date_time,
location,
description,
colorId,
guests_can_modify: guestsCanModify,
guests_can_invite_others: guestsCanInviteOthers,
guests_can_see_other_guests: guestsCanSeeOtherGuests,
create_meet_link: createMeetLink,
} = configValue.propsValue;
const start = {
dateTime: dayjs(start_date_time).format('YYYY-MM-DDTHH:mm:ss.sssZ'),
};
const endTime = end_date_time
? end_date_time
: dayjs(start_date_time).add(30, 'm');
const end = {
dateTime: dayjs(endTime).format('YYYY-MM-DDTHH:mm:ss.sssZ'),
};
/*const attachment = {
fileUrl: configValue.propsValue.attachment,
};*/
const attendeesArray = configValue.propsValue.attendees as string[];
const sendNotifications = configValue.propsValue.send_notifications;
const attendeesObject = [];
if (attendeesArray) {
for (const attendee of attendeesArray) {
attendeesObject.push({ email: attendee });
}
}
const authClient = new OAuth2Client();
authClient.setCredentials(configValue.auth);
const calendar = google.calendar({ version: 'v3', auth: authClient });
const requestBody: any = {
summary,
start,
end,
colorId,
//attachments: configValue.propsValue.attachment ? [attachment] : [],
location: location ?? '',
description: description ?? '',
attendees: attendeesObject,
guestsCanInviteOthers,
guestsCanModify,
guestsCanSeeOtherGuests,
};
if (createMeetLink) {
requestBody.conferenceData = {
createRequest: {
conferenceSolutionKey: {
type: 'hangoutsMeet',
},
requestId: randomUUID(),
},
};
}
const response = await calendar.events.insert({
calendarId,
sendUpdates: sendNotifications,
conferenceDataVersion: createMeetLink ? 1 : 0,
requestBody,
});
return response.data;
},
});

View File

@@ -0,0 +1,67 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpRequest,
HttpMethod,
AuthenticationType,
httpClient,
} from '@activepieces/pieces-common';
import { googleCalendarCommon } from '../common';
import { googleCalendarAuth } from '../../';
export const createQuickCalendarEvent = createAction({
auth: googleCalendarAuth,
name: 'create_quick_event',
description: 'Add Quick Calendar Event',
displayName: 'Create Quick Event',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
text: Property.LongText({
displayName: 'Summary',
description: 'The text describing the event to be created',
required: true,
}),
send_updates: Property.StaticDropdown<string>({
displayName: 'Send Updates',
description:
'Guests who should receive notifications about the creation of the new event.',
required: false,
options: {
disabled: false,
options: [
{
label: 'All',
value: 'all',
},
{
label: 'External Only',
value: 'externalOnly',
},
{
label: 'none',
value: 'none',
},
],
},
}),
},
async run(configValue) {
// docs: https://developers.google.com/calendar/api/v3/reference/events/quickAdd
const calendarId = configValue.propsValue['calendar_id'];
const url = `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events/quickAdd`;
const qParams: Record<string, string> = {
text: configValue.propsValue['text'],
sendUpdates: configValue.propsValue['send_updates'] || 'none',
};
const request: HttpRequest<Record<string, unknown>> = {
method: HttpMethod.POST,
url,
body: {},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: configValue.auth.access_token,
},
queryParams: qParams,
};
return await httpClient.sendRequest(request);
},
});

View File

@@ -0,0 +1,35 @@
import { Property, createAction } from '@activepieces/pieces-framework';
import { google } from 'googleapis';
import { OAuth2Client } from 'googleapis-common';
import { googleCalendarAuth } from '../../index';
import { googleCalendarCommon } from '../common';
export const deleteEventAction = createAction({
displayName: 'Delete Event',
auth: googleCalendarAuth,
name: 'delete_event',
description: 'Deletes an event from Google Calendar.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
eventId: Property.ShortText({
displayName: 'Event ID',
required: true,
}),
},
async run(context) {
const authClient = new OAuth2Client();
authClient.setCredentials(context.auth);
const calendarId = context.propsValue.calendar_id;
const eventId = context.propsValue.eventId;
const calendar = google.calendar({ version: 'v3', auth: authClient });
const response = await calendar.events.delete({
calendarId,
eventId,
});
return response.data;
},
});

View File

@@ -0,0 +1,98 @@
import { createAction, Property, OAuth2PropertyValue } from '@activepieces/pieces-framework';
import { HttpRequest, HttpMethod, AuthenticationType, httpClient } from '@activepieces/pieces-common';
import { googleCalendarAuth } from '../../';
import { googleCalendarCommon } from '../common';
import { getCalendars } from '../common/helper';
import dayjs from 'dayjs';
interface FreeBusyResponse {
kind: 'calendar#freeBusy';
timeMin: string;
timeMax: string;
calendars: {
[calendarId: string]: {
busy: {
start: string;
end: string;
}[];
errors?: {
domain: string;
reason: string;
}[];
};
};
}
export const findFreeBusy = createAction({
auth: googleCalendarAuth,
name: 'google_calendar_find_busy_free_periods',
displayName: 'Find Busy/Free Periods in Calendar',
description: 'Finds free/busy calendar details from Google Calendar.',
props: {
calendar_ids: Property.MultiSelectDropdown({
auth: googleCalendarAuth,
displayName: 'Calendars',
description: 'Select the calendars to check for busy periods.',
required: true,
refreshers: [],
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Connect your account first',
options: [],
};
}
const authProp = auth as OAuth2PropertyValue;
const calendars = await getCalendars(authProp);
return {
disabled: false,
options: calendars.map((calendar) => {
return {
label: calendar.summary,
value: calendar.id,
};
}),
};
},
}),
start_date: Property.DateTime({
displayName: 'Start Time',
description: 'The start of the time range to check.',
required: true,
}),
end_date: Property.DateTime({
displayName: 'End Time',
description: 'The end of the time range to check.',
required: true,
}),
},
async run(context) {
const { calendar_ids, start_date, end_date } = context.propsValue;
const { access_token } = context.auth;
const requestBody = {
timeMin: dayjs(start_date).toISOString(),
timeMax: dayjs(end_date).toISOString(),
items: calendar_ids.map((id) => ({ id })),
};
const request: HttpRequest = {
method: HttpMethod.POST,
url: `${googleCalendarCommon.baseUrl}/freeBusy`,
body: requestBody,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: access_token,
},
};
const response = await httpClient.sendRequest<FreeBusyResponse>(request);
return response.body;
},
});

View File

@@ -0,0 +1,124 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpRequest,
HttpMethod,
AuthenticationType,
httpClient,
} from '@activepieces/pieces-common';
import { googleCalendarCommon } from '../common';
import { googleCalendarAuth } from '../../';
import { GoogleCalendarEvent } from '../common/types';
export const getEventById = createAction({
auth: googleCalendarAuth,
name: 'google_calendar_get_event_by_id',
displayName: 'Get Event by ID',
description: 'Fetch event details by its unique ID from Google Calendar.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown(),
event_id: Property.ShortText({
displayName: 'Event ID',
description:
'The unique ID of the event (e.g., "abc123def456"). You can find this in the event URL or from other calendar actions.',
required: true,
}),
max_attendees: Property.Number({
displayName: 'Max Attendees',
description:
'Maximum number of attendees to include in the response. If there are more attendees, only the participant is returned.',
required: false,
}),
time_zone: Property.ShortText({
displayName: 'Time Zone',
description:
'Time zone for the response (e.g., "America/New_York", "Europe/London"). Defaults to the calendar\'s time zone if not specified.',
required: false,
}),
},
async run(context) {
const {
calendar_id: calendarId,
event_id: eventId,
max_attendees: maxAttendees,
time_zone: timeZone,
} = context.propsValue;
const { access_token: token } = context.auth;
if (
!calendarId ||
typeof calendarId !== 'string' ||
calendarId.trim().length === 0
) {
throw new Error('Calendar ID is required');
}
if (
!eventId ||
typeof eventId !== 'string' ||
eventId.trim().length === 0
) {
throw new Error('Event ID cannot be empty');
}
if (eventId.length < 5 || eventId.length > 1024) {
throw new Error('Event ID must be between 5 and 1024 characters');
}
const queryParams: Record<string, string> = {};
if (maxAttendees !== undefined && maxAttendees > 0) {
queryParams.maxAttendees = maxAttendees.toString();
}
if (
timeZone &&
typeof timeZone === 'string' &&
timeZone.trim().length > 0
) {
queryParams.timeZone = timeZone.trim();
}
const url = `${googleCalendarCommon.baseUrl}/calendars/${encodeURIComponent(
calendarId.trim()
)}/events/${encodeURIComponent(eventId.trim())}`;
const request: HttpRequest = {
method: HttpMethod.GET,
url: url,
queryParams: queryParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: token,
},
};
try {
const response = await httpClient.sendRequest<GoogleCalendarEvent>(
request
);
return response.body;
} catch (error: any) {
if (error.response?.status === 404) {
throw new Error(
`Event with ID "${eventId}" not found in calendar "${calendarId}". Please verify the event ID and calendar selection.`
);
} else if (error.response?.status === 403) {
throw new Error(
`Access denied to event "${eventId}" in calendar "${calendarId}". Please check your permissions.`
);
} else if (error.response?.status === 400) {
throw new Error(
`Invalid request parameters. Please check the event ID format and other parameters.`
);
} else if (error.response?.status === 401) {
throw new Error(
'Authentication failed. Please reconnect your Google Calendar account.'
);
} else {
throw new Error(
`Failed to fetch event: ${error.message || 'Unknown error occurred'}`
);
}
}
},
});

View File

@@ -0,0 +1,112 @@
import { createAction, Property } from '@activepieces/pieces-framework';
import {
HttpRequest,
HttpMethod,
AuthenticationType,
httpClient,
} from '@activepieces/pieces-common';
import { googleCalendarCommon } from '../common';
import dayjs from 'dayjs';
import { googleCalendarAuth } from '../../';
export const getEvents = createAction({
auth: googleCalendarAuth,
name: 'google_calendar_get_events',
description: 'Get Events',
displayName: 'Get all Events',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
event_types: Property.StaticMultiSelectDropdown({
displayName: 'Event types',
description: 'Select event types',
required: true,
defaultValue: ['default', 'focusTime', 'outOfOffice'],
options: {
options: [
{
label: 'Default',
value: 'default',
},
{
label: 'Out Of Office',
value: 'outOfOffice',
},
{
label: 'Focus Time',
value: 'focusTime',
},
{
label: 'Working Location',
value: 'workingLocation',
},
],
},
}),
search: Property.ShortText({
displayName: 'Search Term',
required: false,
}),
start_date: Property.DateTime({
displayName: 'Date from',
required: false,
}),
end_date: Property.DateTime({
displayName: 'Date to',
required: false,
}),
singleEvents: Property.Checkbox({
displayName: 'Expand Recurring Event?',
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.",
required: true,
defaultValue: false,
}),
},
async run(configValue) {
// docs: https://developers.google.com/calendar/api/v3/reference/events/list
const {
calendar_id: calendarId,
start_date,
end_date,
search,
event_types,
singleEvents,
} = configValue.propsValue;
const { access_token: token } = configValue.auth;
const queryParams: Record<string, string> = { showDeleted: 'false' };
let url = `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events`;
if(singleEvents !== null) {
queryParams['singleEvents'] = singleEvents ? 'true' : 'false';
}
if (search) {
queryParams['q'] = `"${search}"`;
}
// date range
if (start_date) {
queryParams['timeMin'] = dayjs(start_date).format(
'YYYY-MM-DDTHH:mm:ss.sssZ'
);
}
if (start_date && end_date) {
queryParams['timeMax'] = dayjs(end_date).format(
'YYYY-MM-DDTHH:mm:ss.sssZ'
);
}
// filter by event type
if (event_types.length > 0) {
url += `?${event_types.map((type) => `eventTypes=${type}`).join('&')}`;
}
const request: HttpRequest<Record<string, unknown>> = {
method: HttpMethod.GET,
url,
queryParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token,
},
};
return await httpClient.sendRequest(request);
},
});

View File

@@ -0,0 +1,129 @@
import { Property, createAction } from '@activepieces/pieces-framework';
import { google, calendar_v3 } from 'googleapis';
import { OAuth2Client } from 'googleapis-common';
import { googleCalendarAuth } from '../../index';
import { googleCalendarCommon } from '../common';
import dayjs from 'dayjs';
export const updateEventAction = createAction({
displayName: 'Update Event',
auth: googleCalendarAuth,
name: 'update_event',
description: 'Updates an event in Google Calendar.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
eventId: Property.ShortText({
displayName: 'Event ID',
required: true,
}),
title: Property.ShortText({
displayName: 'Title of the event',
required: false,
}),
start_date_time: Property.DateTime({
displayName: 'Start date time of the event',
required: false,
}),
end_date_time: Property.DateTime({
displayName: 'End date time of the event',
required: false,
}),
location: Property.ShortText({
displayName: 'Location',
required: false,
}),
description: Property.LongText({
displayName: 'Description',
description: 'Description of the event. You can use HTML tags here.',
required: false,
}),
colorId: googleCalendarCommon.colorId,
attendees: Property.Array({
displayName: 'Attendees',
description: 'Emails of the attendees (guests)',
required: false,
}),
guests_can_modify: Property.Checkbox({
displayName: 'Guests can modify',
defaultValue: false,
required: false,
}),
guests_can_invite_others: Property.Checkbox({
displayName: 'Guests can invite others',
defaultValue: false,
required: false,
}),
guests_can_see_other_guests: Property.Checkbox({
displayName: 'Guests can see other guests',
defaultValue: false,
required: false,
}),
},
async run(context) {
const {
calendar_id,
eventId,
title,
start_date_time,
end_date_time,
location,
description,
colorId,
guests_can_invite_others,
guests_can_modify,
guests_can_see_other_guests,
} = context.propsValue;
const attendees = context.propsValue.attendees as string[];
const authClient = new OAuth2Client();
authClient.setCredentials(context.auth);
const calendar = google.calendar({ version: 'v3', auth: authClient });
// Note that each patch request consumes three quota units;
// prefer using a get followed by an update
const currentEvent = await calendar.events.get({
calendarId: calendar_id,
eventId: eventId,
});
let attendeeFormattedList: calendar_v3.Schema$EventAttendee[] = [];
if (Array.isArray(attendees) && attendees.length > 0) {
attendeeFormattedList = attendees.map((email) => ({ email }));
} else if (
currentEvent.data.attendees &&
Array.isArray(currentEvent.data.attendees)
) {
attendeeFormattedList = currentEvent.data.attendees;
}
const response = await calendar.events.update({
calendarId: calendar_id,
eventId: eventId,
requestBody: {
summary: title ?? currentEvent.data.summary,
attendees: attendeeFormattedList,
description: description ?? currentEvent.data.description,
colorId: colorId,
location: location ?? currentEvent.data.location,
start: start_date_time
? {
dateTime: dayjs(start_date_time).format(
'YYYY-MM-DDTHH:mm:ss.sssZ'
),
}
: currentEvent.data.start,
end: end_date_time
? {
dateTime: dayjs(end_date_time).format('YYYY-MM-DDTHH:mm:ss.sssZ'),
}
: currentEvent.data.end,
guestsCanInviteOthers: guests_can_invite_others,
guestsCanModify: guests_can_modify,
guestsCanSeeOtherGuests: guests_can_see_other_guests,
},
});
return response.data;
},
});

View File

@@ -0,0 +1,228 @@
import { OAuth2PropertyValue } from '@activepieces/pieces-framework';
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
import { randomUUID } from 'crypto';
import { googleCalendarCommon } from '.';
import {
GoogleWatchResponse,
GoogleWatchType,
CalendarObject,
CalendarList,
GoogleCalendarEvent,
GoogleCalendarEventList,
GetColorsResponse,
} from './types';
export async function stopWatchEvent(
body: GoogleWatchResponse,
authProp: OAuth2PropertyValue
) {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `${googleCalendarCommon.baseUrl}/channels/stop`,
body: {
id: body?.id,
resourceId: body?.resourceId,
},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
await httpClient.sendRequest<any>(request);
}
export async function watchEvent(
calendarId: string,
webhookUrl: string,
authProp: OAuth2PropertyValue
): Promise<GoogleWatchResponse> {
const request: HttpRequest = {
method: HttpMethod.POST,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events/watch`,
body: {
id: randomUUID(),
type: GoogleWatchType.WEBHOOK,
address: webhookUrl,
},
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
const { body: webhook } = await httpClient.sendRequest<GoogleWatchResponse>(
request
);
return webhook;
}
export async function getCalendars(
authProp: OAuth2PropertyValue,
minAccessRole?: 'writer'
): Promise<CalendarObject[]> {
// docs: https://developers.google.com/calendar/api/v3/reference/calendarList/list
const queryParams: Record<string, string> = {
showDeleted: 'false',
};
if (minAccessRole) {
queryParams['minAccessRole'] = minAccessRole;
}
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/users/me/calendarList`,
queryParams: queryParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
const response = await httpClient.sendRequest<CalendarList>(request);
return response.body.items;
}
export async function getColors(
authProp: OAuth2PropertyValue
): Promise<GetColorsResponse> {
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/colors`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
const response = await httpClient.sendRequest<GetColorsResponse>(request);
return response.body;
}
export async function getEvents(
calendarId: string,
expandRecurringEvent: boolean,
authProp: OAuth2PropertyValue,
minUpdated?: Date
): Promise<GoogleCalendarEvent[]> {
// docs: https://developers.google.com/calendar/api/v3/reference/events/list
const now = new Date();
const yesterday = new Date();
yesterday.setDate(now.getDate() - 1);
const qParams: Record<string, string> = {
updatedMin: minUpdated?.toISOString() ?? yesterday.toISOString(),
maxResults: '2500', // Modified
orderBy: 'updated',
singleEvents: expandRecurringEvent ? 'true' : 'false',
showDeleted: 'true',
};
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events`,
queryParams: qParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
let eventList: GoogleCalendarEvent[] = [];
let pageToken = '';
do {
qParams['pageToken'] = pageToken;
const { body: res } = await httpClient.sendRequest<GoogleCalendarEventList>(
request
);
if (res.items.length > 0) {
eventList = [...eventList, ...res.items];
}
pageToken = res.nextPageToken;
} while (pageToken);
return eventList;
}
export async function getLatestEvent(
calendarId: string,
authProp: OAuth2PropertyValue
): Promise<GoogleCalendarEvent> {
const eventList = await getEvents(calendarId, false, authProp);
const lastUpdatedEvent = eventList.pop()!; // You can retrieve the last updated event.
return lastUpdatedEvent;
}
export async function getEventsForDropdown(
authProp: OAuth2PropertyValue,
calendarId?: string,
maxResults = 50
): Promise<{ label: string; value: string }[]> {
if (!calendarId) {
return [];
}
try {
const now = new Date();
const futureDate = new Date();
futureDate.setDate(now.getDate() + 30);
const queryParams: Record<string, string> = {
singleEvents: 'true',
orderBy: 'startTime',
timeMin: now.toISOString(),
timeMax: futureDate.toISOString(),
maxResults: maxResults.toString(),
showDeleted: 'false',
};
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${encodeURIComponent(
calendarId
)}/events`,
queryParams: queryParams,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: authProp.access_token,
},
};
const response = await httpClient.sendRequest<GoogleCalendarEventList>(
request
);
if (!response.body.items || response.body.items.length === 0) {
return [];
}
return response.body.items
.map((event) => {
const startTime = event.start?.dateTime || event.start?.date || '';
const startDate = startTime
? new Date(startTime).toLocaleDateString()
: '';
const startTimeFormatted = startTime
? new Date(startTime).toLocaleTimeString()
: '';
let label = event.summary || 'Untitled Event';
if (startDate) {
label += ` (${startDate}`;
if (event.start?.dateTime) {
label += ` at ${startTimeFormatted}`;
}
label += ')';
}
return {
label: label,
value: event.id || '',
};
})
.filter((item) => item.value !== '');
} catch (error) {
console.error('Error fetching events for dropdown:', error);
return [];
}
}

View File

@@ -0,0 +1,93 @@
import { OAuth2PropertyValue, Property } from '@activepieces/pieces-framework';
import { getCalendars, getColors, getEventsForDropdown } from './helper';
import { googleCalendarAuth } from '../..';
export const googleCalendarCommon = {
baseUrl: 'https://www.googleapis.com/calendar/v3',
calendarDropdown: (minAccessRole?: 'writer') => {
return Property.Dropdown<string,true,typeof googleCalendarAuth>({
auth: googleCalendarAuth,
displayName: 'Calendar',
refreshers: [],
required: true,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first',
options: [],
};
}
const authProp = auth as OAuth2PropertyValue;
const calendars = await getCalendars(authProp, minAccessRole);
return {
disabled: false,
options: calendars.map((calendar) => {
return {
label: calendar.summary,
value: calendar.id,
};
}),
};
},
});
},
eventDropdown: (required = false) => {
return Property.Dropdown<string,boolean,typeof googleCalendarAuth>({
displayName: 'Event',
refreshers: ['calendar_id'],
required: required,
auth: googleCalendarAuth,
options: async ({ auth, calendar_id }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first',
options: [],
};
}
if (!calendar_id) {
return {
disabled: true,
placeholder: 'Please select a calendar first',
options: [],
};
}
const authProp = auth as OAuth2PropertyValue;
const events = await getEventsForDropdown(
authProp,
calendar_id as string
);
return {
disabled: false,
options: events,
};
},
});
},
colorId: Property.Dropdown({
auth: googleCalendarAuth,
displayName: 'Color',
refreshers: [],
required: false,
options: async ({ auth }) => {
if (!auth) {
return {
disabled: true,
placeholder: 'Please connect your account first',
options: [],
};
}
const response = await getColors(auth);
return {
disabled: false,
options: Object.entries(response.event).map(([key, value]) => {
return {
label: value.background,
value: key,
};
}),
};
},
}),
};

View File

@@ -0,0 +1,246 @@
export enum GoogleWatchType {
WEBHOOK = 'web_hook',
}
export enum GoogleCalendarKind {
CALENDAR_LIST = 'calendar#calendarList',
CALENDAR_ENTRY = 'calendar#calendarListEntry',
CALENDAR_EVENT = 'calendar#event',
CALENDAR_EVENT_LIST = 'calendar#events',
EVENT_WATCH = 'api#channel',
CALENDAR_COLORS = 'calendar#colors',
}
export interface CalendarList {
kind: GoogleCalendarKind.CALENDAR_LIST;
etag: string;
nextPageToken: string;
nextSyncToken: string;
items: CalendarObject[];
}
export interface CalendarObject {
kind: GoogleCalendarKind.CALENDAR_ENTRY;
etag: string;
id: string;
summary: string;
description: string;
location: string;
timeZone: string;
summaryOverride: string;
colorId: string;
backgroundColor: string;
foregroundColor: string;
hidden: boolean;
selected: boolean;
accessRole: string;
defaultReminders: [
{
method: string;
minutes: number;
}
];
notificationSettings: {
notifications: [
{
type: string;
method: string;
}
];
};
primary: boolean;
deleted: boolean;
conferenceProperties: {
allowedConferenceSolutionTypes: string[];
};
}
export interface GoogleWatchResponse {
kind: GoogleCalendarKind.EVENT_WATCH;
id: string;
resourceId: string;
resourceUri: string;
token: string;
expiration: number;
}
interface Attendee {
id: string;
email: string;
displayName: string;
organizer: boolean;
self: boolean;
resource: boolean;
optional: boolean;
responseStatus: string;
comment: string;
additionalGuests: BigInteger;
}
export interface GoogleCalendarEvent {
kind: GoogleCalendarKind.CALENDAR_EVENT;
etag: string;
id: string;
status: string;
htmlLink: string;
created: string;
updated: string;
summary: string;
description: string;
location: string;
colorId: string;
creator: {
id: string;
email: string;
displayName: string;
self: boolean;
};
organizer: {
id: string;
email: string;
displayName: string;
self: boolean;
};
start: {
date: Date;
dateTime: Date;
timeZone: string;
};
end: {
date: Date;
dateTime: Date;
timeZone: string;
};
endTimeUnspecified: boolean;
recurrence: [string];
recurringEventId: string;
originalStartTime: {
date: Date;
dateTime: Date;
timeZone: string;
};
transparency: string;
visibility: string;
iCalUID: string;
sequence: BigInteger;
attendees: Attendee[];
attendeesOmitted: boolean;
extendedProperties: {
private: {
key: string;
};
shared: {
key: string;
};
};
hangoutLink: string;
conferenceData: {
createRequest: {
requestId: string;
conferenceSolutionKey: {
type: string;
};
status: {
statusCode: string;
};
};
entryPoints: [
{
entryPointType: string;
uri: string;
label: string;
pin: string;
accessCode: string;
meetingCode: string;
passcode: string;
password: string;
}
];
conferenceSolution: {
key: {
type: string;
};
name: string;
iconUri: string;
};
conferenceId: string;
signature: string;
notes: string;
};
gadget: {
type: string;
title: string;
link: string;
iconLink: string;
width: BigInteger;
height: BigInteger;
display: string;
preferences: {
key: string;
};
};
anyoneCanAddSelf: boolean;
guestsCanInviteOthers: boolean;
guestsCanModify: boolean;
guestsCanSeeOtherGuests: boolean;
privateCopy: boolean;
locked: boolean;
reminders: {
useDefault: boolean;
overrides: [
{
method: string;
minutes: BigInteger;
}
];
};
source: {
url: string;
title: string;
};
attachments: [
{
fileUrl: string;
title: string;
mimeType: string;
iconLink: string;
fileId: string;
}
];
eventType: string;
}
export interface GoogleCalendarEventList {
kind: GoogleCalendarKind.CALENDAR_EVENT_LIST;
etag: string;
summary: string;
description: string;
updated: number;
timeZone: string;
accessRole: string;
defaultReminders: [
{
method: string;
minutes: BigInteger;
}
];
nextPageToken: string;
nextSyncToken: string;
items: GoogleCalendarEvent[];
}
export interface GetColorsResponse {
kind: GoogleCalendarKind.CALENDAR_COLORS;
calendar: {
[s: string]: {
background: string;
foreground: string;
};
};
event: {
[s: string]: {
background: string;
foreground: string;
};
};
}

View File

@@ -0,0 +1,25 @@
---
title: 'Google Calendar'
description: ''
---
## Set up and run an app that calls a Google calendar API.
1. In the Google Cloud console, enable the Google Calendar API.
2. Click In the Google Cloud console, and go to Menu menu > APIs & Services > Credentials.
3. Click Create Credentials > OAuth client ID.
4. In the Name field, type a name for the credential. This name is only shown in the Google Cloud console.
5. Click Create. The OAuth client created screen appears, showing your new Client ID and Client secret.
6. Click OK. The newly created credential appears under OAuth 2.0 Client IDs.
---
## Triggers
TRIGGERS
---
## Actions
ACTIONS

View File

@@ -0,0 +1,139 @@
import { AppConnectionValueForAuthProperty, createTrigger, PiecePropValueSchema, Property } from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import { getEvents } from '../common/helper';
import { GoogleCalendarEvent } from '../common/types';
import { googleCalendarAuth } from '../../';
import { DedupeStrategy, Polling, pollingHelper } from '@activepieces/pieces-common';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{ calendarId?: string; expandRecurringEvent: boolean }
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue: { calendarId, expandRecurringEvent }, lastFetchEpochMS }) => {
let minUpdated = new Date(lastFetchEpochMS);
// Google Calendar API breaks if minUpdated is too far in the past
if (lastFetchEpochMS === 0) {
const now = new Date();
const yesterday = new Date();
yesterday.setDate(now.getDate() - 7);
minUpdated = yesterday;
}
const currentValues: GoogleCalendarEvent[] =
(await getEvents(calendarId!, expandRecurringEvent, auth, minUpdated)) ?? [];
const items = currentValues.map((item) => ({
epochMilliSeconds: new Date(item.updated).getTime(),
data: item,
}));
return items;
},
};
export const calendarEventChanged = createTrigger({
// docs: https://developers.google.com/calendar/api/guides/push
auth: googleCalendarAuth,
name: 'new_or_updated_event',
displayName: 'New or Updated Event',
description: 'Triggers when an event is added or updated',
props: {
calendar_id: googleCalendarCommon.calendarDropdown(),
expandRecurringEvent: Property.Checkbox({
displayName: 'Expand Recurring Event?',
description: 'If true, the trigger will activate for every occurrence of a recurring event.',
required: true,
defaultValue: false,
}),
},
sampleData: {
kind: 'calendar#event',
etag: '3350849506974000',
id: '0nsfi5ttd2b17ac76ma2f37oi9',
htmlLink: 'https://www.google.com/calendar/event?eid=kgjb90uioj4klrgfmdsnjsjvlgkm',
summary: 'ap-event-test',
created: '2023-02-03T11:36:36.000Z',
updated: '2023-02-03T11:45:53.487Z',
description: 'Sample description',
status: 'canceled',
creator: {
email: 'test@test.com',
self: true,
},
organizer: {
email: 'test@test.com',
self: true,
},
start: {
dateTime: '2023-02-02T22:30:00+03:00',
timeZone: 'Asia/Amman',
},
end: {
dateTime: '2023-02-02T23:30:00+03:00',
timeZone: 'Asia/Amman',
},
transparency: 'transparent',
iCalUID: '0nsfi5ttd2b17ac76ma2f37oi9@google.com',
sequence: 1,
attendees: [
{
email: 'attende@test.com',
responseStatus: 'needsAction',
},
{
email: 'test@test.com',
organizer: true,
self: true,
responseStatus: 'accepted',
},
],
reminders: {
useDefault: true,
},
eventType: 'default',
},
type: TriggerStrategy.POLLING,
async test({ store, auth, propsValue, files }) {
return await pollingHelper.test(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendar_id,
expandRecurringEvent: propsValue.expandRecurringEvent,
},
files,
});
},
async onEnable({ store, auth, propsValue }) {
await pollingHelper.onEnable(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendar_id,
expandRecurringEvent: propsValue.expandRecurringEvent,
},
});
},
async onDisable({ store, auth, propsValue }) {
await pollingHelper.onDisable(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendar_id,
expandRecurringEvent: propsValue.expandRecurringEvent,
},
});
},
async run({ store, auth, propsValue, files }) {
return await pollingHelper.poll(polling, {
store,
auth,
propsValue: {
calendarId: propsValue.calendar_id,
expandRecurringEvent: propsValue.expandRecurringEvent,
},
files,
});
},
});

View File

@@ -0,0 +1,200 @@
import {
AppConnectionValueForAuthProperty,
createTrigger,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import { GoogleCalendarEvent } from '../common/types';
import { googleCalendarAuth } from '../../';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
import { getEvents } from '../common/helper';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{
calendar_id: string | undefined;
specific_event: boolean | undefined;
event_id: string | undefined;
cancellation_reason: string[] | undefined;
}
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
const {
calendar_id: calendarId,
specific_event,
event_id,
cancellation_reason,
} = propsValue;
if (!calendarId) {
return [];
}
if (specific_event && !event_id) {
return [];
}
let minUpdated: Date;
if (lastFetchEpochMS === 0) {
minUpdated = new Date();
minUpdated.setDate(minUpdated.getDate() - 1);
} else {
minUpdated = new Date(lastFetchEpochMS);
}
let events: GoogleCalendarEvent[] = [];
if (specific_event && event_id) {
const eventRequest: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events/${event_id}`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
};
try {
const eventResponse = await httpClient.sendRequest<GoogleCalendarEvent>(
eventRequest
);
const event = eventResponse.body;
const updatedTime = new Date(event.updated ?? 0).getTime();
if (updatedTime > lastFetchEpochMS && event.status === 'cancelled') {
events = [event];
}
} catch (error) {
console.error('Error fetching specific event:', error);
return [];
}
} else {
const allEvents = await getEvents(calendarId, true, auth, minUpdated);
events = allEvents.filter((event) => event.status === 'cancelled');
}
if (cancellation_reason && cancellation_reason.length > 0) {
events = events.filter((event) => {
return cancellation_reason.some((reason) => {
switch (reason) {
case 'deleted':
return !event.summary || event.summary.includes('Deleted');
case 'declined':
return (
event.attendees?.some(
(attendee) => attendee.responseStatus === 'declined'
) || false
);
case 'rescheduled':
return (
event.summary?.toLowerCase().includes('rescheduled') ||
event.description?.toLowerCase().includes('rescheduled') ||
false
);
case 'other':
return true;
default:
return true;
}
});
});
}
return events.map((event) => {
return {
epochMilliSeconds: new Date(event.updated!).getTime(),
data: event,
};
});
},
};
export const eventCancelled = createTrigger({
auth: googleCalendarAuth,
name: 'event_cancelled',
displayName: 'Event Cancelled',
description: 'Fires when an event is canceled or deleted.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
specific_event: Property.Checkbox({
displayName: 'Target Specific Event',
description:
'Enable to monitor a specific event instead of all events in the calendar.',
required: false,
defaultValue: false,
}),
event_id: googleCalendarCommon.eventDropdown(false),
cancellation_reason: Property.StaticMultiSelectDropdown({
displayName: 'Cancellation Reasons',
description: 'Filter by specific types of cancellations (optional)',
required: false,
options: {
options: [
{ label: 'Event Deleted', value: 'deleted' },
{ label: 'Attendee Declined', value: 'declined' },
{ label: 'Event Rescheduled', value: 'rescheduled' },
{ label: 'Other Cancellations', value: 'other' },
],
},
}),
},
type: TriggerStrategy.POLLING,
sampleData: {
id: 'abc123def456_cancelled',
summary: 'Cancelled: Q3 Planning Session',
status: 'cancelled',
created: '2025-07-20T10:00:00.000Z',
updated: '2025-08-14T09:30:00.000Z',
organizer: { email: 'project.manager@example.com' },
start: { dateTime: '2025-08-25T10:00:00-07:00' },
end: { dateTime: '2025-08-25T11:30:00-07:00' },
},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async run(context) {
return await pollingHelper.poll(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
async test(context) {
return await pollingHelper.test(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
});

View File

@@ -0,0 +1,202 @@
import {
AppConnectionValueForAuthProperty,
createTrigger,
Property,
} from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import { GoogleCalendarEvent } from '../common/types';
import { googleCalendarAuth } from '../../';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
interface GoogleCalendarEventList {
items: GoogleCalendarEvent[];
}
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{
calendar_id: string | undefined;
specific_event: boolean | undefined;
event_id: string | undefined;
}
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
if (lastFetchEpochMS === 0) {
return [];
}
const { calendar_id: calendarId, specific_event, event_id } = propsValue;
if (!calendarId) {
return [];
}
if (specific_event && !event_id) {
return [];
}
let events: GoogleCalendarEvent[] = [];
if (specific_event && event_id) {
const eventRequest: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events/${event_id}`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
};
try {
const eventResponse = await httpClient.sendRequest<GoogleCalendarEvent>(
eventRequest
);
const event = eventResponse.body;
const endTimeString = event.end?.dateTime ?? event.end?.date;
if (endTimeString) {
const endTime = new Date(endTimeString).getTime();
if (endTime > lastFetchEpochMS) {
events = [event];
}
}
} catch (error) {
console.error('Error fetching specific event:', error);
return [];
}
} else {
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendarId}/events`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
queryParams: {
singleEvents: 'true',
orderBy: 'startTime',
timeMin: new Date(lastFetchEpochMS).toISOString(),
},
};
const response = await httpClient.sendRequest<GoogleCalendarEventList>(
request
);
events = response.body.items;
}
const endedEvents: {
epochMilliSeconds: number;
data: GoogleCalendarEvent;
}[] = [];
const now = Date.now();
for (const event of events) {
const endTimeString = event.end?.dateTime ?? event.end?.date;
if (!endTimeString) continue;
const endTime = new Date(endTimeString).getTime();
if (endTime > lastFetchEpochMS && endTime <= now) {
endedEvents.push({
epochMilliSeconds: endTime,
data: event,
});
}
}
return endedEvents;
},
};
export const eventEnds = createTrigger({
auth: googleCalendarAuth,
name: 'event_ends',
displayName: 'Event Ends',
description: 'Fires when an event ends.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
specific_event: Property.Checkbox({
displayName: 'Target Specific Event',
description:
'Enable to monitor a specific event instead of all events in the calendar.',
required: false,
defaultValue: false,
}),
event_id: googleCalendarCommon.eventDropdown(false),
},
type: TriggerStrategy.POLLING,
sampleData: {
kind: 'calendar#event',
etag: '"3419997894982000"',
id: 'sample_event_id_67890',
status: 'confirmed',
htmlLink:
'https://www.google.com/calendar/event?eid=c2FtcGxlX2V2ZW50X2lkXzY3ODkw',
created: '2025-08-14T09:00:00.000Z',
updated: '2025-08-14T09:00:00.000Z',
summary: 'Project Deadline',
creator: { email: 'manager@example.com' },
organizer: {
email: 'manager@example.com',
self: true,
},
start: {
dateTime: '2025-08-14T14:30:00+05:30',
timeZone: 'Asia/Kolkata',
},
end: {
dateTime: '2025-08-14T15:30:00+05:30',
timeZone: 'Asia/Kolkata',
},
iCalUID: 'sample_event_id_67890@google.com',
sequence: 0,
reminders: { useDefault: true },
eventType: 'default',
},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async run(context) {
return await pollingHelper.poll(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
async test(context) {
return await pollingHelper.test(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
});

View File

@@ -0,0 +1,202 @@
import {
AppConnectionValueForAuthProperty,
createTrigger,
PiecePropValueSchema,
Property,
} from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import { GoogleCalendarEvent } from '../common/types';
import { googleCalendarAuth } from '../../';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
interface GoogleCalendarEventList {
items: GoogleCalendarEvent[];
}
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{
calendar_id: string | undefined;
specific_event: boolean | undefined;
event_id: string | undefined;
time_value: number | undefined;
time_unit: string | undefined;
}
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue }) => {
const { calendar_id, specific_event, event_id, time_value, time_unit } =
propsValue;
if (!calendar_id || !time_value || !time_unit) {
return [];
}
if (specific_event && !event_id) {
return [];
}
let offset_ms = time_value * 60 * 1000;
if (time_unit === 'hours') {
offset_ms = time_value * 60 * 60 * 1000;
} else if (time_unit === 'days') {
offset_ms = time_value * 24 * 60 * 60 * 1000;
}
const now = Date.now();
const pollingIntervalMs = 5 * 60 * 1000;
const timeMin = new Date(now + offset_ms).toISOString();
const timeMax = new Date(now + offset_ms + pollingIntervalMs).toISOString();
let events: GoogleCalendarEvent[] = [];
if (specific_event && event_id) {
const eventRequest: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendar_id}/events/${event_id}`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
};
try {
const eventResponse = await httpClient.sendRequest<GoogleCalendarEvent>(
eventRequest
);
const event = eventResponse.body;
// Check if this specific event falls within our time window
const eventStartTime = new Date(
event.start?.dateTime ?? event.start?.date ?? 0
).getTime();
const triggerTime = eventStartTime - offset_ms;
if (triggerTime >= now && triggerTime <= now + pollingIntervalMs) {
events = [event];
}
} catch (error) {
console.error('Error fetching specific event:', error);
return [];
}
} else {
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendar_id}/events`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
queryParams: {
singleEvents: 'true',
orderBy: 'startTime',
timeMin: timeMin,
timeMax: timeMax,
},
};
const response = await httpClient.sendRequest<GoogleCalendarEventList>(
request
);
events = response.body.items;
}
return events.map((event) => {
const startTime = new Date(
event.start?.dateTime ?? event.start?.date ?? 0
).getTime();
const triggerTime = startTime - offset_ms;
return {
epochMilliSeconds: triggerTime,
data: event,
};
});
},
};
export const eventStartTimeBefore = createTrigger({
auth: googleCalendarAuth,
name: 'event_starts_in',
displayName: 'Event Start (Time Before)',
description:
'Fires at a specified amount of time before an event starts (e.g., a reminder).',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
specific_event: Property.Checkbox({
displayName: 'Target Specific Event',
description:
'Enable to monitor a specific event instead of all events in the calendar.',
required: false,
defaultValue: false,
}),
event_id: googleCalendarCommon.eventDropdown(false),
time_value: Property.Number({
displayName: 'Time Before',
description: 'The amount of time before the event starts.',
required: true,
defaultValue: 15,
}),
time_unit: Property.StaticDropdown({
displayName: 'Time Unit',
required: true,
options: {
options: [
{ label: 'Minutes', value: 'minutes' },
{ label: 'Hours', value: 'hours' },
{ label: 'Days', value: 'days' },
],
},
defaultValue: 'minutes',
}),
},
type: TriggerStrategy.POLLING,
sampleData: {},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async run(context) {
return await pollingHelper.poll(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
async test(context) {
return await pollingHelper.test(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
});

View File

@@ -0,0 +1,203 @@
import {
createTrigger,
AppConnectionValueForAuthProperty,
Property,
} from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarAuth } from '../../';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import { getCalendars } from '../common/helper';
import { CalendarObject } from '../common/types';
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{
access_role_filter: string[] | undefined;
calendar_name_filter: string | undefined;
exclude_shared: boolean | undefined;
}
> = {
strategy: DedupeStrategy.LAST_ITEM,
items: async ({ auth, store, propsValue }) => {
const { access_role_filter, calendar_name_filter, exclude_shared } =
propsValue;
const currentCalendars = await getCalendars(auth);
let filteredCalendars = currentCalendars;
if (access_role_filter && access_role_filter.length > 0) {
filteredCalendars = filteredCalendars.filter((cal) =>
access_role_filter.includes(cal.accessRole)
);
}
if (calendar_name_filter && calendar_name_filter.trim()) {
const searchTerm = calendar_name_filter.toLowerCase().trim();
filteredCalendars = filteredCalendars.filter(
(cal) =>
cal.summary?.toLowerCase().includes(searchTerm) ||
cal.description?.toLowerCase().includes(searchTerm)
);
}
if (exclude_shared) {
filteredCalendars = filteredCalendars.filter(
(cal) => cal.accessRole === 'owner' || cal.primary
);
}
const currentCalendarIds = filteredCalendars.map((cal) => cal.id);
const oldCalendarIds = (await store.get<string[]>('calendars')) || [];
const oldCalendarIdsSet = new Set(oldCalendarIds);
const newCalendars = filteredCalendars.filter(
(cal) => !oldCalendarIdsSet.has(cal.id)
);
await store.put('calendars', currentCalendarIds);
return newCalendars.map((cal) => ({
id: cal.id,
data: {
...cal,
isOwned: cal.accessRole === 'owner' || cal.primary,
isShared: cal.accessRole !== 'owner' && !cal.primary,
calendarType: cal.primary
? 'primary'
: cal.accessRole === 'owner'
? 'owned'
: 'shared',
},
}));
},
};
export const newCalendar = createTrigger({
auth: googleCalendarAuth,
name: 'new_calendar',
displayName: 'New Calendar',
description: 'Fires when a new calendar is created or becomes accessible.',
props: {
access_role_filter: Property.StaticMultiSelectDropdown({
displayName: 'Access Role Filter',
description:
'Only trigger for calendars with specific access roles (optional)',
required: false,
options: {
options: [
{ label: 'Owner', value: 'owner' },
{ label: 'Writer', value: 'writer' },
{ label: 'Reader', value: 'reader' },
{ label: 'Free/Busy Reader', value: 'freeBusyReader' },
],
},
}),
calendar_name_filter: Property.ShortText({
displayName: 'Calendar Name Filter',
description:
'Only trigger for calendars containing this text in name or description (optional)',
required: false,
}),
exclude_shared: Property.Checkbox({
displayName: 'Exclude Shared Calendars',
description: 'Only trigger for calendars you own, not shared calendars',
required: false,
defaultValue: false,
}),
},
type: TriggerStrategy.POLLING,
sampleData: {
id: 'sample_calendar_id@group.calendar.google.com',
summary: 'New Project Team Calendar',
description: 'A shared calendar for the new project team.',
timeZone: 'Asia/Kolkata',
backgroundColor: '#9fe1e7',
foregroundColor: '#000000',
accessRole: 'owner',
isOwned: true,
isShared: false,
calendarType: 'owned',
primary: false,
},
async onEnable(context) {
const calendars = await getCalendars(context.auth);
const { access_role_filter, calendar_name_filter, exclude_shared } =
context.propsValue;
let filteredCalendars = calendars;
if (access_role_filter && access_role_filter.length > 0) {
filteredCalendars = filteredCalendars.filter((cal) =>
access_role_filter.includes(cal.accessRole)
);
}
if (calendar_name_filter && calendar_name_filter.trim()) {
const searchTerm = calendar_name_filter.toLowerCase().trim();
filteredCalendars = filteredCalendars.filter(
(cal) =>
cal.summary?.toLowerCase().includes(searchTerm) ||
cal.description?.toLowerCase().includes(searchTerm)
);
}
if (exclude_shared) {
filteredCalendars = filteredCalendars.filter(
(cal) => cal.accessRole === 'owner' || cal.primary
);
}
await context.store.put(
'calendars',
filteredCalendars.map((cal) => cal.id)
);
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async run(context) {
return await pollingHelper.poll(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
async test(context) {
const calendars = await getCalendars(context.auth);
const recentCalendars = calendars.slice(-1);
return recentCalendars.map((cal: CalendarObject) => ({
id: cal.id,
data: {
...cal,
isOwned: cal.accessRole === 'owner' || cal.primary,
isShared: cal.accessRole !== 'owner' && !cal.primary,
calendarType: cal.primary
? 'primary'
: cal.accessRole === 'owner'
? 'owned'
: 'shared',
},
}));
},
});

View File

@@ -0,0 +1,226 @@
import {
createTrigger,
AppConnectionValueForAuthProperty,
Property,
} from '@activepieces/pieces-framework';
import { TriggerStrategy } from '@activepieces/pieces-framework';
import { googleCalendarCommon } from '../common';
import { GoogleCalendarEvent } from '../common/types';
import { googleCalendarAuth } from '../../';
import {
DedupeStrategy,
Polling,
pollingHelper,
} from '@activepieces/pieces-common';
import {
AuthenticationType,
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
interface GoogleCalendarEventList {
items: GoogleCalendarEvent[];
}
const polling: Polling<
AppConnectionValueForAuthProperty<typeof googleCalendarAuth>,
{
calendar_id: string | undefined;
search_term: string | undefined;
event_types: string[] | undefined;
search_fields: string[] | undefined;
}
> = {
strategy: DedupeStrategy.TIMEBASED,
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
const { calendar_id, search_term, event_types, search_fields } = propsValue;
if (!calendar_id || !search_term) {
return [];
}
let minUpdated: Date;
if (lastFetchEpochMS === 0) {
minUpdated = new Date();
minUpdated.setDate(minUpdated.getDate() - 1);
} else {
minUpdated = new Date(lastFetchEpochMS);
}
const queryParams: Record<string, string> = {
singleEvents: 'true',
orderBy: 'updated',
updatedMin: minUpdated.toISOString(),
q: search_term,
};
if (event_types && event_types.length > 0) {
event_types.forEach((type) => {
if (!queryParams.eventTypes) {
queryParams.eventTypes = type;
} else {
queryParams.eventTypes += '&eventTypes=' + type;
}
});
}
const request: HttpRequest = {
method: HttpMethod.GET,
url: `${googleCalendarCommon.baseUrl}/calendars/${calendar_id}/events`,
authentication: {
type: AuthenticationType.BEARER_TOKEN,
token: auth.access_token,
},
queryParams: queryParams,
};
const response = await httpClient.sendRequest<GoogleCalendarEventList>(
request
);
const events = response.body.items;
const newEvents = events.filter((event) => {
const created = new Date(event.created ?? 0).getTime();
const updated = new Date(event.updated ?? 0).getTime();
const isNewEvent = updated - created < 5000;
if (!isNewEvent) return false;
if (search_fields && search_fields.length > 0) {
const searchTermLower = search_term.toLowerCase();
return search_fields.some((field) => {
switch (field) {
case 'summary':
return (
event.summary?.toLowerCase().includes(searchTermLower) || false
);
case 'description':
return (
event.description?.toLowerCase().includes(searchTermLower) ||
false
);
case 'location':
return (
event.location?.toLowerCase().includes(searchTermLower) || false
);
case 'attendees':
return (
event.attendees?.some(
(attendee) =>
attendee.email?.toLowerCase().includes(searchTermLower) ||
attendee.displayName
?.toLowerCase()
.includes(searchTermLower)
) || false
);
default:
return false;
}
});
}
return true;
});
return newEvents.map((event) => {
return {
epochMilliSeconds: new Date(event.updated!).getTime(),
data: event,
};
});
},
};
export const newEventMatchingSearch = createTrigger({
auth: googleCalendarAuth,
name: 'new_event_matching_search',
displayName: 'New Event Matching Search',
description:
'Fires when a new event is created that matches a specified search term.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
search_term: Property.ShortText({
displayName: 'Search Term',
description:
'The keyword(s) to search for in new events (searches across title, description, location, and attendees by default).',
required: true,
}),
event_types: Property.StaticMultiSelectDropdown({
displayName: 'Event Types',
description: 'Filter by specific event types (optional)',
required: false,
options: {
options: [
{ label: 'Default Events', value: 'default' },
{ label: 'Birthday Events', value: 'birthday' },
{ label: 'Focus Time', value: 'focusTime' },
{ label: 'Out of Office', value: 'outOfOffice' },
{ label: 'Working Location', value: 'workingLocation' },
{ label: 'From Gmail', value: 'fromGmail' },
],
},
}),
search_fields: Property.StaticMultiSelectDropdown({
displayName: 'Search In Fields',
description:
"Specify which fields to search in (leave empty to use Google's default search across all fields)",
required: false,
options: {
options: [
{ label: 'Event Title/Summary', value: 'summary' },
{ label: 'Event Description', value: 'description' },
{ label: 'Event Location', value: 'location' },
{ label: 'Attendee Names/Emails', value: 'attendees' },
],
},
}),
},
type: TriggerStrategy.POLLING,
sampleData: {
id: 'abc123def456',
summary: 'Final Project Review',
description: 'Review of the Q3 final project deliverables.',
status: 'confirmed',
created: '2025-08-14T09:05:00.000Z',
updated: '2025-08-14T09:05:01.000Z',
start: { dateTime: '2025-09-01T10:00:00-07:00' },
end: { dateTime: '2025-09-01T11:30:00-07:00' },
organizer: { email: 'project.manager@example.com' },
},
async onEnable(context) {
await pollingHelper.onEnable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async onDisable(context) {
await pollingHelper.onDisable(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
});
},
async run(context) {
return await pollingHelper.poll(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
async test(context) {
return await pollingHelper.test(polling, {
auth: context.auth,
store: context.store,
propsValue: context.propsValue,
files: context.files,
});
},
});

View File

@@ -0,0 +1,186 @@
import {
createTrigger,
TriggerStrategy,
OAuth2PropertyValue,
Property,
} from '@activepieces/pieces-framework';
import { googleCalendarAuth } from '../../';
import { googleCalendarCommon } from '../common';
import { stopWatchEvent, watchEvent, getLatestEvent } from '../common/helper';
import { GoogleWatchResponse, GoogleCalendarEvent } from '../common/types';
export const newEvent = createTrigger({
auth: googleCalendarAuth,
name: 'new_event',
displayName: 'New Event',
description: 'Fires when a new event is created in a calendar.',
props: {
calendar_id: googleCalendarCommon.calendarDropdown('writer'),
event_types: Property.StaticMultiSelectDropdown({
displayName: 'Event Types to Monitor',
description:
'Filter by specific event types (leave empty to monitor all event types)',
required: false,
options: {
options: [
{ label: 'Default Events', value: 'default' },
{ label: 'Birthday Events', value: 'birthday' },
{ label: 'Focus Time', value: 'focusTime' },
{ label: 'Out of Office', value: 'outOfOffice' },
{ label: 'Working Location', value: 'workingLocation' },
{ label: 'From Gmail', value: 'fromGmail' },
],
},
}),
search_filter: Property.ShortText({
displayName: 'Search Filter',
description:
'Only trigger for events containing this text in title, description, or location (optional)',
required: false,
}),
exclude_all_day: Property.Checkbox({
displayName: 'Exclude All-Day Events',
description: 'Skip triggering for all-day events',
required: false,
defaultValue: false,
}),
},
type: TriggerStrategy.WEBHOOK,
sampleData: {
kind: 'calendar#event',
etag: '"3419997894982000"',
id: 'sample_event_id_12345',
status: 'confirmed',
htmlLink:
'https://www.google.com/calendar/event?eid=c2FtcGxlX2V2ZW50X2lkXzEyMzQ1',
created: '2025-08-15T11:02:27.000Z',
updated: '2025-08-15T11:02:27.491Z',
summary: 'Team Sync',
creator: { email: 'creator@example.com' },
organizer: {
email: 'creator@example.com',
self: true,
},
start: {
dateTime: '2025-08-18T10:00:00-07:00',
timeZone: 'America/Los_Angeles',
},
end: {
dateTime: '2025-08-18T11:00:00-07:00',
timeZone: 'America/Los_Angeles',
},
iCalUID: 'sample_event_id_12345@google.com',
sequence: 0,
reminders: { useDefault: true },
eventType: 'default',
},
async onEnable(context) {
const calendarId = context.propsValue.calendar_id!;
const auth = context.auth as OAuth2PropertyValue;
const response = await watchEvent(calendarId, context.webhookUrl, auth);
await context.store.put<GoogleWatchResponse>(
'google_calendar_watch',
response
);
},
async onDisable(context) {
const auth = context.auth as OAuth2PropertyValue;
const watch = await context.store.get<GoogleWatchResponse>(
'google_calendar_watch'
);
if (watch) {
await stopWatchEvent(watch, auth);
}
},
async run(context) {
const payload = context.payload;
const headers = payload.headers as Record<string, string>;
const { event_types, search_filter, exclude_all_day } = context.propsValue;
if (headers['x-goog-resource-state'] === 'add') {
const eventData = payload.body as GoogleCalendarEvent;
if (event_types && event_types.length > 0) {
const eventType = eventData.eventType || 'default';
if (!event_types.includes(eventType)) {
return [];
}
}
if (search_filter && search_filter.trim()) {
const searchTerm = search_filter.toLowerCase().trim();
const summary = (eventData.summary || '').toLowerCase();
const description = (eventData.description || '').toLowerCase();
const location = (eventData.location || '').toLowerCase();
const matchesSearch =
summary.includes(searchTerm) ||
description.includes(searchTerm) ||
location.includes(searchTerm);
if (!matchesSearch) {
return [];
}
}
if (exclude_all_day) {
const isAllDay = eventData.start?.date && !eventData.start?.dateTime;
if (isAllDay) {
return [];
}
}
return [eventData];
} else {
return [];
}
},
async test(context) {
const auth = context.auth as OAuth2PropertyValue;
const { event_types, search_filter, exclude_all_day } = context.propsValue;
const latestEvent = await getLatestEvent(
context.propsValue.calendar_id!,
auth
);
if (event_types && event_types.length > 0) {
const eventType = latestEvent.eventType || 'default';
if (!event_types.includes(eventType)) {
return [];
}
}
if (search_filter && search_filter.trim()) {
const searchTerm = search_filter.toLowerCase().trim();
const summary = (latestEvent.summary || '').toLowerCase();
const description = (latestEvent.description || '').toLowerCase();
const location = (latestEvent.location || '').toLowerCase();
const matchesSearch =
summary.includes(searchTerm) ||
description.includes(searchTerm) ||
location.includes(searchTerm);
if (!matchesSearch) {
return [];
}
}
if (exclude_all_day) {
const isAllDay = latestEvent.start?.date && !latestEvent.start?.dateTime;
if (isAllDay) {
return [];
}
}
return [latestEvent];
},
});

View File

@@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}

View File

@@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"include": ["src/**/*.ts"]
}