puppet-padlink 是一个基于 Wechaty 的微信机器人框架,目前支持 Windows 和 Linux 平台。
- Windows 10 或更高版本(推荐使用win)
- Linux 系统(建议使用 Ubuntu 24.04)
- Node.js 12 或更高版本
- Redis 服务器
npm install wechaty-puppet-padlink-
下载 Redis for Windows:
- 访问 Redis Windows 下载页面
- 下载最新的
.msi安装包
-
安装步骤:
- 双击下载的
.msi文件 - 按照安装向导完成安装
- 安装程序会自动将 Redis 添加为 Windows 服务
- 双击下载的
-
启动 Redis:
- 打开服务管理器(services.msc)
- 找到 "Redis" 服务
- 右键选择"启动"
-
安装 Redis:
sudo apt update sudo apt install redis-server
-
启动 Redis 服务:
sudo systemctl start redis-server
-
设置开机自启:
sudo systemctl enable redis-server
- 访问 GitHub Releases
- 下载对应平台的压缩包:
- Windows:
padlink-win-v1.0.0.zip - Linux:
padlink-linux-v1.0.0.zip
- Windows:
将下载的压缩包解压到项目根目录或者其他地方文件夹, 文件结构如下:
your-project/
├── bin/
│ ├── padlink-win/
│ │ └── win.exe # Windows 可执行文件
│ └── padlink-linux/
│ └── linux # Linux 可执行文件
├── package.json
└── ...
-
双击
bin/padlink-win/win.exe -
如果启动成功,您会看到类似以下的输出:
启动成功
chmod +x bin/padlink-linux/linux
./bin/padlink-linux/linux启动完之后即可使用padlink傀儡
如需获取专属 token,请联系下方客服:
- 飞书扫码联系:
- 或发送邮件至:padlink001@gmail.com
注意: token 是使用本服务的唯一凭证,请妥善保管,勿泄露给他人。
const { WechatyBuilder } = require("wechaty");
const { PuppetPadlink } = require("wechaty-puppet-padlink");
const PUPPET = require("wechaty-puppet");
const puppet = new PuppetPadlink({
token: "你的token", //如:puppet_padplnk_1234567890
});
const bot = WechatyBuilder.build({ puppet });
bot.start();const qrcodeTerminal = require("qrcode-terminal");
// 扫描二维码事件
bot.on("scan", async (qrcode, status) => {
switch (status) {
case 2:
qrcodeTerminal.generate(qrcode, { small: true }, (output) => {
console.log("请扫描二维码登录:\n", output);
});
break;
case 3:
console.log("已扫描,请在手机上确认登录");
break;
case 4:
console.log("已确认登录");
break;
default:
console.log(`扫描状态:${status}`);
}
});
// 登录成功通知
bot.on("login", () => {
console.log("机器人登录成功");
});- 事件参考:
WechatyEventName。以及每个事件对应的回调数据类型:WechatyEventFunction
await bot.logout();//接受消息回调
bot.on("message", async (msg) => {
console.log("接受消息", msg);
});//消息通知回调
bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试文本
if (msg.text() == "测试文本") {
await msg.say("文本");
}
});bot.on("message", async (msg) => {
// 仅对群消息有效,(如在群里发送:测试)
if (msg.room()) {
if (msg.text() == "测试") {
msg.room()?.say("我是padlink", msg.talker());
}
}
});const { FileBox } = require("file-box");
bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试图片
if (msg.text() == "测试图片") {
const fileBox = FileBox.fromUrl(
"http://conimg.yp.yeyimg.com/2025/06/12/5846d6ef-7bff-4d2b-b4a7-4e8d430f341e.jpeg"
);
await msg.say(fileBox);
}
});// 语音文件为 silk 格式。silk 是 skype 开源的一款语音编解码器,被微信的语音文件所采用。
// 注意:文件后缀必须是 `sil`!
const { FileBox } = require("file-box");
bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试语音
if (msg.text() == "测试语音") {
const voiceLength = 1000; // 需要提供语音长度,单位为毫秒
const fileBox = FileBox.fromUrl(
"http://conimg.yp.yeyimg.com/2025/06/12/43660edf-0998-4405-8184-90bf6bfe6b55.sil"
);
fileBox.mimeType = "audio/silk";
fileBox.metadata = {
voiceLength,
};
await msg.say(fileBox);
}
});- silk 转码工具:
silk-v3-decoder
const { FileBox } = require("file-box");
bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试视频
if (msg.text() == "测试视频") {
const fileBox = FileBox.fromUrl("https://---------.mp4"); //填你的视频地址
await msg.say(fileBox);
}
});bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试链接
if (msg.text() == "测试链接") {
const thumbnail =
"http://conimg.yp.yeyimg.com/2023/08/14/e5c4085a-993d-467d-a4b5-437fc00569e3.png";
let url = `https://www.baidu.com/`;
const title = "百度";
const artists = "";
const urlLink = new bot.UrlLink({
title,
description: artists,
url,
thumbnailUrl: thumbnail,
});
msg.say(urlLink);
}
});bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试小程序
if (msg.text() == "测试小程序") {
// 小程序信息
const miniProgram = new bot.MiniProgram({
appid: "wxde8a",
description: "美团丨外卖美食买菜酒店电影购物",
iconUrl: "http://mmbiz.qpic.cn/sz_mmbiz",
pagePath: "index/pages/mt/mt.html",
shareId: "0_wxde8a...........",
thumbKey: "f8df........",
thumbUrl: "3057020100044b304902010002047c0346d.........",
title: "吃喝玩乐 尽在美团",
username: "gh_@app........",
});
msg.say(miniProgram);
}
});这些参数就是收到的表情消息中的数据。
const { FileBox } = require("file-box");
bot.on("message", async (msg) => {
// 如在群里或者对机器发送:测试表情
if (msg.text() == "测试表情") {
const fileBox = FileBox.fromUrl(
"https://guessCar/carPhoto/GMC_89.jpg",
`message-emotion.jpg`
);
fileBox.mimeType = "application/unknown";
const metadata = {
payload: {
gameext: undefined,
type: 2,
width: 540,
height: 540,
md5: "28b9871de90d70c7de11d8a2717fa50d",
len: 409409,
},
type: "emoticon",
};
fileBox.metadata = metadata;
try {
await msg.say(fileBox);
} catch (error) {
console.log(error);
}
}
});//仅对机器人自己发的有效
await msg.recall();// 所有联系人列表中,包含了聊天室中哪些不认识联系人
const allContactList = await bot.Contact.findAll();
// 获取你添加过的好友。和微信一样,不知道对方是否删除了你
const friendList = allContactList.filter((contact) => contact.friend());const isFriend = contact.friend();const self = bot.currentUser;
// 获取
const oldName = self.name();
// 设置
const toName: string = "NEW NICK NAME";
await self.name(toName);const self = bot.currentUser;
const qrStr = await self.qrcode();
// 再用二维码生成工具将 qrStr 生成为二维码即可const self = bot.currentUser;
await self.signature("NEW SIGNATURE");const contact = (await bot.Contact.find({ id: "wxid_xxx" }))!;
// 获取
const oldAlias = await contact.alias();
// 设置
await contact.alias("新的备注");// 自己
const selfContact = bot.currentUser;
const selfAvatarFileBox = await selfContact.avatar();
// 他人
const contact = (await bot.Contact.find({ id: "wxid_xxx" }))!;
const otherAvatarFileBox = await contact.avatar();const puppet = bot.puppet;
await puppet.contactDelete(deleteUserName);
// contact 对象仍然可以得到,但是 friend 变为了 false
const contact = await bot.Contact.find({ id: deleteUserName });
expect(contact!.friend()).toBeFalsy();bot.on("friendship", async (friendship) => {
if (friendship.type() === FriendshipType.Receive) {
await friendship.accept();
}
});// 这种方式的前提是:必须已经知道了对方的 id
const contact = await bot.Contact.find({ id: "wxid_" });
await bot.Friendship.add(contact!, hello);const contact = await bot.Friendship.search({ phone: "135xxx" });
await bot.Friendship.add(contact!, "朋友,你好");const contact = await bot.Friendship.search({ weixin: "wx" });
await bot.Friendship.add(contact!, "朋友,你好");const allRooms = await bot.Room.findAll();// 至少两个其他好友
const memberIdList = ["wxid_xxx", "wxid_yyy"];
const contactList = [];
for (const userId of memberIdList) {
const contact = await bot.Contact.find({ id: userId });
contactList.push(contact!);
}
const roomName = "room.....";
const newRoom = await bot.Room.create(contactList, roomName);
await newRoom.ready();
await newRoom.say("Hello World!");const memberList = await room.memberAll();const room = (await bot.Room.find({ id: "xxx@chatroom" }))!;
const contact = await bot.Contact.find({ id: "wxid_" });
await room!.add(contact!);
// 稍微等待一下
await new Promise((resolve) => setTimeout(resolve, 1000));
// newMemberList 就包含新添加的成员了
const newMemberList = await room.memberAll();const room = (await bot.Room.find({ id: "xxx@chatroom" }))!;
const contact = await bot.Contact.find({ id: "wxid_" });
await room.del(contact!);
// 稍微等待一下
await new Promise((resolve) => setTimeout(resolve, 1000));
// newMemberList 就不包含被删除的联系人
const newMemberList = await room.memberAll();const avatarFileBox = await room!.avatar();二维码需要 bot 保持在线至少24小时后才能获取,否则会出现"生成的群二维码已经失效"的错误
const qrString = await room.qrCode();
// 用二维码生成工具,将 qrString 生成为二维码即可// 获取
const oldTopic = await room.topic();
// 设置
await room.topic("新的群聊名称");// 获取
const announcement = await room.announce();
// 设置
await room.announce("新的群公告");await room.quit();bot.on("room-invite", async (roomInvite) => {
await roomInvite.accept();
});bot.on(
"room-join",
async (room, inviteeList, inviter: Contact, date) => {
log.info(
`on room join: ${room.toString()}, inviteeList: ${inviteeList.map((i) => i.id)}, inviter: ${
inviter.id
}, ${date}`
);
}
);只有自己是群主或管理员的群才能收到退出群聊通知。
bot.on("room-leave", async (room, leaverList, removert, date) => {
log.info(
`on room leave: ${room.toString()}, leaverList: ${leaverList.map((l) => l.id)}, remover: ${
remover?.id
} ${date}`
);
});bot.on("room-topic", async (room, newTopic, oldTopic, changer, date) => {
log.info(
`on room topic: ${room.toString()}, ${newTopic}, ${oldTopic}, ${changer.toString()}, ${date}`
);
});const tag = await bot.Tag.get("标签名称");
const contact = await bot.Contact.find({ id: "wxid_xxx" });
await tag.add(contact!);const tag = await bot.Tag.get("标签名称");
const contact = await bot.Contact.find({ id: "wxid_xxx" });
await tag.remove(contact!);const tag = await bot.Tag.get("标签名称");
await bot.Tag.delete(tag);const contact = await bot.Contact.find({ id: "wxid_xxx" });
const tags = await contact!.tags();- 确保 Redis 服务正常运行(6379端口)
- 保持二进制文件所在目录的访问权限
- 如果遇到 Redis 相关错误,请确保 Redis 服务器已安装并运行
- 如果遇到二进制文件错误,请尝试重新重启
- 如果使用过程中遇到权限问题:
- Windows: 以管理员身份运行命令提示符
- Linux: 使用 sudo 运行安装命令
