2024 年最新使用 Wechaty 开源框架搭建部署微信机器人(微信群客服积极性检测案例)

news2025/1/16 20:19:41

项目需求概述

想要实现微信群机器人进行指定部分群进行定时检测,判断群是否存在指定管理员没有进行及时回复的消息,从而在群里发送提醒管理员进行回复。

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 桌面应用搭建(待更新···)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1569409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哈佛大学商业评论 --- 第三篇:真实世界中的增强现实

AR将全面融入公司发展战略&#xff01; AR将成为人类和机器之间的新接口&#xff01; AR将成为人类的关键技术之一&#xff01; 请将此文转发给您的老板&#xff01; --- 本文作者&#xff1a;Michael E.Porter和James E.Heppelmann 虽然物理世界是三维的&#xff0c;但大…

基于Java微信小程序的医院挂号小程序,附源码

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

intellij idea 使用git ,快速合并冲突

可以选择左边的远程分支上的代码&#xff0c;也可以选择右边的代码&#xff0c;而中间是合并的结果。 一个快速合并冲突的小技巧&#xff1a; 如果冲突比较多&#xff0c;想要快速合并冲突。也可以直接点击上图中 Apply non-conflicting changes 旁边的 All 。 这样 Idea 就会…

matlab的歧视:simulink不能使用stm32f4系列的ADC?

2023b的matlab&#xff0c;stm32f407芯片&#xff0c;运行内容Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Based Boards Using the Analog to Digital Converter Block to Support STMicroelectronics STM32 Processor Base…

Day79:服务攻防-中间件安全IISApacheTomcatNginx弱口令不安全配置CVE

目录 中间件-IIS-短文件&文件解析&蓝屏&写权限 HTTP.SYS&#xff08;CVE-2015-1635&#xff09;主要用作蓝屏破坏&#xff0c;跟权限不挂钩 IIS短文件(iis全版本都可能有这个问题) IIS文件解析 IIS写权限 中间件-Nginx-文件解析&目录穿越漏洞&CRLF …

6:算法基础--6.3:排序算法,6.4:算法策略

转上一节&#xff1a; http://t.csdnimg.cn/fr4I4http://t.csdnimg.cn/fr4I4 6.3&#xff1a;排序算法 考点1&#xff1a;排序算法的基本概念 1.排序的概念 稳定与不稳定排序 2.排序方法分类 插入类排序直接插入排序希尔排序交换类排序冒泡排序快速排序选择类排序简单选…

spring事务那些事

实际工作中迓会面临千奇百怪癿问题&#xff0c;看下面返个例子&#xff08;注意MySql数据库测试&#xff09;&#xff1a; //1.hello1Service 调用 hello2Service Transactional(propagation Propagation.REQUIRED,rollbackFor Exception.class) public void doUpdate() {//…

B/S架构SaaS模式 医院云HIS系统源码,自主研发,支持电子病历4级

B/S架构SaaS模式 医院云HIS系统源码&#xff0c;自主研发&#xff0c;支持电子病历4级 系统概述&#xff1a; 一款满足基层医院各类业务需要的云HIS系统。该系统能帮助基层医院完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查…

Centos-Linux安装部署MySQL-8.0

linux搭建mysql 1.使用系统的root账户 2.切换到 /usr/local 目录下 3.下载mysql wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.31-linux-glibc2.12-x86_64.tar.xz也可以直接在官方下载最新版本 官方下载 选择linux 4.解压mysql tar xvJf mysql-8.0.21-l…

一文介绍回归和分类的本质区别 !!

文章目录 前言 1、回归和分类的本质 &#xff08;1&#xff09;回归&#xff08;Regression&#xff09;的本质 &#xff08;2&#xff09;分类&#xff08;Classification&#xff09;的本质 2、回归和分类的原理 &#xff08;1&#xff09;回归&#xff08;Regression&#x…

Github 2024-04-04 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-04统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目5TypeScript项目2Go项目1Jupyter Notebook项目1Java项目1C++项目1非开发语言项目1Vue项目1编程面试大学:成为软件工程师的全面学习计…

【前端面试3+1】11 http和https有何不同及https的加密过程、数组有哪些方法及作用、tcp三次握手四次挥手、【分发饼干】

一、http和https有何不同&#xff1f;https的加密过程 1、不同&#xff1a; HTTP和HTTPS的主要区别在于安全性。HTTP是超文本传输协议&#xff0c;是一种用于传输数据的协议&#xff0c;但是传输的数据是明文的&#xff0c;容易被窃听和篡改。而HTTPS是在HTTP基础上加入了SSL/T…

QT----opencv4.8.0编译cuda版本,QTcreater使用

目录 1 编译opencv4.8.02 验证能否加载GPU cuda12.1 opencv4.8.0 vs2019 cmake3.29 1 编译opencv4.8.0 打开cmake&#xff0c;选择opencv480路径&#xff0c;build路径随意 点击configure后&#xff0c;选择这些选项&#xff0c;opencv_word&#xff0c;cuda全选&#xff0c;…

前端三剑客 —— CSS (第五节)

目录 内容回顾&#xff1a; 特殊样式 特殊样式 CSS变量 常见函数 倒影效果 页面布局 Table 布局&#xff08;了解即可&#xff09; DIVCSS布局 弹性布局 1&#xff09;不使用弹性布局&#xff0c;而是使用DIVCSS 2&#xff09;使用弹性布局实现导航菜单 内容回顾…

Paddle实现人脸对比

人脸对比 人脸对比&#xff0c;顾名思义&#xff0c;就是对比两个人脸的相似度。本文将用Paddle实现这一功能。 PS&#xff1a;作者肝了整整3天才稍微搞明白实现方法 数据集准备 这里使用百度AI Studio的开源数据集&#xff1a; 人脸数据_数据集-飞桨AI Studio星河社区 (b…

基于SSM的教材管理系统的设计与实现(论文+源码)_kaic

基于SSM的教材管理系统的设计与实现 摘 要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前学校对于教材信息的管理和控制&#xff0c;采用人工登记的方式保存相关数据&#xff0c;这种以…

Spring Boot 整合 RabbitMQ 实现延迟消息

关于 RabbitMQ 消息队列&#xff08;Message Queuing&#xff0c;简写为 MQ&#xff09;最初是为了解决金融行业的特定业务需求而产生的。慢慢的&#xff0c;MQ 被应用到了更多的领域&#xff0c;然而商业 MQ 高昂的价格让很多初创公司望而却步&#xff0c;于是 AMQP&#xff0…

人工智能改变教育:理解和在课堂上使用 ChatGPT 的指南

原文&#xff1a;Talking to Machines: The Fascinating Story of ChatGPT and AI Language Models 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 这本直言不讳、幽默风趣的指南充满了可操作的提示、技巧和策略&#xff0c;帮助你在业务中充分利用 ChatGPT 的优势。在…

【氮化镓】GaN SP-HEMT的栅极可靠性

概括总结&#xff1a; 本文研究了氮化镓&#xff08;GaN&#xff09;肖特基型p-栅高电子迁移率晶体管&#xff08;GaN SP-HEMT&#xff09;的栅极鲁棒性和可靠性&#xff0c;通过一种新的电路方法评估了在实际转换器中栅极电压&#xff08;VGS&#xff09;过冲波形的栅极电压应…

网络基础二——TCP可靠性实现机制补充

11.3.4确认应答机制 ​ 1.双方通信时要返回确认应答报文&#xff0c;保证对方发送的报文是有效的&#xff1b;尽管整个通信过程中无法保证数据全部可靠&#xff0c;但是可以保证单个方向发送的数据是可靠的&#xff1b; ​ 发送的报文要设置序号&#xff0c;如果是应答报文要…