Wechaty API使用示例 - chatrbot/wechaty-puppet-simplepad GitHub Wiki
这里是基本的Wechaty使用示例,具体操作和项目结构可以根据自己项目来修改
import { Wechaty } from "wechaty"
import { PuppetSimplePad } from "wechaty-puppet-simplepad"
const puppet = new PuppetSimplePad({ token })
const bot = new Wechaty({ puppet })- 这里获取扫码图片看起来繁琐其实只是[获取图片]->[解析内容]->[根据内容生成二维码]这几步
- 二维码获取只有在第一次登录的时候需要,之后如果账户没有退出(手机上退出其他平台)下次启动会自动登录,无需扫码
- 首次登录的账户可能会在一天后掉线,重新登录即可
如果觉得麻烦可以
- 直接把获得的二维码图片写入本地文件
fs.writeFile('/tmp/qr.png', buffer, (err) => {
if (err) {
console.error('write qrcode file err', err)
}
})- 使用管理后台登录帐号
import { FriendshipType, ScanStatus } from "wechaty-puppet"
import { program } from "commander"
import QrcodeTerminal from "qrcode-terminal"
import QrCode from "qrcode-reader"
import Jimp from "jimp"
const puppet = new PuppetSimplePad({ token })
const bot = new Wechaty({ puppet })
bot.on("scan", async (qrcode: string, status: ScanStatus) => {
/**
* 由于服务端设计的不同,SimplePad和其他Puppet实现在获取二维码的数据上有所不同
* 其他Puppet实现可能获取到的是"二维码解析"后的数据内容,SimplePad获取到的是一
* 个二维码图片,所以需要先解析一次二维码,然后再把内容重新生成一个二维码输出到终端
*/
if (status === ScanStatus.Waiting && qrcode) {
const buffer = Buffer.from(qrcode, "base64")
await Jimp.read(buffer, function (err, image) {
if (err) {
console.error("jimp err", err)
return
}
const qr = new QrCode()
qr.callback = function (err: any, result: any) {
if (err) {
console.error("call back err", err)
return
}
QrcodeTerminal.generate(result.result, { small: true })
}
qr.decode(image.bitmap)
})
} else {
console.info("Bot Demo", `onScan: ${ScanStatus[status]}(${status})`)
}
})
bot.on("login", async (user: Contact) => {
console.info(`${user.name()} login!`)
})
bot.on("message", async (msg: Message) => {
console.log("接收到消息", msg.text())
})
bot.start()/**
* toUserId: wxid_xxx | xxx@chatroom
* payload: string | number | Message | Contact | FileBox | MiniProgram | UrlLink
*/)
const sendMessage = async (toUserId: string, payload: any): Promise<Message> => {
const toContact = await bot.Contact.load(toUserId);
const message = (await toContact.say(payload)) as Message;
return message;
};const message = await sendMessage("filehelper", "Hello World");const toRoom = await bot.Room.load("xxx@chatroom");
const atUserIdList = ["wxid_xxx", "wxid_yyy"];
const atUserList: Contact[] = [];
for (const userId of atUserIdList) {
const contact = await bot.Contact.load(userId);
atUserList.push(contact!);
}
const message = (await toRoom.say(payload, ...atUserList)) as Message;const contactCard = (await bot.Contact.find({ id: "wxid_" }))!;
await await sendMessage("filehelper", contactCard);// 图片大小建议不要超过 2 M
const imageFilePath = "/Users/.../image.jpeg";
const fileBox = FileBox.fromFile(imageFilePath);
// const fileBox = FileBox.fromUrl("https://.../image.jpeg");
const message = await sendMessage("filehelper", fileBox);// 语音文件为 silk 格式。silk 是 skype 开源的一款语音编解码器,被微信的语音文件所采用。
const voiceFilePath = "/Users/.../voice.slk"
const voiceLength = 6000; // 需要提供语音长度,单位为毫秒
const fileBox = FileBox.fromFile(voiceFilePath);
fileBox.mimeType = "audio/silk";
fileBox.metadata = {
voiceLength,
};
const message = await sendMessage("filehelper", fileBox);silk 转码工具: silk-v3-decoder
const videoFilePath = "/Users/.../video.mp4";
const fileBox = FileBox.fromFile(videoFilePath);
// const fileBox = FileBox.fromUrl("https://.../video.mp4");
const message = await sendMessage("filehelper", fileBox);const fileFilePath = "/Users/.../文件.pdf";
const fileBox = FileBox.fromFile(fileFilePath);
// const fileBox = FileBox.fromUrl("https://.../文件.pdf");
const message = await sendMessage("filehelper", fileBox);const urlLink = new UrlLink({
title: "Hello World! 你好世界!",
description: "This is description。描述可中文",
thumbnailUrl: "https://.../thumb.jpg",
url: "https://...",
});
const message = await sendMessage("filehelper", urlLink);// 封面图片为 cdn 图片
const miniProgramPayload: MiniProgramPayload = {
appid: "wx363a...",
description: "贝壳找房 - 真房源",
title: "美国白宫,10室8厅9卫,99999刀/月",
iconUrl: "http://mmbiz.qpic.cn/mmbiz_png/.../640?wx_fmt=png&wxfrom=200",
pagePath: "pages/home/home.html...",
shareId: "0_wx363afd5a1384b770_..._1615104758_0",
thumbKey: "84db921169862291...",
thumbUrl: "3051020100044a304802010002046296f57502033d14...",
username: "gh_8a51...@app"
}
// 封面图片为自定义外部图片(注意控制图片大小)
const miniProgramPayload: MiniProgramPayload = {
appid: "wx363a...",
description: "贝壳找房 - 真房源",
title: "美国白宫,10室8厅9卫,99999刀/月",
iconUrl: "http://mmbiz.qpic.cn/mmbiz_png/.../640?wx_fmt=png&wxfrom=200",
pagePath: "pages/home/home.html...",
shareId: "0_wx363afd5a1384b770_..._1615104758_0",
thumbKey: undefined,
thumbUrl: "https://.../thumb.jpeg", // 推荐在 200K 以内,比例 5:4,宽度不大于 1080px
username: "gh_8a51...@app",
};
const miniProgram = new MiniProgram(miniProgramPayload);
const message = await sendMessage("filehelper", miniProgram);这些参数就是收到的表情消息中的数据
const emoticonBox = FileBox.fromUrl("http://emoji.qpic.cn/wx_emoji/.../", `message-emotion.jpg`);
emoticonBox.mimeType = "emoticon";
emoticonBox.metadata = {
md5: "45229f68c17167f57ba9393004fcef98",
len: 12345,
type: 2,
gameext: "",
};
const message = await sendMessage("filehelper", emoticonBox);await message.recall()bot.on("message", async (message: Message) => {
switch (message.type()) {
// 文本消息
case MessageType.Text:
const text = message.text();
break;
// 图片消息
case MessageType.Image:
const messageImage = await message.toImage();
// 缩略图
const thumbImage = await messageImage.thumbnail();
const thumbImageData = await thumbImage.toBuffer();
// thumbImageData: 缩略图图片二进制数据
// 大图
const hdImage = await messageImage.hd();
const hdImageData = await hdImage.toBuffer();
// 大图图片二进制数据
// 原图
const artworkImage = await messageImage.artwork();
const artworkImageData = await artworkImage.toBuffer();
// artworkImageData: 原图图片二进制数据
break;
// 链接卡片消息
case MessageType.Url:
const urlLink: UrlLink = await message.toUrlLink();
// urlLink: 链接主要数据:包括 title,URL,description
const urlThumbImage = await message.toFileBox();
const urlThumbImageData = await urlThumbImage.toBuffer();
// urlThumbImageData: 链接的缩略图二进制数据
break;
// 小程序卡片消息
case MessageType.MiniProgram:
const miniProgram: MiniProgram = await message.toMiniProgram();
/*
miniProgram: 小程序卡片数据
{
appid: "wx363a...",
description: "贝壳找房 - 真房源",
title: "美国白宫,10室8厅9卫,99999刀/月",
iconUrl: "http://mmbiz.qpic.cn/mmbiz_png/.../640?wx_fmt=png&wxfrom=200",
pagePath: "pages/home/home.html...",
shareId: "0_wx363afd5a1384b770_..._1615104758_0",
thumbKey: "84db921169862291...",
thumbUrl: "3051020100044a304802010002046296f57502033d14...",
username: "gh_8a51...@app"
}
*/
break;
// 语音消息
case MessageType.Audio:
const audioFileBox = await message.toFileBox();
const audioData: Buffer = await audioFileBox.toBuffer();
// audioData: silk 格式的语音文件二进制数据
break;
// 视频消息
case MessageType.Video:
const videoFileBox = await message.toFileBox();
const videoData: Buffer = await videoFileBox.toBuffer();
// videoData: 视频文件二进制数
break;
// 动图表情消息
case MessageType.Emoticon:
const emotionFile = await message.toFileBox();
const emotionData: Buffer = await emotionFile.toBuffer();
// emotionData: 动图 Gif文件 二进制数据
break;
// 文件消息
case MessageType.Attachment:
const attachFileBox = await message.toFileBox();
const attachData = await attachFileBox.toBuffer();
// attachData: 文件二进制数据
break;
// 其他消息
default:
break;
}
});// 所有联系人列表中
const allContactList = await bot.Contact.findAll();
// 获取你添加过的好友。和微信一样,不知道对方是否删除了你
const friendList = allContactList.filter(contact => contact.friend());const isFriend: boolean = contact.friend();const self = bot.userSelf();
// 获取
const oldName = self.name();
// 设置
const toName: string = "NEW NICK NAME"
await self.name(toName);const self = bot.userSelf();
const qrStr = await self.qrcode();
// 再用二维码生成工具将 qrStr 生成为二维码即可const self = bot.userSelf();
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.userSelf();
const selfAvatarFileBox: FileBox = await selfContact.avatar();
// 他人
const contact = (await bot.Contact.find({ id:"wxid_xxx" }))!;
const otherAvatarFileBox: FileBox = await contact.avatar();const contact = await bot.Contact.find("SomeOne")
if(contact){
const puppet = bot.puppet as PuppetSimplePad
puppet.deleteContact(contact.id)
}bot.on("friendship", async (friendship: 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: "SimplePad" });
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 = "SimplePad";
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: RoomInvitation) => {
await roomInvite.accept();
});bot.on("room-join", async (room: Room, inviteeList: Contact[], 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: Room, leaverList: Contact[], remover?: Contact, date?: Date) => {
log.info(
`on room leave: ${room.toString()}, leaverList: ${leaverList.map((l) => l.id)}, remover: ${
remover?.id
} ${date}`
);
});bot.on("room-topic", async (room: Room, newTopic: string, oldTopic: string, changer: Contact, date?: 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();