微信小助手/小秘书 基于wechaty-puppet-padplus
需求
看到别人有微信机器人, 自己也想拥有一个,那就开发一个。 主要功能
-
自动通过好友验证
当有人添加机器人时,判断验证消息关键字后通过或直接通过
通过验证后自动回复并介绍机器人功能
-
私聊关键字回复
例如回复 加群 推送群列表
回复 群名 推送群聊邀请,
-
自动聊天
群聊中通过 @[机器人]xxx 或以娜美 开头 就可以和机器人聊天
私聊发送消息即可聊天
-
加入群聊自动欢迎
当新的小伙伴加入群聊后自动 @[新的小伙伴] 发一个文字欢迎
开源项目 wechaty-puppet-padplus
wechaty-puppet-padplus 同是 wechaty 团队基于 Node.js 开发,不同于 wechaty 基于微信 web 端,它是基于 iPad 协议。
对于不能使用网页版微信的用户非常友好。
- 使用这个包需要 Token 。
- 可以将JuziBOT Inc的工作人员(微信编号:botorange_yeah )添加为微信好友。添加后,您将收到一份审查表。如果您通过审查并愿意在Wechaty中写博客,则可以免费使用iPad协议(为期15天的免费Token)!
- 想要获取长期有效的免费token,那就参加所谓的开源激励计划,就是在15天后,需要提交一个MVP(最小可行化产品)的Github仓库,Wechaty会将其fork到社区中的同时,会提供一个长期免费Token。
说干就干
先上 源码
建项目装依赖
mkdir nami // 创建 nami 文件夹
cd nami
npm init -y
核心包
npm i wechaty wechaty-puppet-padplus
windows 下安装 wechaty-puppet-padplus 出错,如让配置 python 环境变量 或 找不到 Visual Studio 时。
可通过 admin 权限 打开 powershell 执行
npm i --global --production windows-build-tools
然后切换 node 版本 10.x 再次 执行
npm i wechaty-puppet-padplus
还需要用到qrcode-terminal这个包,作用就是将二维码输出在终端来供我们扫码登录
npm install qrcode-terminal
配置文件
所谓的配置文件就是一些常量。后期可以通过添加后台管理系统, 动态修改。
config.js
/*
* @Author: C
* @Date: 2020-03-08 16:31:25
* @Description: 配置项
*/
module.exports = {
// puppet_padplus Token
token: "puppet_padplus_your_token", // 换上你自己的 token
// 机器人名字
name: "Nami",
// 房间/群聊
room: {
// 管理群组列表
roomList: {
// 群名(用于展示,最好是群名,可随意) : 群id(这个可不能随意)
前端真有趣: "群id" // 先提前运行然后看群id
},
// 加入房间回复
roomJoinReply: `\n 你好,欢迎你的加入,请自觉遵守群规则,文明交流,最后,请向大家介绍你自己!`
},
// 私人
personal: {
// 好友验证自动通过关键字
addFriendKeywords: ["加群", "前端"],
// 是否开启加群
addRoom: true
},
task: {
taskName: '发送新闻',
roomId: '',
url: 'http://api.tianapi.com/internet/index?key=apikey&num=10',
time: '8:0:0', // /h/m/s
date: ''
}
}
入口 index.js
/*
* @Author: C
* @Date: 2020-03-08 16:31:25
* @Description: wechaty-puppet-padplus入口程序
*/
const { Wechaty } = require("wechaty") // Wechaty核心包
const { PuppetPadplus } = require("wechaty-puppet-padplus") // padplus协议包
const config = require("./config") // 配置文件
const onScan = require("./onScan") // 机器人需要扫描二维码时监听回调
const onRoomJoin = require("./onRoomJoin") // 加入房间监听回调
const onMessage = require("./message/index") // 消息监听回调
const onFriendShip = require("./onFriendShip") // 好友添加监听回调
// 初始化
const bot = new Wechaty({
puppet: new PuppetPadplus({
token: config.token
}),
name: config.name
})
// 接下来一段链式调用,监听,启动
bot
.on("scan", onScan) // 机器人需要扫描二维码时监听
.on("room-join", onRoomJoin) // 加入房间监听
.on("message", onMessage(bot)) // 消息监听 // 有些消息需要用到 wechaty 实例所以传入 bot
.on("friendship", onFriendShip) // 好友添加监听
.start()
message
逻辑比较多的就是 message 部分了,消息监听回调
首先对接聊天接口
安装依赖
npm install --save request
npm install --save urlencode
// node-request请求模块包
const request = require("request")
// 请求参数解码
const urlencode = require("urlencode")
/**
* @description 机器人请求接口 处理函数
* @param {String} info 发送文字
* @return {Promise} 相应内容
*/
function requestRobot(info) {
return new Promise((resolve, reject) => {
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
// 免费的接口,所以需要把机器人名字替换成为自己设置的机器人名字
send = send.replace(/Smile/g, name)
resolve(send)
} else {
if (res.code == 1010) {
resolve("老艾特我干啥,有姑娘让我约吗")
} else {
resolve("你说说说的什么,我怎么不知道")
}
}
} else {
resolve("你在说什么,我脑子有点短路诶!")
}
})
})
}
const { Message } = require("wechaty")
// 配置文件
const config = require("./config")
// 机器人名字
const name = config.name
// 管理群组列表
const roomList = config.room.roomList
// 消息监听回调
module.exports = bot => {
return async function onMessage(msg) {
// 判断消息来自自己,直接return
if (msg.self()) return
// 判断此消息类型是否为文本
if (msg.type() == Message.Type.Text) {
// 判断消息类型来自群聊
if (msg.room()) {
// 获取群聊
const room = await msg.room()
// 收到消息,提到自己
if (await msg.mentionSelf()) {
// 获取提到自己的名字
let self = await msg.to()
self = "@" + self.name()
// 获取消息内容,拿到整个消息文本,去掉 @+名字
let sendText = msg.text().replace(self, "")
// 请求机器人接口回复
let res = await requestRobot(sendText)
// 返回消息,并@来自人
room.say(res, msg.from())
return
}
// 收到消息,没有提到自己 忽略
} else {
// 回复信息是关键字 “加群”
if (await isAddRoom(msg)) return
// 回复信息是所管理的群聊名
if (await isRoomName(bot, msg)) return
// 请求机器人聊天接口
let res = await requestRobot(msg.text())
// 返回聊天接口内容
await msg.say(res)
}
} else {
console.log("消息不是文本!")
}
}
}
/**
* @description 回复信息是关键字 “加群” 处理函数
* @param {Object} msg 消息对象
* @return {Promise} true-是 false-不是
*/
async function isAddRoom(msg) {
// 关键字 加群 处理
if (msg.text() == "加群") {
let roomListName = Object.keys(roomList)
let info = `${name}当前管理群聊有${roomListName.length}个,回复群聊名即可加入哦\n\n`
roomListName.map(v => {
info += "【" + v + "】" + "\n"
})
msg.say(info)
return true
}
return false
}
/**
* @description 回复信息是所管理的群聊名 处理函数
* @param {Object} bot 实例对象
* @param {Object} msg 消息对象
* @return {Promise} true-是群聊 false-不是群聊
*/
async function isRoomName(bot, msg) {
// 回复信息为管理的群聊名
if (Object.keys(roomList).some(v => v == msg.text())) {
// 通过群聊id获取到该群聊实例
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
}
然后就可以本地启动试试了