基于Node.js与Wechaty构建微信个人助手
本文介绍如何利用Node.js配合Wechaty框架开发一个具备多项实用功能的微信个人助手。该助手能够自动处理好友请求、关键词响应、群聊互动、小程序解析及翻译等任务。
Wechaty简介
Wechaty是一个面向聊天机器人的现代RPA SDK,开发者仅需少量代码即可快速构建功能丰富的聊天机器人。它支持将即时通讯账号转换为智能助手,并允许开发者根据具体需求进行定制扩展。
最小化示例
以下是最基础的机器人实现,仅需数行代码:
const { Wechaty } = require('wechaty')
async function main () {
const bot = new Wechaty()
bot
.on('scan', (qrcode, status) => console.log(`扫描二维码登录: ${status}\nhttps://wechaty.js.org/qrcode/${encodeURIComponent(qrcode)}`))
.on('login', user => console.log(`用户 ${user} 已登录`))
.on('message', message => console.log(`收到消息: ${message}`))
await bot.start()
}
main().catch(console.error)
环境准备
开始前,请确保拥有可运行Wechaty的微信账号,并获取相应协议的Token(如puppet_padlocal)。
核心功能
- 自动接受好友请求,支持关键字验证
- 私信关键词响应,例如"加群"推送邀请
- 群聊互动模式,支持@机器人对话
- 小程序信息提取
- 新成员入群欢迎语
- 英文文本翻译(限2000字符内)
依赖接口
- 有道翻译、百度翻译
- 天行数据API
关键代码实现
主程序入口
bot.js
const { Wechaty } = require("wechaty");
const { PuppetPadlocal } = require("wechaty-puppet-padlocal");
const QrcodeTerminal = require("qrcode-terminal");
const onMessage = require("./onMessage");
const config = require("./config");
const bot = new Wechaty({
puppet: new PuppetPadlocal({
token: config.token,
}),
});
bot
.on("scan", (qrcode, status) => {
console.log(`扫码登录: ${status}\nhttps://api.qrserver.com/v1/create-qr-code/?data=${encodeURIComponent(qrcode)}`);
QrcodeTerminal.generate(qrcode);
})
.on("login", user => console.log(`${user} 登录成功`))
.on("logout", user => console.log(`${user} 已登出`))
.on("message", onMessage(bot))
.start();
消息处理模块
onMessage.js
const { UrlLink } = require("wechaty");
const request = require("request");
const urlencode = require("urlencode");
const config = require("./config");
const miniProrReply = require("../utils/miniProReply");
const translate = require("../utils/translate");
const { rainbowFart, circle, drugInstruction } = require("../utils/txAPI");
const name = config.name;
const roomList = config.room.roomList;
module.exports = (bot) => {
return async function onMessage(msg) {
if (msg.self()) return;
switch (msg.type()) {
case 7: // 文本消息
console.log("接收到文本");
if (await handleJoinGroup(msg)) return;
if (await handleGroupName(bot, msg)) return;
if (msg.payload.roomId) {
if (msg.payload.roomId === "20856899751@chatroom") {
const reg = /^[\u4e00-\u9fa5]+$/;
if (!reg.test(msg.text())) {
translate(msg);
return;
} else {
handleRoomChat(msg);
return;
}
}
}
break;
case 9: // 小程序
console.log("检测到小程序");
miniProrReply(msg);
break;
case 14: // 卡片链接
console.log("检测到卡片链接");
break;
default:
console.log("暂不支持此消息类型");
break;
}
};
};
async function handleRoomChat(msg) {
const room = msg.room();
const text = msg.text();
if (await msg.mentionSelf()) {
const sendText = text.replace("@蔚蓝", "");
let res = await callBotAPI(sendText);
room.say(res);
} else {
let content = await callBotAPI(text);
room.say(content);
return;
}
if (/互动/.test(text)) {
room.say("互动测试");
} else if (/彩虹屁/.test(text)) {
let reply = await rainbowFart({});
room.say(reply);
} else if (/文案/.test(text)) {
let reply = await circle({});
room.say(reply);
} else if (/蔚蓝工作室/.test(text)) {
room.say(new UrlLink(config.personal.introUrl));
} else if (/药品/.test(text)) {
let params = { word: text.substring(2) };
let reply = await drugInstruction(params);
room.say(reply);
}
}
async function handleJoinGroup(msg) {
if (msg.text() == "加群") {
let roomNames = Object.keys(roomList);
let info = `${name}当前管理${roomNames.length}个群聊,回复群名即可加入\n\n`;
roomNames.forEach(v => {
info += "【" + v + "】\n";
});
msg.say(info);
return true;
}
return false;
}
async function handleGroupName(bot, msg) {
if (Object.keys(roomList).some(v => v == msg.text())) {
const room = await bot.Room.find({ id: roomList[msg.text()] });
if (await room.has(msg.from())) {
await msg.say("您已在该群聊中");
return true;
}
await room.add(msg.from());
await msg.say("已发送群邀请");
return true;
}
return false;
}
function callBotAPI(info) {
return new Promise((resolve) => {
let url = `https://open.drea.cc/bbsapi/chat/get?keyWord=${urlencode(info)}`;
request(url, (error, response, body) => {
if (!error && response.statusCode == 200) {
let res = JSON.parse(body);
if (res.isSuccess) {
let send = res.data.reply.replace(/Smile/g, name);
resolve(send);
} else {
resolve(res.code == 1010 ? "没事别老艾特我" : "听不懂你说的");
}
} else {
resolve("网络异常,请稍后再试");
}
});
});
}
工具函数目录
utils目录包含翻译接口调用、小程序参数解析、第三方API封装等功能模块,可根据实际需要修改相关密钥配置。
常见问题
- 若使用旧版padplus协议,建议升级至hostie或service协议
- 部分npm包可能已更名,请使用最新版本替代
Token获取
推荐使用padlocal协议,提供7天免费试用期。
通过合理配置各组件,您可以快速搭建属于自己的微信智能助手。完整源码可在GitHub查看。