n8n/packages/nodes-base/nodes/Twilio/TwilioTrigger.node.ts
Bram Kn c204995d9c
feat: Add Twilio Trigger Node (#8859)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Giulio Andreini <andreini@netseven.it>
2024-03-29 10:24:25 +02:00

197 lines
4.9 KiB
TypeScript

import type {
IHookFunctions,
IWebhookFunctions,
INodeType,
INodeTypeDescription,
IWebhookResponseData,
} from 'n8n-workflow';
import { twilioTriggerApiRequest } from './GenericFunctions';
export class TwilioTrigger implements INodeType {
description: INodeTypeDescription = {
displayName: 'Twilio Trigger',
name: 'twilioTrigger',
icon: 'file:twilio.svg',
group: ['trigger'],
version: [1],
defaultVersion: 1,
subtitle: '=Updates: {{$parameter["updates"].join(", ")}}',
description: 'Starts the workflow on a Twilio update',
defaults: {
name: 'Twilio Trigger',
},
inputs: [],
outputs: ['main'],
credentials: [
{
name: 'twilioApi',
required: true,
},
],
webhooks: [
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'Trigger On',
name: 'updates',
type: 'multiOptions',
options: [
{
name: 'New SMS',
value: 'com.twilio.messaging.inbound-message.received',
description: 'When an SMS message is received',
},
{
name: 'New Call',
value: 'com.twilio.voice.insights.call-summary.complete',
description: 'When a call is received',
},
],
required: true,
default: [],
},
{
displayName: "The 'New Call' event may take up to thirty minutes to be triggered",
name: 'callTriggerNotice',
type: 'notice',
default: '',
displayOptions: {
show: {
updates: ['com.twilio.voice.insights.call-summary.complete'],
},
},
},
],
};
webhookMethods = {
default: {
async checkExists(this: IHookFunctions): Promise<boolean> {
const webhookUrl = this.getNodeWebhookUrl('default');
const { sinks } = (await twilioTriggerApiRequest.call(this, 'GET', 'Sinks')) || {};
const sink = sinks.find(
(entry: { sink_configuration: { destination: string | undefined } }) =>
entry.sink_configuration.destination === webhookUrl,
);
if (sink) {
const { subscriptions } =
(await twilioTriggerApiRequest.call(this, 'GET', 'Subscriptions')) || {};
const subscription = subscriptions.find(
(entry: { sink_sid: any }) => entry.sink_sid === sink.sid,
);
if (subscription) {
const { types } =
(await twilioTriggerApiRequest.call(
this,
'GET',
`Subscriptions/${subscription.sid}/SubscribedEvents`,
)) || {};
const typesFound = types.map((type: { type: any }) => type.type);
const allowedUpdates = this.getNodeParameter('updates') as string[];
if (typesFound.sort().join(',') === allowedUpdates.sort().join(',')) {
return true;
} else {
return false;
}
}
}
return false;
},
async create(this: IHookFunctions): Promise<boolean> {
const workflowData = this.getWorkflowStaticData('node');
const webhookUrl = this.getNodeWebhookUrl('default');
const allowedUpdates = this.getNodeParameter('updates') as string[];
const bodySink = {
Description: 'Sink created by n8n Twilio Trigger Node.',
SinkConfiguration: `{ "destination": "${webhookUrl}", "method": "POST" }`,
SinkType: 'webhook',
};
const sink = await twilioTriggerApiRequest.call(this, 'POST', 'Sinks', bodySink);
workflowData.sinkId = sink.sid;
const body = {
Description: 'Subscription created by n8n Twilio Trigger Node.',
Types: `{ "type": "${allowedUpdates[0]}" }`,
SinkSid: sink.sid,
};
const subscription = await twilioTriggerApiRequest.call(
this,
'POST',
'Subscriptions',
body,
);
workflowData.subscriptionId = subscription.sid;
// if there is more than one event type add the others on the existing subscription
if (allowedUpdates.length > 1) {
for (let index = 1; index < allowedUpdates.length; index++) {
await twilioTriggerApiRequest.call(
this,
'POST',
`Subscriptions/${workflowData.subscriptionId}/SubscribedEvents`,
{
Type: allowedUpdates[index],
},
);
}
}
return true;
},
async delete(this: IHookFunctions): Promise<boolean> {
const workflowData = this.getWorkflowStaticData('node');
const sinkId = workflowData.sinkId;
const subscriptionId = workflowData.subscriptionId;
try {
if (sinkId) {
await twilioTriggerApiRequest.call(this, 'DELETE', `Sinks/${sinkId}`, {});
workflowData.sinkId = '';
}
if (subscriptionId) {
await twilioTriggerApiRequest.call(
this,
'DELETE',
`Subscriptions/${subscriptionId}`,
{},
);
workflowData.subscriptionId = '';
}
} catch (error) {
return false;
}
return true;
},
},
};
async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
const bodyData = this.getBodyData();
return {
workflowData: [this.helpers.returnJsonArray(bodyData)],
};
}
}