n8n-nodes-nimbasms
Version:
Nimba SMS node for n8n - Send SMS, manage contacts, campaigns and more
431 lines (430 loc) • 21.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NimbaSMS = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const GenericFunctions_1 = require("./GenericFunctions");
// Assurez-vous que tous ces imports existent et sont corrects
const ContactDescription_1 = require("./descriptions/ContactDescription");
const GroupDescription_1 = require("./descriptions/GroupDescription");
const SmsDescription_1 = require("./descriptions/SmsDescription");
const AccountDescription_1 = require("./descriptions/AccountDescription");
class NimbaSMS {
constructor() {
this.description = {
displayName: 'Nimba SMS',
name: 'nimbaSMS',
icon: 'file:icons/nimbasms.svg',
group: ['communication'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Send SMS, manage campaigns, and track delivery reports using the Nimba SMS API with ease.',
defaults: {
name: 'Nimba SMS',
},
inputs: ["main" /* NodeConnectionType.Main */],
outputs: ["main" /* NodeConnectionType.Main */],
credentials: [
{
name: 'nimbaSmsApi',
required: true,
},
],
properties: [
// Resource selector
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Message',
value: 'message',
description: 'Send and manage SMS',
},
{
name: 'Contact',
value: 'contact',
description: 'Manage contacts',
},
{
name: 'Group',
value: 'group',
description: 'Manage contact groups',
},
{
name: 'Account',
value: 'account',
description: 'Account information and billing',
},
{
name: 'Sender Name',
value: 'senderName',
description: 'Manage sender names',
},
],
default: 'message',
},
// Message Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['message'],
},
},
options: [
{
name: 'Send SMS',
value: 'send',
description: 'Send an SMS message',
action: 'Send an SMS message',
},
{
name: 'Get All Messages',
value: 'getAll',
description: 'Get all SMS messages',
action: 'Get all SMS messages',
},
{
name: 'Get Message',
value: 'get',
description: 'Get a specific SMS message',
action: 'Get a SMS message',
},
],
default: 'send',
},
// Send SMS Fields
{
displayName: 'Sender Name',
name: 'senderName',
type: 'options',
typeOptions: {
loadOptionsMethod: 'getSenderNames',
},
displayOptions: {
show: {
resource: ['message'],
operation: ['send'],
},
},
default: '',
required: true,
description: 'The sender name to use for the SMS',
},
{
displayName: 'Message',
name: 'message',
type: 'string',
typeOptions: {
rows: 4,
},
displayOptions: {
show: {
resource: ['message'],
operation: ['send'],
},
},
default: '',
required: true,
description: 'The message content (max 665 characters)',
},
{
displayName: 'Phone Numbers',
name: 'contact',
type: 'fixedCollection',
typeOptions: {
multipleValues: true,
multipleValueButtonText: 'Add Phone Number',
},
displayOptions: {
show: {
resource: ['message'],
operation: ['send'],
},
},
default: {
contact: [
{
phoneNumber: '',
},
],
},
required: true,
description: 'The recipient phone numbers (up to 50 numbers, including country code)',
placeholder: 'Add phone number',
options: [
{
displayName: 'Phone Number',
name: 'phoneNumber',
type: 'string',
default: '',
description: 'Phone number with country code',
placeholder: '+224623000000',
},
],
},
// Spread other operations and fields
...ContactDescription_1.contactOperations,
...ContactDescription_1.contactFields,
...GroupDescription_1.groupOperations,
...GroupDescription_1.groupFields,
...SmsDescription_1.smsOperations,
...SmsDescription_1.smsFields,
...AccountDescription_1.accountOperations,
...AccountDescription_1.accountFields,
],
};
this.methods = {
loadOptions: {
async getSenderNames() {
const returnData = [];
try {
const response = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'sendernames');
if (response.results && Array.isArray(response.results)) {
for (const senderName of response.results) {
if (senderName.status === 'accepted') {
returnData.push({
name: senderName.name,
value: senderName.name,
});
}
}
}
}
catch (error) {
console.error('Error loading sender names:', error);
return [];
}
return returnData;
},
},
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const length = items.length;
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
for (let i = 0; i < length; i++) {
try {
if (resource === 'message') {
// SMS Operations
if (operation === 'send') {
const senderName = this.getNodeParameter('senderName', i);
const contactsData = this.getNodeParameter('contact', i);
const message = this.getNodeParameter('message', i);
// Extract phone numbers from the fixedCollection
const contactList = [];
if (contactsData.contact && Array.isArray(contactsData.contact)) {
for (const contact of contactsData.contact) {
if (contact.phoneNumber && typeof contact.phoneNumber === 'string') {
contactList.push(contact.phoneNumber.trim());
}
}
}
if (contactList.length === 0) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No valid contacts provided. Please provide at least one phone number.`, { itemIndex: i });
}
if (contactList.length > 50) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Too many contacts. Maximum 50 contacts allowed.`, { itemIndex: i });
}
// Validate each phone number and format them
const formattedContacts = contactList.map(contact => {
if (!(0, GenericFunctions_1.validatePhoneNumber)(contact)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid phone number "${contact}". Please provide a valid phone number.`, { itemIndex: i });
}
return (0, GenericFunctions_1.formatPhoneNumber)(contact);
});
if (!(0, GenericFunctions_1.validateMessage)(message)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Message too long. Maximum 665 characters allowed.`, { itemIndex: i });
}
const body = {
sender_name: senderName,
to: formattedContacts,
message,
};
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'POST', 'messages', body);
returnData.push(responseData);
}
else if (operation === 'verification') {
const senderName = this.getNodeParameter('senderName', i);
const to = this.getNodeParameter('to', i);
const message = this.getNodeParameter('message', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
// Validate phone number
if (!(0, GenericFunctions_1.validatePhoneNumber)(to)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid phone number "${to}". Please provide a valid phone number.`, { itemIndex: i });
}
// Validate message contains <1234> placeholder
if (!message.includes('<1234>')) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Message must contain <1234> placeholder for OTP code.`, { itemIndex: i });
}
// Validate message length
if (message.length > 153) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Message too long. Maximum 153 characters allowed for OTP verification.`, { itemIndex: i });
}
const body = {
to: (0, GenericFunctions_1.formatPhoneNumber)(to),
message,
sender_name: senderName,
};
// Add optional fields
if (additionalFields.expiry_time) {
body.expiry_time = additionalFields.expiry_time;
}
if (additionalFields.attempts) {
body.attempts = additionalFields.attempts;
}
if (additionalFields.code_length) {
body.code_length = additionalFields.code_length;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'POST', 'verifications', body);
returnData.push(responseData);
}
else if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
const qs = {};
if (additionalFields.search) {
qs.search = additionalFields.search;
}
if (additionalFields.status) {
qs.status = additionalFields.status;
}
if (returnAll) {
const responseData = await GenericFunctions_1.nimbaSmsApiRequestAllItems.call(this, 'results', 'GET', 'messages', {}, qs);
returnData.push.apply(returnData, responseData);
}
else {
const limit = this.getNodeParameter('limit', i);
qs.limit = limit;
if (additionalFields.offset) {
qs.offset = additionalFields.offset;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'messages', {}, qs);
returnData.push.apply(returnData, responseData.results || []);
}
}
else if (operation === 'get') {
const smsId = this.getNodeParameter('smsId', i);
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', `/messages/${smsId}`);
returnData.push(responseData);
}
}
else if (resource === 'contact') {
// Contact Operations
if (operation === 'create') {
const numero = this.getNodeParameter('numero', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
if (!(0, GenericFunctions_1.validatePhoneNumber)(numero)) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid phone number "${numero}". Please provide a valid phone number.`, { itemIndex: i });
}
const body = {
numero: (0, GenericFunctions_1.formatPhoneNumber)(numero),
};
if (additionalFields.name) {
body.name = additionalFields.name;
}
if (additionalFields.groups) {
const groups = additionalFields.groups.split(',').map(group => group.trim());
body.groups = groups;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'POST', 'contacts', body);
returnData.push(responseData);
}
else if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i);
const filters = this.getNodeParameter('filters', i);
const qs = {};
if (filters.search) {
qs.search = filters.search;
}
if (returnAll) {
const responseData = await GenericFunctions_1.nimbaSmsApiRequestAllItems.call(this, 'results', 'GET', 'contacts', {}, qs);
returnData.push.apply(returnData, responseData);
}
else {
const limit = this.getNodeParameter('limit', i);
qs.limit = limit;
if (filters.offset) {
qs.offset = filters.offset;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'contacts', {}, qs);
returnData.push.apply(returnData, responseData.results || []);
}
}
}
else if (resource === 'group') {
// Group Operations
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i);
const filters = this.getNodeParameter('filters', i);
const qs = {};
if (filters.search) {
qs.search = filters.search;
}
if (filters.ordering) {
qs.ordering = filters.ordering;
}
if (returnAll) {
const responseData = await GenericFunctions_1.nimbaSmsApiRequestAllItems.call(this, 'results', 'GET', 'groups', {}, qs);
returnData.push.apply(returnData, responseData);
}
else {
const limit = this.getNodeParameter('limit', i);
qs.limit = limit;
if (filters.offset) {
qs.offset = filters.offset;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'groups', {}, qs);
returnData.push.apply(returnData, responseData.results || []);
}
}
}
else if (resource === 'account') {
// Account Operations
if (operation === 'getBalance') {
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'accounts');
returnData.push(responseData);
}
}
else if (resource === 'senderName') {
// Sender Name Operations
if (operation === 'getAll') {
const returnAll = this.getNodeParameter('returnAll', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
const qs = {};
if (returnAll) {
const responseData = await GenericFunctions_1.nimbaSmsApiRequestAllItems.call(this, 'results', 'GET', 'sendernames', {}, qs);
returnData.push.apply(returnData, responseData);
}
else {
const limit = this.getNodeParameter('limit', i);
qs.limit = limit;
if (additionalFields.offset) {
qs.offset = additionalFields.offset;
}
const responseData = await GenericFunctions_1.nimbaSmsApiRequest.call(this, 'GET', 'sendernames', {}, qs);
returnData.push.apply(returnData, responseData.results || []);
}
}
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({ error: error.message });
continue;
}
throw error;
}
}
return [this.helpers.returnJsonArray(returnData)];
}
}
exports.NimbaSMS = NimbaSMS;