first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const callOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['call'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Make',
|
||||
value: 'make',
|
||||
description: 'Make a voice call',
|
||||
action: 'Make a call',
|
||||
},
|
||||
],
|
||||
default: 'make',
|
||||
},
|
||||
];
|
||||
|
||||
export const callFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// call: make
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'From',
|
||||
name: 'from',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: '+14156667777',
|
||||
description: 'Caller ID for the call to make',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['call'],
|
||||
operation: ['make'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: '+14156667778',
|
||||
required: true,
|
||||
description: 'Phone number to make the call to',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['call'],
|
||||
operation: ['make'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Answer Method',
|
||||
name: 'answer_method',
|
||||
type: 'options',
|
||||
required: true,
|
||||
description: 'HTTP verb to be used when invoking the Answer URL',
|
||||
default: 'POST',
|
||||
options: [
|
||||
{
|
||||
name: 'GET',
|
||||
value: 'GET',
|
||||
},
|
||||
{
|
||||
name: 'POST',
|
||||
value: 'POST',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['call'],
|
||||
operation: ['make'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Answer URL',
|
||||
name: 'answer_url',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
'URL to be invoked by Plivo once the call is answered. It should return the XML to handle the call once answered.',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['call'],
|
||||
operation: ['make'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,47 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IHookFunctions,
|
||||
IDataObject,
|
||||
JsonObject,
|
||||
IHttpRequestMethods,
|
||||
IRequestOptions,
|
||||
} from 'n8n-workflow';
|
||||
import { NodeApiError } from 'n8n-workflow';
|
||||
|
||||
/**
|
||||
* Make an API request to Plivo.
|
||||
*
|
||||
*/
|
||||
export async function plivoApiRequest(
|
||||
this: IHookFunctions | IExecuteFunctions,
|
||||
method: IHttpRequestMethods,
|
||||
endpoint: string,
|
||||
body: IDataObject = {},
|
||||
qs: IDataObject = {},
|
||||
) {
|
||||
const credentials = await this.getCredentials<{
|
||||
authId: string;
|
||||
authToken: string;
|
||||
}>('plivoApi');
|
||||
|
||||
const options: IRequestOptions = {
|
||||
headers: {
|
||||
'user-agent': 'plivo-n8n',
|
||||
},
|
||||
method,
|
||||
form: body,
|
||||
qs,
|
||||
uri: `https://api.plivo.com/v1/Account/${credentials.authId}${endpoint}/`,
|
||||
auth: {
|
||||
user: credentials.authId,
|
||||
pass: credentials.authToken,
|
||||
},
|
||||
json: true,
|
||||
};
|
||||
|
||||
try {
|
||||
return await this.helpers.request(options);
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error as JsonObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const mmsOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['mms'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Send',
|
||||
value: 'send',
|
||||
description: 'Send an MMS message (US/Canada only)',
|
||||
action: 'Send an MMS',
|
||||
},
|
||||
],
|
||||
default: 'send',
|
||||
},
|
||||
];
|
||||
|
||||
export const mmsFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// mms: send
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'From',
|
||||
name: 'from',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Plivo Number to send the MMS from',
|
||||
placeholder: '+14156667777',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['mms'],
|
||||
operation: ['send'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Phone number to send the MMS to',
|
||||
placeholder: '+14156667778',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['send'],
|
||||
resource: ['mms'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Message',
|
||||
name: 'message',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Message to send',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['mms'],
|
||||
operation: ['send'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Media URLs',
|
||||
name: 'media_urls',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['mms'],
|
||||
operation: ['send'],
|
||||
},
|
||||
},
|
||||
description: 'Comma-separated list of media URLs of the files from your file server',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.plivo",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Communication", "Development"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/plivo/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.plivo/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
import {
|
||||
type IExecuteFunctions,
|
||||
type IDataObject,
|
||||
type INodeExecutionData,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
NodeConnectionTypes,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { callFields, callOperations } from './CallDescription';
|
||||
import { plivoApiRequest } from './GenericFunctions';
|
||||
import { mmsFields, mmsOperations } from './MmsDescription';
|
||||
import { smsFields, smsOperations } from './SmsDescription';
|
||||
|
||||
export class Plivo implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Plivo',
|
||||
name: 'plivo',
|
||||
icon: 'file:plivo.svg',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Send SMS/MMS messages or make phone calls',
|
||||
defaults: {
|
||||
name: 'Plivo',
|
||||
},
|
||||
usableAsTool: true,
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'plivoApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Call',
|
||||
value: 'call',
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-resource-with-plural-option
|
||||
name: 'MMS',
|
||||
value: 'mms',
|
||||
},
|
||||
{
|
||||
name: 'SMS',
|
||||
value: 'sms',
|
||||
},
|
||||
],
|
||||
default: 'sms',
|
||||
required: true,
|
||||
},
|
||||
...smsOperations,
|
||||
...smsFields,
|
||||
...mmsOperations,
|
||||
...mmsFields,
|
||||
...callOperations,
|
||||
...callFields,
|
||||
],
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: IDataObject[] = [];
|
||||
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let responseData;
|
||||
|
||||
if (resource === 'sms') {
|
||||
// *********************************************************************
|
||||
// sms
|
||||
// *********************************************************************
|
||||
|
||||
if (operation === 'send') {
|
||||
// ----------------------------------
|
||||
// sms: send
|
||||
// ----------------------------------
|
||||
|
||||
const body = {
|
||||
src: this.getNodeParameter('from', i) as string,
|
||||
dst: this.getNodeParameter('to', i) as string,
|
||||
text: this.getNodeParameter('message', i) as string,
|
||||
} as IDataObject;
|
||||
|
||||
responseData = await plivoApiRequest.call(this, 'POST', '/Message', body);
|
||||
}
|
||||
} else if (resource === 'call') {
|
||||
// *********************************************************************
|
||||
// call
|
||||
// *********************************************************************
|
||||
|
||||
if (operation === 'make') {
|
||||
// ----------------------------------
|
||||
// call: make
|
||||
// ----------------------------------
|
||||
|
||||
// https://www.plivo.com/docs/voice/api/call#make-a-call
|
||||
|
||||
const body = {
|
||||
from: this.getNodeParameter('from', i) as string,
|
||||
to: this.getNodeParameter('to', i) as string,
|
||||
answer_url: this.getNodeParameter('answer_url', i) as string,
|
||||
answer_method: this.getNodeParameter('answer_method', i) as string,
|
||||
} as IDataObject;
|
||||
|
||||
responseData = await plivoApiRequest.call(this, 'POST', '/Call', body);
|
||||
}
|
||||
} else if (resource === 'mms') {
|
||||
// *********************************************************************
|
||||
// mms
|
||||
// *********************************************************************
|
||||
|
||||
if (operation === 'send') {
|
||||
// ----------------------------------
|
||||
// mss: send
|
||||
// ----------------------------------
|
||||
|
||||
// https://www.plivo.com/docs/sms/api/message#send-a-message
|
||||
|
||||
const body = {
|
||||
src: this.getNodeParameter('from', i) as string,
|
||||
dst: this.getNodeParameter('to', i) as string,
|
||||
text: this.getNodeParameter('message', i) as string,
|
||||
type: 'mms',
|
||||
media_urls: this.getNodeParameter('media_urls', i) as string,
|
||||
} as IDataObject;
|
||||
|
||||
responseData = await plivoApiRequest.call(this, 'POST', '/Message', body);
|
||||
}
|
||||
}
|
||||
|
||||
Array.isArray(responseData)
|
||||
? returnData.push(...(responseData as IDataObject[]))
|
||||
: returnData.push(responseData as IDataObject);
|
||||
}
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const smsOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['sms'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Send',
|
||||
value: 'send',
|
||||
description: 'Send an SMS message',
|
||||
action: 'Send an SMS',
|
||||
},
|
||||
],
|
||||
default: 'send',
|
||||
},
|
||||
];
|
||||
|
||||
export const smsFields: INodeProperties[] = [
|
||||
// ----------------------------------
|
||||
// sms: send
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'From',
|
||||
name: 'from',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Plivo Number to send the SMS from',
|
||||
placeholder: '+14156667777',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['sms'],
|
||||
operation: ['send'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'To',
|
||||
name: 'to',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Phone number to send the message to',
|
||||
placeholder: '+14156667778',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['sms'],
|
||||
operation: ['send'],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Message',
|
||||
name: 'message',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Message to send',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: ['send'],
|
||||
resource: ['sms'],
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"api_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_uuid": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="40 30 170 170"><defs><path id="a" d="M0 .549h152V119H0z"/></defs><g fill="none" fill-rule="evenodd"><path fill="#FFF" fill-opacity=".01" d="M0 0h250v218H0z"/><g transform="translate(49 49.451)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><path fill="#43A046" d="M75.735.548C62.831.594 50.927 4.841 41.311 11.99c-9.616 7.15-16.943 17.202-20.695 28.853a4.3 4.3 0 0 1-.684 1.3 4.4 4.4 0 0 1-1.08.997 41.64 41.64 0 0 0-14.14 15.496C1.402 64.93-.328 72.182.052 79.872c.548 11.117 5.601 20.919 13.3 27.93 7.697 7.014 18.041 11.236 29.173 11.198h67.233a42.94 42.94 0 0 0 29.096-11.513c7.65-7.122 12.635-17.015 13.108-28.137.326-7.693-1.454-14.932-4.807-21.203a41.64 41.64 0 0 0-14.244-15.4 4.4 4.4 0 0 1-1.089-.988 4.3 4.3 0 0 1-.692-1.296c-3.832-11.625-11.228-21.626-20.894-28.71C100.572 4.672 88.64.506 75.736.549m.05 14.778c9.526-.032 18.572 3.124 25.92 8.568 7.347 5.444 12.998 13.175 15.734 22.293l.592 1.973.593 1.974a4.25 4.25 0 0 0 1.913 2.441l1.776 1.047 1.775 1.046c4.261 2.513 7.634 6.024 9.894 10.143s3.408 8.847 3.22 13.794c-.277 7.18-3.503 13.548-8.458 18.128a27.9 27.9 0 0 1-18.824 7.392l-33.83.116-33.83.117a27.9 27.9 0 0 1-18.874-7.263c-4.986-4.545-8.257-10.891-8.58-18.07-.225-4.945.89-9.68 3.122-13.815 2.233-4.135 5.582-7.67 9.826-10.211l1.768-1.058 1.767-1.06a4.25 4.25 0 0 0 1.898-2.454l.578-1.978.58-1.977c2.673-9.136 8.27-16.906 15.58-22.401 7.31-5.493 16.333-8.711 25.86-8.745" mask="url(#b)"/></g><path fill="#43A046" d="M113.281 100.651c0 .87-.35 1.658-.918 2.229a3.15 3.15 0 0 1-2.224.934l-3.174.012-3.175.011a3.15 3.15 0 0 1-2.229-.919 3.16 3.16 0 0 1-.934-2.223l-.01-3.175-.01-3.175a3.16 3.16 0 0 1 3.141-3.163l3.174-.01 3.174-.011c.87 0 1.658.35 2.23.918a3.15 3.15 0 0 1 .933 2.223l.011 3.175zm17.961 0c0 .87-.35 1.658-.918 2.229a3.15 3.15 0 0 1-2.223.934l-3.175.012-3.174.011c-.87 0-1.658-.351-2.23-.919a3.15 3.15 0 0 1-.933-2.223l-.012-3.175-.01-3.175a3.16 3.16 0 0 1 3.141-3.163l3.175-.01 3.174-.011c.87 0 1.658.35 2.23.918s.928 1.354.934 2.223l.01 3.175zm17.962.002c0 .869-.35 1.657-.918 2.229a3.16 3.16 0 0 1-2.225.934l-3.174.011-3.174.011a3.15 3.15 0 0 1-2.232-.916 3.15 3.15 0 0 1-.931-2.226l-.012-3.175-.01-3.175a3.13 3.13 0 0 1 .916-2.231 3.15 3.15 0 0 1 2.226-.931l3.175-.011 3.173-.011a3.15 3.15 0 0 1 2.26.867c.587.557.96 1.338.984 2.21v.064l-.03 3.175-.029 3.175zm-35.915 17.955c0 .869-.35 1.657-.918 2.229a3.16 3.16 0 0 1-2.224.934l-3.174.011-3.175.011a3.15 3.15 0 0 1-2.23-.918 3.16 3.16 0 0 1-.933-2.224l-.011-3.175-.01-3.174c-.001-.87.35-1.658.918-2.229a3.15 3.15 0 0 1 2.223-.934l3.175-.01 3.174-.012c.87 0 1.658.35 2.229.919.573.567.929 1.353.934 2.222l.01 3.175zm17.96 0c0 .869-.35 1.657-.917 2.229a3.16 3.16 0 0 1-2.223.934l-3.175.011-3.174.011a3.15 3.15 0 0 1-2.23-.918 3.15 3.15 0 0 1-.933-2.224l-.012-3.175-.01-3.174c-.001-.87.35-1.658.918-2.229a3.15 3.15 0 0 1 2.223-.934l3.175-.01 3.174-.012c.87 0 1.658.35 2.23.919a3.15 3.15 0 0 1 .934 2.222l.01 3.175zm17.962 0c0 .869-.35 1.657-.918 2.229a3.16 3.16 0 0 1-2.224.934l-3.174.011-3.175.011a3.14 3.14 0 0 1-2.232-.916 3.15 3.15 0 0 1-.93-2.226l-.012-3.175-.01-3.174a3.13 3.13 0 0 1 .915-2.232 3.15 3.15 0 0 1 2.226-.931l3.175-.01 3.174-.012c.87 0 1.658.35 2.23.919.572.567.928 1.353.933 2.222l.011 3.175zm-35.914 17.95a3.14 3.14 0 0 1-.916 2.232 3.14 3.14 0 0 1-2.226.931l-3.174.011-3.175.011a3.15 3.15 0 0 1-2.232-.915 3.15 3.15 0 0 1-.931-2.226l-.011-3.175-.01-3.175a3.15 3.15 0 0 1 .918-2.229 3.16 3.16 0 0 1 2.223-.934l3.175-.01 3.174-.01a3.14 3.14 0 0 1 2.229.917c.573.568.929 1.353.934 2.222l.01 3.175zm17.96 0a3.14 3.14 0 0 1-.915 2.232 3.14 3.14 0 0 1-2.225.931l-3.175.011-3.174.011a3.146 3.146 0 0 1-3.163-3.14l-.012-3.176-.01-3.175a3.15 3.15 0 0 1 .918-2.229 3.16 3.16 0 0 1 2.223-.934l3.175-.01 3.174-.01a3.15 3.15 0 0 1 2.23.917c.572.568.928 1.353.934 2.222l.01 3.175zm17.962 0a3.14 3.14 0 0 1-.916 2.232 3.14 3.14 0 0 1-2.226.931l-3.174.011-3.175.011a3.15 3.15 0 0 1-2.232-.915 3.15 3.15 0 0 1-.93-2.226l-.012-3.175-.01-3.175c-.004-.87.346-1.66.915-2.232a3.15 3.15 0 0 1 2.226-.93l3.175-.01 3.174-.012a3.14 3.14 0 0 1 2.23.918c.572.568.928 1.353.933 2.222l.011 3.175z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
Reference in New Issue
Block a user