UNPKG

n8n-nodes-wechat-pad-pro

Version:

n8n node for WeChatPadPro, allowing you to automate WeChat messaging and interactions within your n8n workflows. Support WeChatPadPro0859

336 lines 17.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WeChatPadProTrigger = void 0; const n8n_workflow_1 = require("n8n-workflow"); const xml2js_1 = require("xml2js"); const ws_1 = __importDefault(require("ws")); const buffer_1 = require("buffer"); const audioUtils_1 = require("../audioUtils"); var MsgType; (function (MsgType) { MsgType[MsgType["Text"] = 1] = "Text"; MsgType[MsgType["Image"] = 3] = "Image"; MsgType[MsgType["Voice"] = 34] = "Voice"; MsgType[MsgType["EmojiOrVideo"] = 47] = "EmojiOrVideo"; })(MsgType || (MsgType = {})); class WeChatPadProTrigger { constructor() { this.description = { displayName: 'WeChatPadPro Trigger', name: 'weChatPadProTrigger', icon: 'file:wechatPadPro.svg', group: ['trigger'], version: 1, description: 'Triggers the workflow when a new message is received via WeChatPadPro', defaults: { name: 'WeChatPadPro Trigger', }, inputs: [], outputs: ["main"], credentials: [ { name: 'weChatPadProApi', required: true, }, ], properties: [ { displayName: '场景', name: 'scene', type: 'options', options: [ { name: '接收文本消息', value: 'text', }, { name: '接收图片消息', value: 'image', }, { name: '接收语音消息', value: 'voice', }, { name: '接收表情消息', value: 'emoji', }, { name: '接收视频消息', value: 'video', }, { name: '其他事件', value: 'other', }, ], default: 'text', description: '选择要监听的消息场景', }, { displayName: '群聊消息接收规则', name: 'groupMessageRule', type: 'options', options: [ { name: '接收全部消息', value: 'all', }, { name: '接收@机器人消息', value: 'mention', displayOptions: { show: { scene: ['text'], }, }, }, { name: '不接收消息', value: 'none', }, ], default: 'all', description: '选择群聊消息接收规则', }, { displayName: '群聊白名单', name: 'groupWhitelist', type: 'string', typeOptions: { multipleValues: true, }, displayOptions: { show: { scene: ['text', 'voice', 'image', 'emoji', 'video'], groupMessageRule: ['all', 'mention'], }, }, default: [], description: '设置允许接收消息的群聊ID列表', }, ], }; } async trigger() { const credentials = await this.getCredentials('weChatPadProApi'); if (credentials === undefined) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No credentials got returned!'); } const { baseUrl, authKey } = credentials; const urlString = baseUrl.toString(); const isSecure = urlString.startsWith('https://') || urlString.startsWith('wss://'); const protocol = isSecure ? 'wss' : 'ws'; const cleanBaseUrl = urlString.replace(/(^\w+:|^)\/\//, ''); const wsUrl = `${protocol}://${cleanBaseUrl}/ws/GetSyncMsg?key=${authKey}`; let ws; let pingInterval; const connect = () => { console.log('wsUrl===', wsUrl); ws = new ws_1.default(wsUrl); ws.on('open', () => { this.logger.info('WeChatPadPro Trigger: WebSocket connection established.'); pingInterval = setInterval(() => { if (ws.readyState === ws_1.default.OPEN) { ws.ping(); } }, 30000); }); ws.on('message', async (data) => { var _a, _b, _c, _d, _e, _f; try { const message = JSON.parse(data.toString()); const scene = this.getNodeParameter('scene', 'text'); const groupMessageRule = this.getNodeParameter('groupMessageRule', 'all'); const msgType = message.msg_type; message.fromUserName = (_a = message.from_user_name) === null || _a === void 0 ? void 0 : _a.str; message.toUserName = (_b = message.to_user_name) === null || _b === void 0 ? void 0 : _b.str; message.msgContent = (_c = message.content) === null || _c === void 0 ? void 0 : _c.str; delete message.from_user_name; delete message.to_user_name; delete message.content; if (message.msg_source) { try { const sourceData = await (0, xml2js_1.parseStringPromise)(message.msg_source, { explicitArray: false, ignoreAttrs: true, charkey: 'text', trim: true, }); message.msgSource = sourceData === null || sourceData === void 0 ? void 0 : sourceData.msgsource; delete message.msg_source; const msgJson = await (0, xml2js_1.parseStringPromise)(message.msgContent, { explicitArray: false, ignoreAttrs: false, charkey: 'text', trim: true, }); message.contentObj = msgJson; } catch (e) { } } let shouldTrigger = false; if ([MsgType.Text, MsgType.Image, MsgType.Voice, MsgType.EmojiOrVideo].includes(msgType)) { const isGroupMessage = (_d = message.fromUserName) === null || _d === void 0 ? void 0 : _d.includes('@chatroom'); if (!isGroupMessage) { shouldTrigger = true; } else { switch (groupMessageRule) { case 'all': shouldTrigger = true; break; case 'mention': shouldTrigger = (_f = (_e = message.msgSource) === null || _e === void 0 ? void 0 : _e.atuserlist) === null || _f === void 0 ? void 0 : _f.includes(message.toUserName); break; case 'none': shouldTrigger = false; break; } const groupWhitelist = this.getNodeParameter('groupWhitelist', []); if (shouldTrigger && groupWhitelist.length > 0) { shouldTrigger = groupWhitelist.includes(message.fromUserName); } } } if (shouldTrigger) { switch (msgType) { case MsgType.Image: try { const bigImgUrl = `${baseUrl}/message/GetMsgBigImg?key=${authKey}`; let startPos = 0; let totalLen = null; let imageData = []; while (totalLen === null || startPos < totalLen) { const requestBody = { CompressType: 0, FromUserName: message.FromUserName, MsgId: message.msg_id, Section: { DataLen: 65536, StartPos: startPos }, ToUserName: message.ToUserName, TotalLen: totalLen === null ? undefined : totalLen, }; const options = { method: 'POST', url: bigImgUrl, json: true, body: requestBody, }; const { Code, Data } = await this.helpers.httpRequest(options); if (Code !== 200) { this.logger.error(`WeChatPadPro Trigger: 获取图片分段失败,Code: ${Code}`); break; } const dataBuffer = Data.Data.Buffer; if (!dataBuffer) { this.logger.error('WeChatPadPro Trigger: 响应中缺少图片数据'); break; } try { const chunkData = buffer_1.Buffer.from(dataBuffer, 'base64'); if (chunkData.length === 0) { this.logger.warn('WeChatPadPro Trigger: 接收到空数据块'); break; } imageData.push(chunkData); const chunkSize = chunkData.length; startPos += chunkSize; if (totalLen === null) { totalLen = Data === null || Data === void 0 ? void 0 : Data.TotalLen; if (typeof totalLen !== 'number' || totalLen <= 0) { this.logger.error('WeChatPadPro Trigger: 无效的图片总长度'); break; } this.logger.info(`WeChatPadPro Trigger: 图片总长度: ${totalLen} 字节`); } this.logger.info(`WeChatPadPro Trigger: 下载进度: ${startPos}/${totalLen}`); } catch (e) { this.logger.error(`WeChatPadPro Trigger: Base64解码失败: ${e.message}`); break; } } if (totalLen !== null && startPos === totalLen) { const fullImageData = buffer_1.Buffer.concat(imageData); message.msgContent = fullImageData.toString('base64'); this.logger.info(`WeChatPadPro Trigger: 图片下载完成,大小: ${fullImageData.length} 字节`); } else { this.logger.warn('WeChatPadPro Trigger: 图片下载未完成或遇到问题。'); } delete message.img_buf; } catch (error) { this.logger.error(`WeChatPadPro Trigger: Error getting big image: ${error.message}`); } break; case MsgType.Voice: try { const voiceB64 = message.img_buf.buffer; const Data = { Base64: voiceB64 }; const Code = 200; if (Code === 200 && (Data === null || Data === void 0 ? void 0 : Data.Base64)) { let silkBuffer = buffer_1.Buffer.from(voiceB64, 'base64'); try { const pcmBase64 = await (0, audioUtils_1.silkToPcmBase64)(silkBuffer); const wavBase64 = await (0, audioUtils_1.silkToWavBase64)(silkBuffer); message.pcmData = pcmBase64; message.msgContent = wavBase64; this.logger.info(`WeChatPadPro Trigger: 语音下载并转换为 WAV 格式完成,大小: ${message.msgContent.length} 字节`); } catch (e) { this.logger.error(`WeChatPadPro Trigger: 语音转换失败: ${e.message}`); message.msgContent = Data.Base64; } } else { this.logger.error(`WeChatPadPro Trigger: 下载语音失败,Code: ${Code}, Data: ${JSON.stringify(Data)}`); } } catch (error) { this.logger.error(`WeChatPadPro Trigger: 下载语音时发生错误: ${error.message}`); } break; case MsgType.EmojiOrVideo: break; default: break; } } if (shouldTrigger || scene === 'other') { this.emit([this.helpers.returnJsonArray([message])]); } } catch (error) { this.logger.error('WeChatPadPro Trigger: Error parsing WebSocket message.', error); } }); ws.on('error', (error) => { this.logger.error(`WeChatPadPro Trigger: WebSocket error: ${error.message}`); }); ws.on('close', (code, reason) => { clearInterval(pingInterval); this.logger.warn(`WeChatPadPro Trigger: WebSocket connection closed (code: ${code}, reason: ${reason.toString()}). Reconnecting...`); setTimeout(connect, 5000); }); }; connect(); return { dispose: async () => { if (pingInterval) { clearInterval(pingInterval); } if (ws) { ws.removeAllListeners(); ws.close(); } }, }; } } exports.WeChatPadProTrigger = WeChatPadProTrigger; //# sourceMappingURL=WeChatPadProTrigger.node.js.map