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
JavaScript
;
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