2023年最新 wechaty 框架开发微信机器人详细教程说明(案例篇)

您所在的位置:网站首页 微信机器人是怎么弄的啊 2023年最新 wechaty 框架开发微信机器人详细教程说明(案例篇)

2023年最新 wechaty 框架开发微信机器人详细教程说明(案例篇)

2024-07-16 07:03| 来源: 网络整理| 查看: 265

1. 基础 API 教程概述

在使用 wechaty 相关 api 之前请大家先学习 wechaty 基础篇!!!

博主有话要说!!!

为什么要选择看博主的博文?因为 Wechaty 官方文档已经太久没有更新了,所以同学们学习 WeChaty 请使用博主的博客作为教程文档,博主都是自己研究测试整理出来的,所有的案例测试都是最新版。

基础篇:最新 2023 如何使用 wechaty 框架开发微信机器人详细教程(基础篇)

在这里插入图片描述

2. 图片二维码扫码登陆

配置微信机器人启动快捷脚本 npm run start

在 package.json 文件中,配置 "start": "node bot.js"

在这里插入图片描述

在 terminal 终端进行执行

PS C:\Users\Administrator\Desktop\HackerWaking\Wechaty-Project> npm run start > [email protected] start > node index.js

图片二维码扫码登陆

const { WechatyBuilder } = require('wechaty'); const qrcode = require('qrcode-terminal'); const bot = WechatyBuilder.build() bot.on('scan', (code, status) => { qrcode.generate(code, { small: true }); }) 3. 判断微信群消息

判断 message.room() 对象进行判断是否是群消息

bot.on('message', async message => { const room = message.room() if (room) { console.log(room) const talker = message.talker(); talker.say("hello, i got your message") } });

查询 message.room() 群名 topic 回复群消息 hello

bot.on('message', async message => { const room = message.room() if (room && await room.topic() == "testgroup") { room.say("hello") } }); 4. 接收图片消息保存

机器人 bot 监听消息判断是否是图片消息?

const fs = require('fs'); bot.on('message', async message => { if (message.type() == bot.Message.Type.Image) { const fileBox = await message.toFileBox() console.log(fileBox) console.log("Message.Type.Image") const ws = fs.createWriteStream(fileBox._name); ws.write(fileBox.buffer); } });

图片类型消息 fileBox 数据结构

FileBox { version: '1.5.5', _type: 4, _size: 115413, md5: undefined, mimeType: 'application/unknown', _mediaType: 'image/jpeg', _name: '6373249138066348739.jpg', _metadata: undefined, base64: undefined, remoteUrl: undefined, qrCode: undefined, uuid: undefined, buffer: , localPath: undefined, stream: undefined, headers: undefined }

bot.Message.Type 消息类型

MessageType { Unknown = 0, Attachment = 1, ### Attach(6), Audio = 2, ### Audio(1), Voice(34) Contact = 3, ### ShareCard(42) ChatHistory = 4, ### ChatHistory(19) Emoticon = 5, ### Sticker: Emoticon(15), Emoticon(47) Image = 6, ### Img(2), Image(3) Text = 7, ### Text(1) Location = 8, ### Location(48) MiniProgram = 9, ### MiniProgram(33) GroupNote = 10, ### GroupNote(53) Transfer = 11, ### Transfers(2000) RedEnvelope = 12, ### RedEnvelopes(2001) Recalled = 13, ### Recalled(10002) Url = 14, ### Url(5) Video = 15, ### Video(4), Video(43) Post = 16, ### Moment, Channel, Tweet, etc } 5. 微信群发送图片

官方 Wechaty 发送案例展示

import { FileBox } from 'wechaty' const fileBox = FileBox.fromFile('C:\Users\Administrator\Desktop\image.png') await bot.say(fileBox)

亲测存在报错!uncaughtException TypeError: Cannot read properties of undefined (reading ‘fromFile’)

可能是 wechaty 版本问题 >>> 解决方案:单独安装 file-box 模块包调用

npm i file-box

具体解决方案实现

const { FileBox } = require('file-box') const fileBox1 = FileBox.fromFile('C:\Users\Administrator\Desktop\image.png') await bot.say(fileBox1) const fileBox2 = FileBox.fromUrl('https://wechaty.js.org/img/icon.png') await bot.say(fileBox2) 函数说明FileBox.fromFile选择本地图片FileBox.fromUrl选择网络图片

例如:检测关键词回复图片

const { WechatyBuilder } = require('wechaty'); const { FileBox } = require('file-box') const qrcode = require('qrcode-terminal'); const path = require('path') const bot = WechatyBuilder.build() bot.on('scan', (code, status) => { qrcode.generate(code, { small: true }); }) bot.on('login', user => console.log(`User ${user} logged in`)) bot.on('message', async message => { const room = message.room() if (room && message.payload.type != 7) { return; } else { let msg = message.text() if (msg == "chicken") { await room.say("Chicken is too beautiful.") } if (msg == "ikun") { const fileBox = FileBox.fromFile(path.join(process.cwd(), "image.png")) await room.say(fileBox) } } }); bot.start();

真机演示展示

在这里插入图片描述

6. 音频处理工具

在这里插入图片描述

下载地址:https://github.com/BtbN/FFmpeg-Builds/releases

ffmpeg 工具 bin 目录

在这里插入图片描述

配置 ffmpeg/bin 系统环境变量

在这里插入图片描述

7. 接收语音消息保存

机器人 bot 监听消息判断是否是语音消息?

const fs = require('fs'); bot.on('message', async message => { if (message.type() == bot.Message.Type.Audio) { const fileBox = await message.toFileBox() console.log(fileBox) console.log("Message.Type.Audio") const ws = fs.createWriteStream(fileBox._name); ws.write(fileBox.stream); } });

语音类型消息 fileBox 数据结构

FileBox { version: '1.5.5', _type: 6, _size: undefined, md5: undefined, mimeType: 'application/unknown', _mediaType: 'audio/silk', _name: 'message-6741646316917598047-audio.sil', _metadata: { voiceLength: 1231 }, base64: undefined, remoteUrl: undefined, qrCode: undefined, uuid: undefined, buffer: undefined, localPath: undefined, stream: , headers: undefined }

接收保存类型:sil 文件

message-5316276040531231762-audio.sil

借助 ffmpeg 转换音频格式

const { exec } = require('child_process'); const silFilePath = 'message-5316276040531231762-audio.sil'; const mp3FilePath = 'message-5316276040531231762-audio.mp3'; const command = `ffmpeg -i ${silFilePath} ${mp3FilePath}`; exec(command, (error, stdout, stderr) => { if (error) { console.error(`Error: ${error.message}`); return; } console.log('Conversion successful!'); }); 8. 查询联系人信息

事件 ready 是指微信机器人登陆完成启动预备状态

bot.on('ready', () => { let contactName = "" bot.Contact.find(contactName).then(contact => { console.log(contact) }).catch(err => { console.log() }) })

联系人信息结构体

WechatifiedContactSelfImpl { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, id: '@80d60ed0fb7633cb0069de96f78718df80a0148618f1981b7fe3869f145a82d5', payload: { address: undefined, alias: '', avatar: '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1945142728&username=@80d60ed0fb7633cb0069de96f78718df80a0148618f1981b7fe3869f145a82d5&skey=@crypt_13d84e54_07d2f691525dadf043c467d1a3f4b23f', city: undefined, friend: false, gender: 1, id: '@80d60ed0fb7633cb0069de96f78718df80a0148618f1981b7fe3869f145a82d5', name: '一语中的', phone: [], province: undefined, signature: '唤醒手腕', star: false, weixin: undefined, type: 1 }, [Symbol(kCapture)]: false }

查询联系人并且发送消息

bot.on('ready', () => { let contactName = "" bot.Contact.find(contactName).then(contact => { contact.say("hello") }).catch(err => { console.log() }) }) 9. ChatGPT3.5 应用

特别注意:调用 chatGPT 3.5 需要注册获取 OPENAI_API_KEY

环境变量配置文件 .env 存储 OPENAI_API_KEY

OPENAI_API_KEY=【你的OPENAI_API_KEY】

配置 Openai 接口调用工具 openai.js

const dotenv = require('dotenv') const OpenAI = require('openai') dotenv.config() const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const getOpenAIResponse = async (input) => { const chatCompletion = await openai.chat.completions.create({ messages: [{ role: 'user', content: input }], model: 'gpt-3.5-turbo', }); return chatCompletion.choices[0].message.content } module.exports = { getOpenAIResponse }

配置需要开通服务的群列表 config.json

{ "group": [ "testgroup", "helloworld" ] }

微信机器人启动 bot.js

const { WechatyBuilder } = require('wechaty'); const qrcode = require('qrcode-terminal'); const { getOpenAIResponse } = require('./openai.js') const fs = require('fs'); const data = fs.readFileSync('config.json', 'utf8'); const config = JSON.parse(data); const bot = WechatyBuilder.build() bot.on('scan', (code, status) => { qrcode.generate(code, { small: true }); }) bot.on('login', user => console.log(`User ${user} logged in`)) bot.on('message', async message => { const room = message.room() if (room && config.group.includes(await room.topic())) { if (message.payload.type != 7) { room.say("Sorry, please input text."); return; } else { room.say(await getOpenAIResponse(message.text())) } } }); bot.start();

package.json 依赖模块版本

"dependencies": { "openai": "^4.16.1", "qrcode-terminal": "^0.12.0", "wechaty": "^1.20.2" }

案例视频展示

在这里插入图片描述

10. 开通 Pad-local 协议

默认免费 WEB 协议是不支持发送语音权限(只具有接收语音消息的权限)IPAD 协议支持

在这里插入图片描述

推荐开通 pad-local 协议(链接地址):http://pad-local.com/

TOKEN 购买完成

在这里插入图片描述

11. 创建 puppet 登陆

PuppetPadlocal 创建机器人

const { PuppetPadlocal } = require("wechaty-puppet-padlocal"); const { WechatyBuilder } = require('wechaty'); const puppet = new PuppetPadlocal({ token: "puppet_padlocal_xxxxxxxxxxxx" }); const bot = WechatyBuilder.build({ name: "wristwaking", puppet })

详细官方案例教程文档介绍:https://github.com/wechaty/puppet-padlocal/wiki/API-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3-(TypeScript-JavaScript)

手机端使用微信扫描登陆显示(登陆设备 iPad) 在这里插入图片描述 Node 控制台登陆扫描输出

Welcome to Wechaty PadLocal puppet! puppet-padlocal version: 1.20.1 adlocal-ts-client version: 0.5.3 13:26:41 INFO [PuppetPadlocal] start login with type: AutoLogin User Contact logged in

注意:通过 PadLocal 协议登陆具有自动登陆功能(扫码完二次登陆无需进行扫码)

INFO TestBot started 问题

如果运行 npm run bot.js 后,正常情况会提示扫码登录。如果一直卡在 INFO TestBot started,二维码没有出现。解决方案:检测本地网络是否能够正常上网?检测是否开启了全局的 VPN?检测是否设置了网络防火墙?

网络测试:测试和 PadLocal 服务器之间网络是否通畅?

ping gateway.pad-local.com

网络测试:测试和微信服务器之间网络是否通畅?

$ ping long.weixin.qq.com $ ping short.weixin.qq.com 12. ffmpeg 音频工具

在这里插入图片描述

下载地址:https://github.com/BtbN/FFmpeg-Builds/releases

ffmpeg 工具 bin 目录

在这里插入图片描述

配置 ffmpeg/bin 系统环境变量

在这里插入图片描述

13. 被动回复语音消息

借助 vhan 开源接口创建 MP3 语音音频

const fs = require('fs') const axios = require('axios') const path = require('path') let content = "唤醒手腕我喜欢你" axios({ method: 'get', url: `https://api.vvhan.com/api/song?txt=${content}`, responseType: 'stream', }) .then(async res => { await res.data.pipe(fs.createWriteStream(path.join(__dirname, 'content.mp3'))) }) .catch(err => { console.log(err); });

借助 ffmpeg 工具 和 silk_v3_encoder 工具 进行音频转换处理 sil 语音

在这里插入图片描述

GitHub silk-v3-decoder 工具资源地址:https://github.com/kn007/silk-v3-decoder

const { execSync } = require('child_process'); const mp3FilePath = 'content.mp3'; const silFilePath = 'output.sil'; execSync(`ffmpeg -i "${mp3FilePath}" -f s16le -ar 24000 -ac 1 -acodec pcm_s16le "temp.pcm"`); execSync(`silk_v3_encoder "temp.pcm" "${silFilePath}" -tencent`)

语音文件为 silk 格式。silk 是 skype 开源的一款语音编解码器,被微信的语音文件所采用。注意:文件后缀必须是 sil!

bot.on('message', async message => { if (message.type() == bot.Message.Type.Audio) { const voiceFilePath = "output.sil" const voiceLength = 2000; const fileBox = FileBox.fromFile(voiceFilePath); fileBox.metadata = { voiceLength }; await message.say(fileBox) } });

特别注意:被动回复语音消息 WEB 协议不支持(推荐采用 iPad 协议实现)

运行演示视频

在这里插入图片描述

14. 发送动态链接 bot.on('message', async message => { if (message.text() == "发送链接") { const urlLink = new bot.UrlLink({ title: "Hello World! 你好世界!", description: "This is description", thumbnailUrl: "http://q1.qlogo.cn/g?b=qq&nk=1620444902&s=100", url: "https://www.baidu.com", }); await message.say(urlLink) } });

动态链接配置说明

parmas说明案例title标题Hello World! 你好世界!description详细描述This is descriptionthumbnailUrl预览图http://q1.qlogo.cn/g?b=qq&nk=1620444902&s=100 (图片链接地址)url链接地址https://www.baidu.com(链接)

发送动态链接测试结果:

在这里插入图片描述

15. 自动通过加好友请求 bot.on("friendship", async friendship => { console.log(friendship) if (friendship.type() === FriendshipType.Receive) { await friendship.accept(); } });

WechatifiedFriendshipImpl 数据结构

WechatifiedFriendshipImpl { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, id: '6163475632946471959', payload: { contactId: 'wxid_njqktrcgap7822', hello: '我是子夜吴歌', id: '6163475632946471959', scene: 15, shareCardContactId: '', shareCardNickName: '', sourceContactId: '', sourceNickName: '', stranger: 'v3_020b3826fd0301000000000095b7279086b4b4000000501ea9a3dba12f95f6b60a0536a1adb6bca1de246eb2c79828d52b3f6f6fdbb0dcdf144ece9d5ef453bc87350909b183e109f57083da037301a1a492156c38faaa1792d953a18405e5034f1876@stranger', ticket: 'v4_000b708f0b0400000100000000003ce338ab64bfba5b2eab48d683651000000050ded0b020927e3c97896a09d47e6e9e44ac1aeaa3585259ed6edc2f83825b3d166d50e27fb7b44161a4427e52d47e03cb9920bf7ad004fed00c4754150d75b4969a5ffefc1e5e6ebe3612f3f52a147c7ffc2634859836c1586dcf74d0bdeac97c5b6b9224a6cee2acf97a3705a88ababfb21dfb2f0bddbc75@stranger', timestamp: 1703138888, type: 2 }, [Symbol(kCapture)]: false }

监听自动通过好友结果:

在这里插入图片描述 控制台输出结果

自动通过验证 16. 读取全部群信息

我们可以通过 bot.Room.findAll() 函数,进行获取当前账号所有群组信息。

bot.on('ready', async () => { const roomList = await bot.Room.findAll(); console.log(`Total ${roomList.length} rooms found`); })

测试结果:

Total 29 rooms found

特别注意:如果我们想要全部群信息,必须要等到微信机器人准备完成之后才能进行读取,否则结果可能为空。就是您必须在 ready 事件触发时候进行读取,在 login / scan 事件读取的话,群组数据将读取失败。

Room Impl 接口实现

WechatifiedRoomImpl { _events: [Object: null prototype] {}, _eventsCount: 0, _maxListeners: undefined, id: '@@af95d96d3c31bc8999708594b48c5f4d79660cc48285a17706e85be3b92e7b2a', payload: { adminIdList: [], avatar: '/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=0&username=@@af95d96d3c31bc8999708594b48c5f4d79660cc48285a17706e85be3b92e7b2a&skey=@crypt_13d84e54_8d83375971336cd46842d5667ee67649', id: '@@af95d96d3c31bc8999708594b48c5f4d79660cc48285a17706e85be3b92e7b2a', memberIdList: [ '@a01b4c748882b1f35b685428cded4ea6386437d974e348240d644c61c883f855', '@0209e75ea4788f781e241a1a2ac7936563a90d11f6c0dcc3f067035cb6d5dd91' ], topic: '雨落晴天, 一语中的' }, [Symbol(kCapture)]: false }

通过 Room 对象发送群消息

Promise say(textOrContactOrFileOrUrl, …mentionList) 在群内发消息,如果设置了 …mentionList 参数,机器人在群内发送消息的时候还会@这些联系人。

room.say("hello, good night!")

艾特群主进行发送消息

注意:一般来说群主是群成员列表中的第一个(通常不是最准确的方法)要注意艾特功能(即“@”某人)在微信的 Web 和 API 版本中可能有一些限制和特定的实现方式。

bot.on('ready', async () => { console.log("机器人开始运行!!!") let roomList = await bot.Room.findAll() for (let index = 0; index { console.log("机器人开始运行!!!") const contact = await bot.Contact.find({ name: "番茄土豆" }); console.log(contact) fileBox = await contact.avatar() const filePath = './番茄土豆的头像.jpg'; fs.writeFile(filePath, fileBox.buffer, 'binary', (err) => { if (err) { console.error(err); } else { console.log("save success!!!"); } }); await contact.say("我已经保存了您的头像!!!") })


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3