UNPKG

n8n-nodes-zalo-nnt

Version:

Unofficial Zalo integration for n8n - Send messages, manage groups, user operations with QR login. No API key required, works via browser simulation.

305 lines 14.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ZaloMessageTrigger = void 0; const n8n_workflow_1 = require("n8n-workflow"); const branding_1 = require("../shared/branding"); const constants_1 = require("./constants"); const EventFilter_1 = require("./EventFilter"); const EventListenerRegistry_1 = require("./EventListenerRegistry"); const ZaloConnectionManager_1 = require("./ZaloConnectionManager"); const CatchUpManager_1 = require("./CatchUpManager"); let api; let reconnectTimer; function getNodeConfig(functions) { const selfListen = functions.getNodeParameter('selfListen', 0); const eventTypes = functions.getNodeParameter('eventTypes', 0); const messageContentTypes = functions.getNodeParameter('messageContentTypes', 0); const threadTypes = functions.getNodeParameter('threadTypes', 0); const specificIds = functions.getNodeParameter('specificIds', 0); const catchUpOnReconnect = functions.getNodeParameter('catchUpOnReconnect', true); const idList = specificIds .split(',') .map(id => id.trim()) .filter(id => id); return { selfListen, eventTypes, messageContentTypes, threadTypes, specificIds, idList, catchUpOnReconnect, }; } class ZaloMessageTrigger { constructor() { this.description = { displayName: 'Zalo Event Trigger by diginno.net Trigger', name: 'zaloMessageTrigger', icon: 'file:../shared/image.svg', group: ['trigger'], version: 2, description: 'Lắng nghe các sự kiện từ Zalo (tin nhắn, reaction, typing, group events, friend events, etc) by diginno.net', defaults: { name: 'Zalo Event Trigger by diginno.net', }, inputs: [], outputs: ['main'], webhooks: [ { name: 'default', httpMethod: 'POST', responseMode: 'onReceived', path: 'webhook', }, ], credentials: [ { name: 'zaloApi', required: true, displayName: 'Zalo Credential to connect with', }, ], properties: [ branding_1.BRANDING_CONFIG, { displayName: 'Loại Sự Kiện', name: 'eventTypes', type: 'multiOptions', options: [ { name: 'Tin Nhắn Mới', value: constants_1.EVENT_TYPES.MESSAGE, description: 'Lắng nghe tin nhắn mới từ user và group', }, { name: 'Reaction (Thả Cảm Xúc)', value: constants_1.EVENT_TYPES.REACTION, description: 'Khi có người thả reaction vào tin nhắn', }, { name: 'ĐAng Soạn Tin', value: constants_1.EVENT_TYPES.TYPING, description: 'Khi có người đang gõ tin nhắn', }, { name: 'ĐÃ Xem Tin Nhắn', value: constants_1.EVENT_TYPES.SEEN_MESSAGES, description: 'Khi tin nhắn được xem', }, { name: 'ĐÃ Nhận Tin Nhắn', value: constants_1.EVENT_TYPES.DELIVERED_MESSAGES, description: 'Khi tin nhắn được gửi thành công', }, { name: 'Thu Hồi Tin Nhắn', value: constants_1.EVENT_TYPES.UNDO, description: 'Khi có tin nhắn bị thu hồi', }, { name: 'Sự Kiện Nhóm', value: constants_1.EVENT_TYPES.GROUP_EVENT, description: 'Join/Leave/Kick/Admin changes trong nhóm', }, { name: 'Sự Kiện Bạn Bè', value: constants_1.EVENT_TYPES.FRIEND_EVENT, description: 'Friend request, accept, reject, etc', }, { name: 'Trạng Thái Kết Nối', value: constants_1.EVENT_TYPES.CONNECTION, description: 'Connected, disconnected, error events', }, ], default: [constants_1.EVENT_TYPES.MESSAGE], required: true, description: 'Chọn các loại sự kiện cần lắng nghe', hint: 'Có thể chọn nhiều loại sự kiện cùng lúc. Mỗi event sẽ trigger workflow riêng biệt.', }, { displayName: 'Lọc Theo Loại Nội Dung', name: 'messageContentTypes', type: 'multiOptions', displayOptions: { show: { eventTypes: [constants_1.EVENT_TYPES.MESSAGE], }, }, options: [ { name: 'File', value: 'file', description: 'Tin nhắn file đính kèm', }, { name: 'GIF', value: 'gif', description: 'Tin nhắn ảnh động GIF', }, { name: 'Image', value: 'image', description: 'Tin nhắn hình ảnh', }, { name: 'Link', value: 'link', description: 'Tin nhắn có link hoặc thẻ xem trước', }, { name: 'Location', value: 'location', description: 'Tin nhắn chia sẻ vị trí', }, { name: 'Sticker', value: 'sticker', description: 'Tin nhắn sticker', }, { name: 'Text', value: 'text', description: 'Tin nhắn văn bản', }, { name: 'Video', value: 'video', description: 'Tin nhắn video', }, { name: 'Voice', value: 'voice', description: 'Tin nhắn voice/audio', }, ], default: [], description: 'Chỉ trigger khi nhận loại nội dung này (bỏ trống = tất cả)', hint: 'Bộ lọc này chỉ áp dụng cho tin nhắn. Bỏ trống để nhận tất cả loại tin nhắn.', }, { displayName: 'Lọc Theo Nguồn', name: 'threadTypes', type: 'multiOptions', displayOptions: { show: { eventTypes: [constants_1.EVENT_TYPES.MESSAGE, constants_1.EVENT_TYPES.REACTION, constants_1.EVENT_TYPES.TYPING], }, }, options: [ { name: 'Tin Nhắn Cá Nhân', value: 'user', description: 'Chỉ từ chat 1-1', }, { name: 'Tin Nhắn Nhóm', value: 'group', description: 'Chỉ từ nhóm chat', }, ], default: ['user', 'group'], description: 'Lọc theo nguồn tin nhắn', hint: 'Chọn cả User và Group để nhận tất cả. Bỏ chọn một trong hai để lọc nguồn cụ thể.', }, { displayName: 'Lọc Theo ID Cụ Thể', name: 'specificIds', type: 'string', displayOptions: { show: { eventTypes: [constants_1.EVENT_TYPES.MESSAGE, constants_1.EVENT_TYPES.REACTION, constants_1.EVENT_TYPES.TYPING], }, }, default: '', placeholder: '1234567890,0987654321', description: 'Chỉ trigger từ các User ID hoặc Group ID này (phân cách bằng dấu phẩy, bỏ trống = tất cả)', hint: 'Nhập danh sách User ID hoặc Group ID cách nhau bằng dấu phẩy. Bỏ trống để nhận từ tất cả.', }, { displayName: 'Self Listen', name: 'selfListen', type: 'boolean', default: false, required: true, description: 'Cho phép lắng nghe tin nhắn của chính mình tự gửi', hint: 'Bật tùy chọn này nếu muốn workflow chạy khi bạn tự gửi tin nhắn.', }, { displayName: 'Kéo Bù Sau Khi Mất Kết Nối', name: 'catchUpOnReconnect', type: 'boolean', displayOptions: { show: { eventTypes: [constants_1.EVENT_TYPES.MESSAGE], }, }, default: true, description: 'Whether to tự lấy lại tin nhắn đến trong lúc mất kết nối. Kết nối Zalo rớt rất thường xuyên; không bật thì mỗi lần rớt là thủng một mảng tin nhắn mà không ai biết.', hint: 'Tin kéo bù có cờ "isCatchUp": true và có thể trùng với tin đã nhận — hãy upsert theo msgId ở bước lưu dữ liệu.', }, ], }; this.webhookMethods = { default: { async checkExists() { const webhookData = this.getWorkflowStaticData('node'); return !!webhookData.isConnected; }, async create() { const credentials = await this.getCredentials('zaloApi'); if (!credentials) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials found'); } try { const parsedCredentials = ZaloConnectionManager_1.ZaloConnectionManager.parseCredentials(credentials); const config = getNodeConfig(this); const filter = new EventFilter_1.EventFilter(config.threadTypes, config.idList, config.messageContentTypes); api = await ZaloConnectionManager_1.ZaloConnectionManager.login(this, parsedCredentials.cookie, parsedCredentials.imei, parsedCredentials.userAgent, config.selfListen); const webhookData = this.getWorkflowStaticData('node'); webhookData.eventQueue = []; webhookData.connectionStatus = 'connecting'; EventListenerRegistry_1.EventListenerRegistry.registerAll(this, api, webhookData, config.eventTypes, filter); webhookData.connectCount = 0; if (config.catchUpOnReconnect && config.eventTypes.includes(constants_1.EVENT_TYPES.MESSAGE)) { (0, CatchUpManager_1.registerCatchUp)(this, api, webhookData, filter, config.threadTypes); } api.listener.start({ retryOnClose: true }); webhookData.isConnected = true; webhookData.eventTypes = config.eventTypes; return true; } catch (error) { ZaloConnectionManager_1.ZaloConnectionManager.handleError(this, error, api); } }, async delete() { const webhookData = this.getWorkflowStaticData('node'); if (api) { api.listener.stop(); api = undefined; } if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = undefined; } delete webhookData.isConnected; delete webhookData.eventTypes; delete webhookData.eventQueue; delete webhookData.connectCount; delete webhookData.lastCatchUpTime; return true; }, }, }; } async webhook() { const bodyData = this.getBodyData(); return { workflowData: [this.helpers.returnJsonArray([bodyData])], }; } } exports.ZaloMessageTrigger = ZaloMessageTrigger; //# sourceMappingURL=ZaloMessageTrigger.node.js.map