UNPKG

n8n-nodes-wuzapi

Version:

n8n community nodes for Wuzapi - WhatsApp Multi-Device REST API

565 lines 23.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WuzapiChat = void 0; const GenericFunctions_1 = require("../GenericFunctions"); class WuzapiChat { constructor() { this.description = { displayName: 'Wuzapi Chat', name: 'wuzapiChat', icon: 'file:wuzapi.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"]}}', description: 'Perform chat operations with Wuzapi WhatsApp API', defaults: { name: 'Wuzapi Chat', }, inputs: ["main" /* NodeConnectionType.Main */], outputs: ["main" /* NodeConnectionType.Main */], credentials: [ { name: 'wuzapiApi', required: true, }, ], properties: [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, options: [ { name: 'Delete Message', value: 'delete', description: 'Delete a message you sent', action: 'Delete message', }, { name: 'Download Media', value: 'download', description: 'Download media from a message', action: 'Download media', }, { name: 'Edit Message', value: 'edit', description: 'Edit a previously sent message', action: 'Edit message', }, { name: 'Mark as Read', value: 'markRead', description: 'Mark messages as read', action: 'Mark as read', }, { name: 'React to Message', value: 'react', description: 'Send a reaction to a message', action: 'React to message', }, { name: 'Set Presence', value: 'presence', description: 'Set typing/recording indicator', action: 'Set chat presence', }, ], default: 'delete', }, // Delete Message { displayName: 'Message ID', name: 'messageId', type: 'string', default: '', placeholder: 'e.g. 3EB06F9067F80BAB89FF', description: 'ID of the message to delete', required: true, displayOptions: { show: { operation: ['delete'], }, }, }, // Edit Message { displayName: 'Message ID', name: 'editMessageId', type: 'string', default: '', placeholder: 'e.g. 90B2F8B13FAC8A9CF6B06E99C7834DC5', description: 'ID of the message to edit', required: true, displayOptions: { show: { operation: ['edit'], }, }, }, { displayName: 'Phone Number', name: 'editPhone', type: 'string', default: '', placeholder: 'e.g. 5491155553934 or me:5491155553934', description: 'Phone number or "me:" prefix for your own message', required: true, displayOptions: { show: { operation: ['edit'], }, }, }, { displayName: 'New Message', name: 'newBody', type: 'string', default: '', placeholder: 'Type the updated message here', description: 'New content for the message', required: true, displayOptions: { show: { operation: ['edit'], }, }, }, // Download Media { displayName: 'Media Type', name: 'mediaType', type: 'options', default: 'image', options: [ { name: 'Audio', value: 'audio', description: 'Download audio from message', }, { name: 'Document', value: 'document', description: 'Download document from message', }, { name: 'Image', value: 'image', description: 'Download image from message', }, { name: 'Video', value: 'video', description: 'Download video from message', }, ], description: 'Type of media to download', displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'Media URL', name: 'url', type: 'string', default: '', description: 'URL of the media file', required: true, displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'Direct Path', name: 'directPath', type: 'string', default: '', description: 'Direct path to the media file', displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'Media Key', name: 'mediaKey', type: 'string', default: '', description: 'Media encryption key', required: true, displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'Mime Type', name: 'mimetype', type: 'string', default: '', placeholder: 'e.g. image/jpeg', description: 'MIME type of the media', required: true, displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'File SHA256', name: 'fileSHA256', type: 'string', default: '', description: 'SHA256 hash of the file', required: true, displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'File Length', name: 'fileLength', type: 'number', default: 0, description: 'Size of the file in bytes', required: true, displayOptions: { show: { operation: ['download'], }, }, }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { operation: ['download'], }, }, options: [ { displayName: 'File Enc SHA256', name: 'fileEncSHA256', type: 'string', default: '', description: 'Encrypted file SHA256 hash', }, { displayName: 'Binary Property Name', name: 'binaryPropertyName', type: 'string', default: 'data', description: 'Name of the binary property to store the downloaded media', }, ], }, // Mark as Read { displayName: 'Message IDs', name: 'messageIds', type: 'string', default: '', placeholder: 'AABBCC11223344,DDEEFF55667788', description: 'Comma-separated list of message IDs to mark as read', required: true, displayOptions: { show: { operation: ['markRead'], }, }, }, { displayName: 'Chat JID', name: 'chatJid', type: 'string', default: '', placeholder: 'e.g. 5491155553934.0:1@s.whatsapp.net', description: 'JID of the chat containing the messages', required: true, displayOptions: { show: { operation: ['markRead'], }, }, }, { displayName: 'Sender JID', name: 'senderJid', type: 'string', default: '', placeholder: 'e.g. 5491155553111.0:1@s.whatsapp.net', description: 'JID of the message sender', displayOptions: { show: { operation: ['markRead'], }, }, }, // React to Message { displayName: 'Phone Number', name: 'reactPhone', type: 'string', default: '', placeholder: 'e.g. 5491155553934 or me:5491155553934', description: 'Phone number or "me:" prefix for your own message', required: true, displayOptions: { show: { operation: ['react'], }, }, }, { displayName: 'Reaction', name: 'reaction', type: 'string', default: '', placeholder: 'e.g. ❤️, 👍, 😂', description: 'Emoji to react with (leave empty to remove reaction)', displayOptions: { show: { operation: ['react'], }, }, }, { displayName: 'Message ID', name: 'reactMessageId', type: 'string', default: '', placeholder: 'e.g. me:3EB06F9067F80BAB89FF', description: 'ID of the message to react to (prefix with "me:" for your own messages)', required: true, displayOptions: { show: { operation: ['react'], }, }, }, // Set Presence { displayName: 'Phone Number', name: 'presencePhone', type: 'string', default: '', placeholder: 'e.g. 5491155553934', description: 'Phone number to set presence for', required: true, displayOptions: { show: { operation: ['presence'], }, }, }, { displayName: 'State', name: 'state', type: 'options', default: 'composing', options: [ { name: 'Typing', value: 'composing', description: 'Show typing indicator', }, { name: 'Not Typing', value: 'paused', description: 'Hide typing indicator', }, ], description: 'Presence state to set', displayOptions: { show: { operation: ['presence'], }, }, }, { displayName: 'Media Type', name: 'presenceMedia', type: 'options', default: '', options: [ { name: 'None', value: '', description: 'Regular typing indicator', }, { name: 'Audio', value: 'audio', description: 'Recording audio indicator', }, ], description: 'Type of media being composed', displayOptions: { show: { operation: ['presence'], }, }, }, ], }; } async execute() { const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { const operation = this.getNodeParameter('operation', i); let responseData; if (operation === 'delete') { const messageId = this.getNodeParameter('messageId', i); const body = { Id: messageId, }; responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', '/chat/delete', body); } else if (operation === 'edit') { const messageId = this.getNodeParameter('editMessageId', i); const phone = this.getNodeParameter('editPhone', i); const newBody = this.getNodeParameter('newBody', i); const body = { Id: messageId, Phone: phone, Body: newBody, }; responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', '/chat/send/edit', body); } else if (operation === 'download') { const mediaType = this.getNodeParameter('mediaType', i); const url = this.getNodeParameter('url', i); const directPath = this.getNodeParameter('directPath', i); const mediaKey = this.getNodeParameter('mediaKey', i); const mimetype = this.getNodeParameter('mimetype', i); const fileSHA256 = this.getNodeParameter('fileSHA256', i); const fileLength = this.getNodeParameter('fileLength', i); const additionalFields = this.getNodeParameter('additionalFields', i); const body = { Url: url, MediaKey: mediaKey, Mimetype: mimetype, FileSHA256: fileSHA256, FileLength: fileLength, }; if (directPath) { body.DirectPath = directPath; } if (additionalFields.fileEncSHA256) { body.FileEncSHA256 = additionalFields.fileEncSHA256; } let endpoint = '/chat/download'; switch (mediaType) { case 'image': endpoint = '/chat/downloadimage'; break; case 'video': endpoint = '/chat/downloadvideo'; break; case 'audio': endpoint = '/chat/downloadaudio'; break; case 'document': endpoint = '/chat/downloaddocument'; break; } responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', endpoint, body); // Handle binary data if (responseData.data && responseData.data.Data) { const binaryPropertyName = additionalFields.binaryPropertyName || 'data'; const dataUrl = responseData.data.Data; const matches = dataUrl.match(/^data:([^;]+);base64,(.+)$/); if (matches && matches[2]) { const mimeType = matches[1] || mimetype; const base64Data = matches[2]; // Determine file extension from mime type let fileExtension = 'bin'; if (mimeType.includes('image')) fileExtension = mimeType.split('/')[1] || 'jpg'; else if (mimeType.includes('video')) fileExtension = mimeType.split('/')[1] || 'mp4'; else if (mimeType.includes('audio')) fileExtension = mimeType.split('/')[1] || 'ogg'; else if (mimeType.includes('pdf')) fileExtension = 'pdf'; items[i].binary = items[i].binary || {}; items[i].binary[binaryPropertyName] = { data: base64Data, mimeType, fileExtension, fileName: `downloaded-media.${fileExtension}`, }; } } } else if (operation === 'markRead') { const messageIds = this.getNodeParameter('messageIds', i); const chatJid = this.getNodeParameter('chatJid', i); const senderJid = this.getNodeParameter('senderJid', i); const body = { Id: messageIds.split(',').map(id => id.trim()), Chat: chatJid, }; if (senderJid) { body.Sender = senderJid; } responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', '/chat/markread', body); } else if (operation === 'react') { const phone = this.getNodeParameter('reactPhone', i); const reaction = this.getNodeParameter('reaction', i); const messageId = this.getNodeParameter('reactMessageId', i); const body = { Phone: phone, Body: reaction, Id: messageId, }; responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', '/chat/react', body); } else if (operation === 'presence') { const phone = this.getNodeParameter('presencePhone', i); const state = this.getNodeParameter('state', i); const media = this.getNodeParameter('presenceMedia', i); const body = { Phone: phone, State: state, }; if (media) { body.Media = media; } responseData = await GenericFunctions_1.wuzapiApiRequest.call(this, 'POST', '/chat/presence', body); } const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } }); returnData.push(...executionData); } catch (error) { if (this.continueOnFail()) { const executionErrorData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray({ error: error.message }), { itemData: { item: i } }); returnData.push(...executionErrorData); continue; } throw error; } } return [returnData]; } } exports.WuzapiChat = WuzapiChat; //# sourceMappingURL=WuzapiChat.node.js.map