import { IHookFunctions, IWebhookFunctions, } from 'n8n-core'; import { IDataObject, ILoadOptionsFunctions, INodePropertyOptions, INodeType, INodeTypeDescription, IWebhookResponseData, } from 'n8n-workflow'; import { eventbriteApiRequest, eventbriteApiRequestAllItems, } from './GenericFunctions'; export class EventbriteTrigger implements INodeType { description: INodeTypeDescription = { displayName: 'Eventbrite Trigger', name: 'eventbriteTrigger', icon: 'file:eventbrite.png', group: ['trigger'], version: 1, description: 'Handle Eventbrite events via webhooks', defaults: { name: 'Eventbrite Trigger', color: '#dc5237', }, inputs: [], outputs: ['main'], credentials: [ { name: 'eventbriteApi', required: true, displayOptions: { show: { authentication: [ 'privateKey', ], }, }, }, { name: 'eventbriteOAuth2Api', required: true, displayOptions: { show: { authentication: [ 'oAuth2', ], }, }, }, ], webhooks: [ { name: 'default', httpMethod: 'POST', responseMode: 'onReceived', path: 'webhook', }, ], properties: [ { displayName: 'Authentication', name: 'authentication', type: 'options', options: [ { name: 'Private Key', value: 'privateKey', }, { name: 'OAuth2', value: 'oAuth2', }, ], default: 'privateKey', description: 'The resource to operate on.', }, { displayName: 'Organization', name: 'organization', type: 'options', required: true, typeOptions: { loadOptionsMethod: 'getOrganizations' }, default: '', description: '', }, { displayName: 'Event', name: 'event', type: 'options', required: true, typeOptions: { loadOptionsDependsOn: [ 'organization', ], loadOptionsMethod: 'getEvents' }, default: '', description: '', }, { displayName: 'Actions', name: 'actions', type: 'multiOptions', options: [ { name: 'attendee.updated', value: 'attendee.updated' }, { name: 'attendee.checked_in', value: 'attendee.checked_in' }, { name: 'attendee.checked_out', value: 'attendee.checked_out' }, { name: 'event.created', value: 'event.created' }, { name: 'event.published', value: 'event.published' }, { name: 'event.unpublished', value: 'event.unpublished' }, { name: 'event.updated', value: 'event.updated' }, { name: 'order.placed', value: 'order.placed' }, { name: 'order.refunded', value: 'order.refunded' }, { name: 'order.updated', value: 'order.updated' }, { name: 'organizer.updated', value: 'organizer.updated' }, { name: 'ticket_class.created', value: 'ticket_class.created' }, { name: 'ticket_class.deleted', value: 'ticket_class.deleted' }, { name: 'ticket_class.updated', value: 'ticket_class.updated' }, { name: 'venue.updated', value: 'venue.updated' }, ], required: true, default: [], description: '', }, { displayName: 'Resolve Data', name: 'resolveData', type: 'boolean', default: true, description: 'By default does the webhook-data only contain the URL to receive
the object data manually. If this option gets activated it
will resolve the data automatically.', }, ], }; methods = { loadOptions: { // Get all the available organizations to display them to user so that he can // select them easily async getOrganizations(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; const organizations = await eventbriteApiRequestAllItems.call(this, 'organizations', 'GET', '/users/me/organizations'); for (const organization of organizations) { const organizationName = organization.name; const organizationId = organization.id; returnData.push({ name: organizationName, value: organizationId, }); } return returnData; }, // Get all the available events to display them to user so that he can // select them easily async getEvents(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; const organization = this.getCurrentNodeParameter('organization'); const events = await eventbriteApiRequestAllItems.call(this, 'events', 'GET', `/organizations/${organization}/events`); for (const event of events) { const eventName = event.name.text; const eventId = event.id; returnData.push({ name: eventName, value: eventId, }); } return returnData; }, }, }; // @ts-ignore webhookMethods = { default: { async checkExists(this: IHookFunctions): Promise { const webhookData = this.getWorkflowStaticData('node'); const webhookUrl = this.getNodeWebhookUrl('default'); const organisation = this.getNodeParameter('organization') as string; const actions = this.getNodeParameter('actions') as string[]; const endpoint = `/organizations/${organisation}/webhooks/`; const { webhooks } = await eventbriteApiRequest.call(this, 'GET', endpoint); const check = (currentActions: string[], webhookActions: string[]) => { for (const currentAction of currentActions) { if (!webhookActions.includes(currentAction)) { return false; } } return true; }; for (const webhook of webhooks) { if (webhook.endpoint_url === webhookUrl && check(actions, webhook.actions)) { webhookData.webhookId = webhook.id; return true; } } return false; }, async create(this: IHookFunctions): Promise { const webhookUrl = this.getNodeWebhookUrl('default'); const webhookData = this.getWorkflowStaticData('node'); const organisation = this.getNodeParameter('organization') as string; const event = this.getNodeParameter('event') as string; const actions = this.getNodeParameter('actions') as string[]; const endpoint = `/organizations/${organisation}/webhooks/`; const body: IDataObject = { endpoint_url: webhookUrl, actions: actions.join(','), event_id: event, }; const responseData = await eventbriteApiRequest.call(this, 'POST', endpoint, body); webhookData.webhookId = responseData.id; return true; }, async delete(this: IHookFunctions): Promise { let responseData; const webhookData = this.getWorkflowStaticData('node'); const endpoint = `/webhooks/${webhookData.webhookId}/`; try { responseData = await eventbriteApiRequest.call(this, 'DELETE', endpoint); } catch(error) { return false; } if (!responseData.success) { return false; } delete webhookData.webhookId; return true; }, }, }; async webhook(this: IWebhookFunctions): Promise { const req = this.getRequestObject(); if (req.body.api_url === undefined) { throw new Error('The received data does not contain required "api_url" property!'); } const resolveData = this.getNodeParameter('resolveData', false) as boolean; if (resolveData === false) { // Return the data as it got received return { workflowData: [ this.helpers.returnJsonArray(req.body), ], }; } if (req.body.api_url.includes('api-endpoint-to-fetch-object-details')) { return { workflowData: [ this.helpers.returnJsonArray({ placeholder: 'Test received. To display actual data of object get the webhook triggered by performing the action which triggers it.', }) ], }; } const responseData = await eventbriteApiRequest.call(this, 'GET', '', {}, undefined, req.body.api_url); return { workflowData: [ this.helpers.returnJsonArray(responseData), ], }; } }