diff --git a/packages/nodes-base/nodes/ActiveCampaign/ActiveCampaignTrigger.node.ts b/packages/nodes-base/nodes/ActiveCampaign/ActiveCampaignTrigger.node.ts new file mode 100644 index 0000000000..b76ed9fd3b --- /dev/null +++ b/packages/nodes-base/nodes/ActiveCampaign/ActiveCampaignTrigger.node.ts @@ -0,0 +1,162 @@ +import { + IHookFunctions, + IWebhookFunctions, +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + INodeType, + INodeTypeDescription, + INodePropertyOptions, + IWebhookResponseData, +} from 'n8n-workflow'; + +import { + activeCampaignApiRequest, + activeCampaignApiRequestAllItems, +} from './GenericFunctions'; + +export class ActiveCampaignTrigger implements INodeType { + description: INodeTypeDescription = { + displayName: 'Active Campaign Trigger', + name: 'activeCampaignTrigger', + icon: 'file:activeCampaign.png', + group: ['trigger'], + version: 1, + description: 'Handle Active Campaign events via webhooks', + defaults: { + name: 'ActiveCampaign Trigger', + color: '#356ae6', + }, + inputs: [], + outputs: ['main'], + credentials: [ + { + name: 'activeCampaignApi', + required: true, + } + ], + webhooks: [ + { + name: 'default', + httpMethod: 'POST', + responseMode: 'onReceived', + path: 'webhook', + }, + ], + properties: [ + { + displayName: 'Events', + name: 'events', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getEvents', + }, + default: [], + options: [], + }, + { + displayName: 'Source', + name: 'sources', + type: 'multiOptions', + options: [ + { + name: 'Public', + value: 'public', + description: 'Run the hooks when a contact triggers the action', + }, + { + name: 'Admin', + value: 'admin', + description: 'Run the hooks when an admin user triggers the action', + }, + { + name: 'Api', + value: 'api', + description: 'Run the hooks when an API call triggers the action', + }, + { + name: 'System', + value: 'system', + description: 'Run the hooks when automated systems triggers the action', + }, + ], + default: [], + }, + ], + }; + methods = { + loadOptions: { + // Get all the events to display them to user so that he can + // select them easily + async getEvents(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const events = await activeCampaignApiRequestAllItems.call(this, 'GET', '/api/3/webhook/events', {}, {}, 'webhookEvents'); + for (const event of events) { + const eventName = event; + const eventId = event; + returnData.push({ + name: eventName, + value: eventId, + }); + } + return returnData; + }, + } + }; + // @ts-ignore + webhookMethods = { + default: { + async checkExists(this: IHookFunctions): Promise { + const webhookData = this.getWorkflowStaticData('node'); + if (webhookData.webhookId === undefined) { + return false; + } + const endpoint = `/api/3/webhooks/${webhookData.webhookId}`; + try { + await activeCampaignApiRequest.call(this, 'GET', endpoint, {}); + } catch (e) { + return false; + } + return true; + }, + async create(this: IHookFunctions): Promise { + const webhookUrl = this.getNodeWebhookUrl('default') as string; + const webhookData = this.getWorkflowStaticData('node'); + const events = this.getNodeParameter('events', []) as string[]; + const sources = this.getNodeParameter('sources', '') as string[]; + const body: IDataObject = { + webhook: { + name: `n8n-webhook:${webhookUrl}`, + url: webhookUrl, + events, + sources, + } + }; + const { webhook } = await activeCampaignApiRequest.call(this, 'POST', '/api/3/webhooks', body); + webhookData.webhookId = webhook.id; + return true; + }, + async delete(this: IHookFunctions): Promise { + const webhookData = this.getWorkflowStaticData('node'); + try { + await activeCampaignApiRequest.call(this, 'DELETE', `/api/3/webhooks/${webhookData.webhookId}`, {}); + } catch(error) { + return false; + } + delete webhookData.webhookId; + return true; + }, + }, + }; + + async webhook(this: IWebhookFunctions): Promise { + const req = this.getRequestObject(); + return { + workflowData: [ + this.helpers.returnJsonArray(req.body) + ], + }; + } +} diff --git a/packages/nodes-base/nodes/ActiveCampaign/GenericFunctions.ts b/packages/nodes-base/nodes/ActiveCampaign/GenericFunctions.ts index fe607b80b9..833e334b92 100644 --- a/packages/nodes-base/nodes/ActiveCampaign/GenericFunctions.ts +++ b/packages/nodes-base/nodes/ActiveCampaign/GenericFunctions.ts @@ -4,7 +4,7 @@ import { } from 'n8n-core'; import { - IDataObject, + IDataObject, ILoadOptionsFunctions, } from 'n8n-workflow'; import { OptionsWithUri } from 'request'; @@ -25,7 +25,7 @@ export interface IProduct { * @param {object} body * @returns {Promise} */ -export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, dataKey?: string): Promise { // tslint:disable-line:no-any +export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, dataKey?: string): Promise { // tslint:disable-line:no-any const credentials = this.getCredentials('activeCampaignApi'); if (credentials === undefined) { throw new Error('No credentials got returned!'); @@ -50,7 +50,7 @@ export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFu } try { - const responseData = await this.helpers.request(options); + const responseData = await this.helpers.request!(options); if (responseData.success === false) { throw new Error(`ActiveCampaign error response: ${responseData.error} (${responseData.error_info})`); @@ -87,7 +87,7 @@ export async function activeCampaignApiRequest(this: IHookFunctions | IExecuteFu * @param {IDataObject} [query] * @returns {Promise} */ -export async function activeCampaignApiRequestAllItems(this: IHookFunctions | IExecuteFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, dataKey?: string): Promise { // tslint:disable-line:no-any +export async function activeCampaignApiRequestAllItems(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: IDataObject, query?: IDataObject, dataKey?: string): Promise { // tslint:disable-line:no-any if (query === undefined) { query = {}; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 470c6e5a7e..16792b6f8a 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -83,6 +83,7 @@ ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", + "dist/nodes/ActiveCampaign/ActiveCampaignTrigger.node.js", "dist/nodes/Airtable/Airtable.node.js", "dist/nodes/Amqp/Amqp.node.js", "dist/nodes/Amqp/AmqpTrigger.node.js",