UNPKG

n8n-nodes-walichat

Version:

n8n plugin for WaliChat

1,336 lines (1,335 loc) 65.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.executeMessageOperations = exports.messageProperties = void 0; const request_1 = require("../request"); exports.messageProperties = [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['send-messages'], }, }, options: [ { name: 'Send text message', value: 'sendText', description: 'Send a simple text message', action: 'Send a text message', }, { name: 'Send multimedia message', value: 'sendMedia', description: 'Send a message with media attachment', action: 'Send a multimedia message', }, { name: 'Send scheduled message', value: 'sendScheduled', description: 'Schedule a message to be sent later', action: 'Send a scheduled message', }, { name: 'Send poll message', value: 'sendPoll', description: 'Send a poll message with multiple options', action: 'Send a poll message', }, { name: 'Send votes in a poll', value: 'sendPollVote', description: 'Vote in an existing poll message', action: 'Send votes in a poll', }, { name: 'Delete votes in a poll', value: 'deletePollVote', description: 'Remove all votes from an existing poll', action: 'Delete votes in a poll', }, { name: 'Send meeting event', value: 'sendEvent', description: 'Send an event invitation message', action: 'Send a meeting event', }, { name: 'Send meeting confirmation', value: 'confirmEvent', description: 'Respond to an event invitation (accept or decline)', action: 'Send a meeting confirmation', }, { name: 'Send location', value: 'sendLocation', description: 'Send a location message', action: 'Send a location message', }, { name: 'Send contacts', value: 'sendContacts', description: 'Send one or more contact cards', action: 'Send contact cards', }, { name: 'Send reaction', value: 'sendReaction', description: 'React to an existing message with an emoji', action: 'Send a reaction', }, { name: 'Send catalog product', value: 'sendProduct', description: 'Send a product from a WhatsApp Business catalog', action: 'Send a catalog product', }, { name: 'Forward message', value: 'forwardMessage', description: 'Forward an existing message to a chat', action: 'Forward a message', } ], default: 'sendText', }, // Common fields for all operations { displayName: 'WhatsApp number', name: 'device', type: 'options', default: '', placeholder: 'Select the WaliChat Number ID...', description: 'The target WaliChat Number ID to be used for message delivery.', required: true, typeOptions: { loadOptionsMethod: 'getDevices', }, displayOptions: { show: { resource: ['send-messages'], operation: ['sendText', 'sendMedia', 'sendScheduled', 'sendPoll', 'sendPollVote', 'deletePollVote', 'sendEvent', 'confirmEvent', 'sendLocation', 'sendContacts', 'sendReaction', 'sendProduct', 'forwardMessage'], }, }, }, { displayName: 'Target', name: 'target', description: 'Select type of target chat', type: 'options', default: 'phone', options: [ { name: 'Phone', value: 'phone', }, { name: 'Group', value: 'group', }, { name: 'Channel', value: 'channel', }, ], displayOptions: { show: { resource: ['send-messages'], operation: ['sendText', 'sendMedia', 'sendScheduled', 'sendPoll', 'sendPollVote', 'deletePollVote', 'sendEvent', 'confirmEvent', 'sendLocation', 'sendContacts', 'sendReaction', 'sendProduct', 'forwardMessage'], }, }, }, { displayName: 'Phone Number', name: 'phone', type: 'string', default: '', required: true, description: 'Target phone number in international format (e.g: +1234567890)', placeholder: '+1234567890', typeOptions: { validationRule: 'regex', regex: /^\+[1-9]\d{1,14}$/, errorMessage: 'Please enter a valid phone number in E.164 format (e.g., +1234567890)', }, displayOptions: { show: { resource: ['send-messages'], target: ['phone'], operation: ['sendText', 'sendMedia', 'sendScheduled', 'sendPoll', 'sendPollVote', 'deletePollVote', 'sendEvent', 'confirmEvent', 'sendLocation', 'sendContacts', 'sendReaction', 'sendProduct', 'forwardMessage'], }, }, }, { displayName: 'Group ID', name: 'groupId', type: 'options', default: '', placeholder: 'Enter the group ID...', description: 'The ID of the target group chat, e.g: 12345678902401234@g.us', required: true, displayOptions: { show: { resource: ['send-messages'], target: ['group'], }, }, typeOptions: { maxLength: 50, loadOptionsMethod: 'getGroups', loadOptionsDependsOn: ['device'], loadOptionsParameters: { target: 'group', }, }, }, { displayName: 'Channel ID', name: 'channel', type: 'options', default: '', placeholder: 'Enter the channel ID...', description: 'The channel ID to send the message to, e.g: 12345678902402200@newsletter', required: true, displayOptions: { show: { resource: ['send-messages'], target: ['channel'], }, }, typeOptions: { maxLength: 50, loadOptionsMethod: 'getChannels', }, }, { displayName: 'Message', name: 'message', type: 'string', typeOptions: { rows: 4, maxLength: 6000, }, default: '', description: 'Message text to be sent', displayOptions: { show: { resource: ['send-messages'], operation: ['sendText', 'sendMedia', 'sendScheduled'], }, }, }, // Fields specific to Media operation { displayName: 'File URL', name: 'mediaUrl', type: 'string', default: '', required: true, typeOptions: { validationRule: 'url', maxLength: 1000, minLength: 5, }, description: 'URL of the media to be sent (image, document, video, audio)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendMedia'], }, }, }, // Fields specific to Scheduled operation { displayName: 'Delivery date', name: 'deliverAt', type: 'dateTime', default: '', required: true, description: 'Date and time when the message should be delivered', displayOptions: { show: { resource: ['send-messages'], operation: ['sendScheduled'], }, }, }, // Fields specific to Poll operation { displayName: 'Poll Question', name: 'pollQuestion', type: 'string', default: '', required: true, typeOptions: { maxLength: 250, }, description: 'The question or title for the poll', displayOptions: { show: { resource: ['send-messages'], operation: ['sendPoll'], }, }, }, { displayName: 'Poll Options', name: 'pollOptions', type: 'fixedCollection', typeOptions: { multipleValues: true, sortable: true, minValue: 2, maxValue: 10, }, default: { options: [{ option: '' }, { option: '' }] }, description: 'The options for the poll (minimum 2, maximum 10)', placeholder: 'Add Option', options: [ { name: 'options', displayName: 'Options', values: [ { displayName: 'Option', name: 'option', type: 'string', default: '', description: 'Poll option text', required: true, typeOptions: { maxLength: 100, } }, ], }, ], displayOptions: { show: { resource: ['send-messages'], operation: ['sendPoll'], } } }, // Fields specific to Poll Vote operation { displayName: 'Poll Message ID', name: 'pollMessageId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, errorMessage: 'Enter a valid poll message ID (18, 20, 24 or 32 hexadecimal characters)', }, description: 'The ID of the poll message to vote on', displayOptions: { show: { resource: ['send-messages'], operation: ['sendPollVote'], }, }, }, { displayName: 'Vote Options', name: 'voteOptions', type: 'fixedCollection', typeOptions: { multipleValues: true, sortable: true, maxValue: 12, }, default: {}, description: 'The options to vote for (leave empty to remove all votes)', placeholder: 'Add Vote Option', options: [ { name: 'options', displayName: 'Options', values: [ { displayName: 'Option Type', name: 'optionType', type: 'options', options: [ { name: 'By Option ID', value: 'id', }, { name: 'By Option Text', value: 'value', }, ], default: 'value', description: 'How to identify the option to vote for', }, { displayName: 'Option ID', name: 'id', type: 'number', default: 0, typeOptions: { minValue: 0, maxValue: 11, }, description: 'The ID of the poll option (0-11)', displayOptions: { show: { optionType: ['id'], }, }, }, { displayName: 'Option Text', name: 'value', type: 'string', default: '', typeOptions: { maxLength: 100, }, description: 'The exact text of the poll option to vote for', displayOptions: { show: { optionType: ['value'], }, }, }, ], }, ], displayOptions: { show: { resource: ['send-messages'], operation: ['sendPollVote'], } } }, // Fields specific to Poll Vote Deletion { displayName: 'Poll Message ID', name: 'pollMessageId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, errorMessage: 'Enter a valid poll message ID (18, 20, 24 or 32 hexadecimal characters)', }, description: 'The ID of the poll message to remove votes from', displayOptions: { show: { resource: ['send-messages'], operation: ['deletePollVote'], }, }, }, // Fields specific to Event operation { displayName: 'Event Name', name: 'eventName', type: 'string', default: '', required: true, typeOptions: { maxLength: 100, }, description: 'Name or title of the event (up to 100 characters)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, }, { displayName: 'Event Description', name: 'eventDescription', type: 'string', default: '', required: false, typeOptions: { rows: 3, maxLength: 2048, }, description: 'Optional description of the event (up to 2048 characters)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, }, { displayName: 'Event Date and Time', name: 'eventDate', type: 'dateTime', default: '', required: true, description: 'Date and time of the event in ISO 8601 format', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, }, { displayName: 'Event Location', name: 'eventLocation', type: 'string', default: '', required: false, typeOptions: { maxLength: 255, }, description: 'Optional location name for the event (up to 255 characters)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, }, { displayName: 'Location Coordinates', name: 'eventCoordinates', type: 'fixedCollection', typeOptions: { multipleValues: false, }, default: {}, description: 'Optional geographical coordinates for the event location', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, options: [ { name: 'coordinates', displayName: 'Coordinates', values: [ { displayName: 'Latitude', name: 'latitude', type: 'number', default: 0, typeOptions: { minValue: -90, maxValue: 90, }, description: 'Latitude of the event location (between -90 and 90)', }, { displayName: 'Longitude', name: 'longitude', type: 'number', default: 0, typeOptions: { minValue: -180, maxValue: 180, }, description: 'Longitude of the event location (between -180 and 180)', }, ], }, ], }, { displayName: 'Meeting Call Type', name: 'eventCallType', type: 'options', default: 'none', options: [ { name: 'No Call', value: 'none', }, { name: 'Voice Call', value: 'voice', }, { name: 'Video Call', value: 'video', }, ], description: 'Type of WhatsApp call for the event meeting', displayOptions: { show: { resource: ['send-messages'], operation: ['sendEvent'], }, }, }, // Fields specific to Event Confirmation { displayName: 'Event Message ID', name: 'eventMessageId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, errorMessage: 'Enter a valid event message ID (18, 20, 24 or 32 hexadecimal characters)', }, description: 'The ID of the event message to respond to', displayOptions: { show: { resource: ['send-messages'], operation: ['confirmEvent'], }, }, }, { displayName: 'Response', name: 'eventResponse', type: 'options', default: 'accept', options: [ { name: 'Accept Invitation', value: 'accept', }, { name: 'Decline Invitation', value: 'decline', }, ], description: 'Respond to the event invitation', displayOptions: { show: { resource: ['send-messages'], operation: ['confirmEvent'], }, }, }, // Fields specific to Location operation { displayName: 'Location Type', name: 'locationType', type: 'options', options: [ { name: 'Address', value: 'address', description: 'Specify location by address', }, { name: 'Coordinates', value: 'coordinates', description: 'Specify location by coordinates', }, ], default: 'address', description: 'How to specify the location', displayOptions: { show: { resource: ['send-messages'], operation: ['sendLocation'], }, }, }, { displayName: 'Address', name: 'locationAddress', type: 'string', default: '', required: true, typeOptions: { minLength: 3, maxLength: 100, }, placeholder: 'e.g., 1600 Amphitheatre Parkway, Mountain View, CA', description: 'The address of the location to send (3-100 characters)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendLocation'], locationType: ['address'], }, }, }, { displayName: 'Latitude', name: 'locationLatitude', type: 'number', default: 0, required: true, typeOptions: { minValue: -90, maxValue: 90, numberPrecision: 8, }, description: 'Latitude of the location (-90 to 90)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendLocation'], locationType: ['coordinates'], }, }, }, { displayName: 'Longitude', name: 'locationLongitude', type: 'number', default: 0, required: true, typeOptions: { minValue: -180, maxValue: 180, numberPrecision: 8, }, description: 'Longitude of the location (-180 to 180)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendLocation'], locationType: ['coordinates'], }, }, }, { displayName: 'Location Name', name: 'locationName', type: 'string', default: '', required: false, typeOptions: { maxLength: 100, }, description: 'Optional name or description for the location (up to 100 characters)', displayOptions: { show: { resource: ['send-messages'], operation: ['sendLocation'], }, }, }, // Fields specific to Contacts operation { displayName: 'Contacts', name: 'contactsList', type: 'fixedCollection', typeOptions: { multipleValues: true, sortable: true, minValue: 1, maxValue: 10, }, default: { contacts: [{ phone: '', name: '' }] }, description: 'The contacts to send (minimum 1, maximum 10)', placeholder: 'Add Contact', options: [ { name: 'contacts', displayName: 'Contacts', values: [ { displayName: 'Phone Number', name: 'phone', type: 'string', default: '', required: true, description: 'Phone number in E.164 format (e.g., +1234567890)', placeholder: '+1234567890', typeOptions: { validationRule: 'regex', regex: /^\+[1-9]\d{1,14}$/, errorMessage: 'Please enter a valid phone number in E.164 format', minLength: 6, maxLength: 16, } }, { displayName: 'Name', name: 'name', type: 'string', default: '', required: true, description: 'Contact name or full name', placeholder: 'e.g., John Smith', typeOptions: { minLength: 1, maxLength: 40, } }, ], }, ], displayOptions: { show: { resource: ['send-messages'], operation: ['sendContacts'], } } }, // Fields specific to Reaction operation { displayName: 'Message ID to React to', name: 'reactionMessageId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, errorMessage: 'Enter a valid message ID (18, 20, 24 or 32 hexadecimal characters)', }, description: 'The ID of the message to react to', displayOptions: { show: { resource: ['send-messages'], operation: ['sendReaction'], }, }, }, { displayName: 'Emoji Reaction', name: 'reactionEmoji', type: 'string', default: '', required: true, placeholder: 'e.g., 👍 or - (to remove reaction)', description: 'Emoji to send as reaction, or "-" to remove a reaction. See getemojis.com for available emojis.', typeOptions: { maxLength: 10, }, displayOptions: { show: { resource: ['send-messages'], operation: ['sendReaction'], }, }, }, // Fields specific to Catalog Product operation { displayName: 'Product ID', name: 'productId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[0-9]{14,18}$/, minLength: 16, maxLength: 18, errorMessage: 'Enter a valid product ID (16-18 numeric characters)', }, description: 'The ID of the product from a WhatsApp Business catalog', displayOptions: { show: { resource: ['send-messages'], operation: ['sendProduct'], }, }, }, // Fields specific to Forward operation { displayName: 'Message ID to Forward', name: 'forwardMessageId', type: 'string', default: '', required: true, typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, errorMessage: 'Enter a valid message ID (18, 20, 24 or 32 hexadecimal characters)', }, description: 'The ID of the message to forward', displayOptions: { show: { resource: ['send-messages'], operation: ['forwardMessage'], }, }, }, { displayName: 'Source Chat ID', name: 'forwardChatId', type: 'string', default: '', required: false, typeOptions: { minLength: 8, maxLength: 32, }, placeholder: 'e.g., +1234567890 or 123456789012345@g.us', description: 'Source chat ID where the message to forward belongs to (optional, the system will try to discover it if not provided)', displayOptions: { show: { resource: ['send-messages'], operation: ['forwardMessage'], }, }, }, // Advanced options for all operations { displayName: 'Options', name: 'options', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['send-messages'], operation: [ 'sendText', 'sendMedia', 'sendScheduled', 'sendPoll', 'sendPollVote', 'deletePollVote', 'sendEvent', 'confirmEvent', 'sendLocation', 'sendContacts', 'sendReaction', 'sendProduct', 'forwardMessage' ], }, }, options: [ { displayName: 'Priority', name: 'priority', type: 'options', options: [ { name: 'Normal', value: 'normal' }, { name: 'High', value: 'high' }, { name: 'Low', value: 'low' }, ], default: 'normal', description: 'Message delivery priority', }, { displayName: 'Label', name: 'label', type: 'string', typeOptions: { loadOptionsMethod: 'getLabels', loadOptionsDependsOn: ['device'], }, default: '', description: 'Custom label to categorize the message', }, { displayName: 'Reference ID', name: 'reference', type: 'string', default: '', description: 'Custom reference ID for the message', }, { displayName: 'Team Agent', name: 'agent', description: 'Optionally send the message in behalf of an agent', type: 'options', default: '', typeOptions: { validationRule: 'regex', regex: /^[a-f0-9]{24}$/, errorMessage: 'Please enter a valid team agent ID (24 characters hexadecimal)', maxLength: 24, minLength: 24, loadOptionsMethod: 'getTeamAgents', loadOptionsDependsOn: ['device'], }, }, // Advanced delivery options { displayName: 'Send in real-time (riskier, no queue)', name: 'live', type: 'boolean', default: false, description: 'Send message in real-time mode without enqueuing it (live mode). Important: do not use this option if you plan to send dozens of messages per minute at a constant rate since this can increase risk of ban by WhatsApp.', }, { displayName: 'Delivery Queue Mode', name: 'enqueue', type: 'options', options: [ { name: 'Default (Based on plan)', value: '' }, { name: 'Always Queue', value: 'always' }, { name: 'Never Queue (Real-time delivery)', value: 'never' }, { name: 'Opportunistic (Try real-time, fallback to queue)', value: 'opportunistic' }, ], default: '', description: 'Defines how the message should be queued and delivered. Not all modes are available in all plans. Imporaant: do not use the "never" option if you plan to send dozens of messages per minute at a constant rate since this can increase risk of ban by WhatsApp.', }, { displayName: 'Maximum Retries', name: 'retries', type: 'number', default: 25, typeOptions: { minValue: 0, maxValue: 100, }, description: 'Maximum message delivery retries', }, { displayName: 'Chat Actions (Assign, Resolve, Metadata...)', name: 'actions', type: 'fixedCollection', typeOptions: { multipleValues: true, }, default: {}, description: 'Optional actions to perform after the message is delivered', options: [ { name: 'actions', displayName: 'Actions', values: [ { displayName: 'Action Type', name: 'action', type: 'options', options: [ { name: 'Assign Chat to an Agent', value: 'chat:assign' }, { name: 'Assign Chat to a Department', value: 'chat:assign:department' }, { name: 'Unassign Chat', value: 'chat:unassign' }, { name: 'Resolve Chat', value: 'chat:resolve' }, { name: 'Unresolve Chat', value: 'chat:unresolve' }, { name: 'Mark Chat as Read', value: 'chat:read' }, { name: 'Mark Chat as Unread', value: 'chat:unread' }, { name: 'Add Labels', value: 'labels:add' }, { name: 'Remove Labels', value: 'labels:remove' }, { name: 'Set Labels', value: 'labels:set' }, { name: 'Set Metadata', value: 'metadata:set' }, { name: 'Add Metadata', value: 'metadata:add' }, { name: 'Remove Metadata', value: 'metadata:remove' }, ], default: 'chat:assign', description: 'The type of action to perform after message delivery', }, // Fields for chat:assign { displayName: 'Agent ID', name: 'agent', description: 'User agent ID to assign the chat to after message delivery. Required if Department ID is not provided.', type: 'options', default: '', typeOptions: { validationRule: 'regex', regex: /^[a-f0-9]{24}$/, errorMessage: 'Please enter a valid team agent ID (24 characters hexadecimal)', maxLength: 24, minLength: 24, loadOptionsMethod: 'getTeamAgents', loadOptionsDependsOn: ['device'], }, displayOptions: { show: { action: ['chat:assign'], }, }, }, { displayName: 'Department ID', name: 'department', type: 'options', default: '', description: 'Department ID to assign the chat to. Required if Agent ID is not provided.', typeOptions: { validationRule: 'regex', regex: /^[a-f0-9]{24}$/, errorMessage: 'Please enter a valid Department ID (24 characters hexadecimal)', maxLength: 24, minLength: 24, loadOptionsMethod: 'getDepartments', loadOptionsDependsOn: ['device'], }, displayOptions: { show: { action: ['chat:assign:department'], }, }, }, // Fields for labels actions { displayName: 'Labels', name: 'labels', type: 'options', typeOptions: { multipleValues: true, minValue: 1, maxValue: 50, loadOptionsMethod: 'getLabels', loadOptionsDependsOn: ['device'], }, default: '', placeholder: 'Select labels', description: 'Label tags to add, remove or set in the chat.', displayOptions: { show: { action: ['labels:add', 'labels:remove', 'labels:set'], }, }, }, // Fields for metadata actions { displayName: 'Metadata Entries', name: 'metadata', type: 'fixedCollection', typeOptions: { multipleValues: true, minValue: 1, maxValue: 10, }, default: { metadataValues: [{ key: '', value: '' }] }, description: 'Metadata key-value pairs to set or add.', displayOptions: { show: { action: ['metadata:set', 'metadata:add'], }, }, options: [ { name: 'metadataValues', displayName: 'Metadata', values: [ { displayName: 'Key', name: 'key', type: 'string', default: '', description: 'Metadata entry key that can only contain alphanumeric (a-z, A-Z, 0-9), or underscore (_) characters.', typeOptions: { minLength: 1, maxLength: 30, }, required: true, }, { displayName: 'Value', name: 'value', type: 'string', default: '', description: 'Metadata entry value can contain any text up to 300 characters.', typeOptions: { maxLength: 300, }, required: true, }, ], }, ], }, // Fields for metadata:remove { displayName: 'Delete metadata', name: 'keys', type: 'string', typeOptions: { multipleValues: true, multipleValueButtonText: 'Add Key', minValue: 1, maxValue: 30, }, default: '', placeholder: 'e.g., customer_id, status', description: 'Metadata entries to remove by keys.', displayOptions: { show: { action: ['metadata:remove'], }, }, }, ], }, ], }, { displayName: 'Message Expiration', name: 'expiration', type: 'fixedCollection', typeOptions: { multipleValues: false, }, default: {}, description: 'Define a message time-to-live (TTL) expiration time', options: [ { name: 'values', displayName: 'Expiration Values', values: [ { displayName: 'Expiration Type', name: 'type', type: 'options', options: [ { name: 'Seconds', value: 'seconds' }, { name: 'Duration', value: 'duration' }, { name: 'Date', value: 'date' }, ], default: 'seconds', description: 'How to specify the expiration time', }, { displayName: 'Seconds', name: 'seconds', type: 'number', default: 300, typeOptions: { minValue: 5, maxValue: 2592000, // 30 days in seconds }, description: 'Expire after this many seconds', displayOptions: { show: { type: ['seconds'], }, }, }, { displayName: 'Duration', name: 'duration', type: 'string', default: '1h', placeholder: 'e.g., 1h, 30m, 1d', description: 'Expire after this duration (e.g., 1h, 15m, 12h, 1d)', displayOptions: { show: { type: ['duration'], }, }, }, { displayName: 'Date', name: 'date', type: 'dateTime', default: '', description: 'Expire at this specific date and time', displayOptions: { show: { type: ['date'], }, }, }, ], }, ], }, { displayName: 'Mark Chat as Read', name: 'sendReadAck', type: 'boolean', default: false, description: 'Notifies WhatsAPp that the previous unread chat messages will be read after message delivery (blue double-check). Will not work if read confirmation is disabled in WhatsApp Privacy settings.', }, { displayName: 'Typing simulation', name: 'typing', type: 'number', default: 0, typeOptions: { minValue: 0, maxValue: 30, }, description: 'Seconds to simulate typing or recording status before delivery (2-30 seconds, 0 to disable)', }, { displayName: 'Quote Message', name: 'quote', type: 'string', default: '', typeOptions: { validationRule: 'regex', regex: /^[a-fA-F0-9]{18,32}$/, minLength: 18, maxLength: 32, }, description: 'Message ID to quote when sending the message (18-32 hex characters). Can only quote messages in the same conversation.', }, { displayName: 'Strict Message Order', name: 'order', type: 'boolean', default: false, description: 'Ensure messages are sent to the target chat in strict order. Useful for chatbots and message sequences. Not compatible with Live Mode or Never Queue delivery options.', }, ], }, ]; async function executeMessageOperations(itemIndex) { const operation = this.getNodeParameter('operation', itemIndex); const requestBody = {}; // Common parameters if (operation === 'sendText' || operation === 'sendMedia' || operation === 'sendScheduled' || operation === 'sendPoll' || operation === 'sendPollVote' || operation === 'deletePollVote' || operation === 'sendEvent' || operation === 'confirmEvent' || operation === 'sendLocation' || operation === 'sendContacts' || operation === 'sendReaction' || operation === 'sendProduct' || operation === 'forwardMessage') { const device = this.getNodeParameter('device', itemIndex); const target = this.getNodeParameter('target', itemIndex); const options = this.getNodeParameter('options', itemIndex, {}); requestBody.device = device; if (!device) { throw new Error('WhatsApp Device ID is required'); } // Handle target-specific parameters if (target === 'phone') { const phone = this.getNodeParameter('phone', itemIndex); requestBody.phone = phone; } else if (target === 'group') { const group = this.getNodeParameter('groupId', itemIndex); requestBody.group = group; } else if (target === 'channel') { const channel = this.getNodeParameter('channel', itemIndex); requestBody.channel = channel; } // Handle operation-specific parameters if (operation === 'sendText' || operation === 'sendMedia' || operation === 'sendScheduled') { const message = this.getNodeParameter('message', itemIndex); if (message) { requestBody.message = message; } } // Process options if (options) { // Process chat actions if present if (options.actions && typeof options.actions === 'object' && options.actions.actions) { const actionsCollection = options.actions.actions; if (actionsCollection && actionsCollection.length > 0) { const actions = []; for (const actionItem of actionsCollection) { const action = actionItem.action; if (!action) continue; const actionObject = { action }; // Handle different action types and their parameters switch (action) { case 'chat:assign': case 'chat:assign:department': actionObject.action = 'chat:assign'; // Add agent and/or department parameters if (actionItem.agent || actionItem.department) { const params = {}; if (actionItem.agent) { params.agent = actionItem.agent; } else if (actionItem.department) { params.department = actionItem.department;