项目需求概述
想要实现微信群机器人进行指定部分群进行定时检测,判断群是否存在指定管理员没有进行及时回复的消息,从而在群里发送提醒管理员进行回复。
Package.json 依赖
"dependencies": {
"moment": "^2.29.4",
"qrcode-terminal": "^0.12.0",
"wechaty": "^1.20.2"
}
初始化获取群信息
bot.on('ready', async () => {
const roomList = await bot.Room.findAll();
checkGroupList = []
for (let index = 0; index < roomList.length; index++) {
let room = roomList[index];
let groupTopic = await room.topic()
if (groups.includes(groupTopic)) {
let roomItem = {
topic: groupTopic,
obj: room,
time: null
}
checkGroupList.push(roomItem)
}
}
console.log(`Total ${roomList.length} rooms found`);
finishReadyState = true
console.log("开始定时检查任务")
startIntervalCheck()
})
roomItem 属性
{
topic: '唤醒手腕测试群',
obj: WechatifiedRoomImpl {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
id: '@@5ad6740d0133c831016bb1f56f1caf9e44eb68a0bbb7f7fbcfb1a9e93778751a',
payload: [Object],
[Symbol(kCapture)]: false
},
time: null
}
更新检查表时间状态
let updateCheckGroupTime = (groupTopic, time) => {
checkGroupList.forEach(roomItem => {
if (roomItem.topic == groupTopic) {
roomItem.time = time
}
})
}
消息事件监听数据
bot.on('message', async message => {
if (finishReadyState != true) { return }
let room = message.room()
if (!room) { return }
let groupTopic = await room.topic()
if (groups.includes(groupTopic)) {
if (message.payload.type != 7) {
return;
} else {
let talkerName = message.talker().payload.name;
if (contacts.includes(talkerName)) {
updateCheckGroupTime(groupTopic, null)
} else {
console.log('新消息提醒!!!')
updateCheckGroupTime(groupTopic, moment().format("YYYY-MM-DD HH:mm:ss"))
}
}
}
});
判断时间是否指定区间
时间配置
time.json
{
"startTime": "04:30",
"endTime": "09:30",
"duration": 20
}
判断时间是否指定区间
isTimeBetween.js
const moment = require('moment');
const fs = require("fs");
timeConfig = JSON.parse(fs.readFileSync('time.json').toString())
startTime = timeConfig.startTime
endTime = timeConfig.endTime
let isTimeBetween = (timeString, startTimeString = startTime, endTimeString = endTime) => {
const time = moment(timeString, 'HH:mm:ss');
const startTime = moment(startTimeString, 'HH:mm');
const endTime = moment(endTimeString, 'HH:mm');
if (!time.isValid() || !startTime.isValid() || !endTime.isValid()) {
return false;
}
return time.isBetween(startTime, endTime, null, '[]');
}
const timeString = '21:30:01';
const isBetween = isTimeTodayBetween(timeString, "19:00:00", "20:00:00");
console.log(isBetween)
module.exports = isTimeBetween
检查消息是否超时
检测时间字符串是否表示的时间在距离当前时间 X 分钟范围内。
isWithinMinutes.js
const moment = require('moment');
isWithinMinutes = (timeString, minutes) => {
const timeMoment = moment(timeString, 'YYYY-MM-DD HH:mm:ss');是'YYYY-MM-DD HH:mm:ss'
if (!timeMoment.isValid()) {
return false;
}
const nowMoment = moment();
const diffMinutes = nowMoment.diff(timeMoment, 'minutes');
return Math.abs(diffMinutes) <= minutes;
}
const timeString = '2023-03-15 12:30:00';
const X = 20;
const isWithinXMinutes = isWithinMinutes(timeString, X);
console.log(isWithinXMinutes);
module.exports = isWithinMinutes
配置定时检测任务
timeConfig = JSON.parse(fs.readFileSync('time.json').toString())
let duration = timeConfig.duration
let startIntervalCheck = () => {
setInterval(async () => {
if (!isTimeBetween(moment().format("HH:mm:ss"))) { return }
console.log("正在检测中···")
for (let index = 0; index < checkGroupList.length; index++) {
const room = checkGroupList[index];
if (room.time) {
if (!isWithinXminutes(room.time, duration)) {
await room.obj.say("Warning!!! 超时回复消息!!! 客服摸鱼警告!!!")
room.time = moment().format("YYYY-MM-DD HH:mm:ss")
}
}
}
}, 10000);
}
配置授权群组、授权客服
授权客服数据
contacts.json
[
{
"id": "38de7ca8-d95a-4617-953c-babdaf5e0e1f",
"content": "唤醒手腕"
},
{
"id": "37e20e96-32a1-4b33-bc4e-edd7a41217db",
"content": "夜雨星空"
}
]
授权群组数据
groups.json
[
{
"id": "1d4a26d8-a9b6-4759-a703-602254d92ad6",
"content": "测试1群"
},
{
"id": "3328a15a-cbb7-4042-9459-77e40f3164dd",
"content": "测试2群"
}
]
读取数据
let groups = []
const groupsData = JSON.parse(fs.readFileSync('groups.json', 'utf8'));
groupsData.forEach(item => { groups.push(item.content) });
console.log(`【获取授权群组】` + groups + '\n')
let contacts = []
const contactsData = JSON.parse(fs.readFileSync('contacts.json', 'utf8'));
contactsData.forEach(item => { contacts.push(item.content) });
console.log(`【获取监听客服】` + contacts + '\n')
详细完整源码 bot.js
源码目录结构
node_modules 模块包
package.json package 配置文件
bot.js 启动脚本(启动文件 node bot.js)
isTimeBetween.js 判断时间是否指定区间
isWithinXMinutes.js 检查消息是否超时脚本工具
groups.json 授权群组数据
contacts.json 授权客服数据
time.json 配置时间数据
启动脚本 bot.js
const { WechatyBuilder } = require('wechaty');
const qrcode = require('qrcode-terminal');
const fs = require('fs');
const moment = require('moment');
const isWithinXminutes = require('./isWithinXminutes');
const isTimeBetween = require('./isTimeBetween');
let finishReadyState = false
let checkGroupList = []
let updateCheckGroupTime = (groupTopic, time) => {
checkGroupList.forEach(roomItem => {
if (roomItem.topic == groupTopic) {
roomItem.time = time
}
})
}
timeConfig = JSON.parse(fs.readFileSync('time.json').toString())
let duration = timeConfig.duration
let startIntervalCheck = () => {
setInterval(async () => {
if (!isTimeBetween(moment().format("HH:mm:ss"))) { return }
console.log("正在检测中···")
for (let index = 0; index < checkGroupList.length; index++) {
const room = checkGroupList[index];
if (room.time) {
if (!isWithinXminutes(room.time, duration)) {
await room.obj.say("Warning!!! 超时回复消息!!! 客服摸鱼警告!!!")
room.time = moment().format("YYYY-MM-DD HH:mm:ss")
}
}
}
}, 10000);
}
let groups = []
const groupsData = JSON.parse(fs.readFileSync('groups.json', 'utf8'));
groupsData.forEach(item => { groups.push(item.content) });
console.log(`【获取授权群组】` + groups + '\n')
let contacts = []
const contactsData = JSON.parse(fs.readFileSync('contacts.json', 'utf8'));
contactsData.forEach(item => { contacts.push(item.content) });
console.log(`【获取监听客服】` + contacts + '\n')
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 => {
if (!isTimeBetween(moment().format("HH:mm:ss"))) { return }
if (finishReadyState != true) { return }
let room = message.room()
if (!room) { return }
let groupTopic = await room.topic()
if (groups.includes(groupTopic)) {
if (message.payload.type != 7) {
return;
} else {
let talkerName = message.talker().payload.name;
if (contacts.includes(talkerName)) {
updateCheckGroupTime(groupTopic, null)
} else {
console.log('新消息提醒!!!')
updateCheckGroupTime(groupTopic, moment().format("YYYY-MM-DD HH:mm:ss"))
}
}
}
});
bot.on('ready', async () => {
const roomList = await bot.Room.findAll();
checkGroupList = []
for (let index = 0; index < roomList.length; index++) {
let room = roomList[index];
let groupTopic = await room.topic()
if (groups.includes(groupTopic)) {
let roomItem = {
topic: groupTopic,
obj: room,
time: ""
}
checkGroupList.push(roomItem)
}
}
console.log(`Total ${roomList.length} rooms found`);
finishReadyState = true
console.log("开始定时检查任务")
startIntervalCheck()
})
bot.start();
Electron 搭建 UI 界面
客服管理界面
时间管理界面
关于 electron 桌面应用搭建(待更新···)