• 【NodeJs-5天学习】第三天实战篇④ ——QQ机器人,实现自动回复、重要提醒


    面向读者群体

    • ❤️ 电子物联网专业同学,想针对硬件功能构造简单的服务器,不需要学习专业的服务器开发知识 ❤️
    • ❤️ 业余爱好物联网开发者,有简单技术基础,想针对硬件功能构造简单的服务器❤️

    技术要求

    • HTMLCSSJavaScript基础更好,当然也没事,就直接运行实例代码学习

    专栏介绍

    • 通过简短5天时间的渐进式学习NodeJs,可以了解到基本的服务开发概念,同时可以学习到npm、内置核心API(FS文件系统操作、HTTP服务器、Express框架等等),最终能够完成基本的web开发,而且能够部署到公网访问。

    学习交流群

    • NodeJs物联网五天入门学习之旅(搜索:729040020

    🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请留言轰炸哦!及时修正!感谢支持!🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝

    1. 前言

    NodeJs能否实现一个QQ机器人,对于一些重复性的信息能够自动回复或者一些重要时刻做一些信息提醒?

    比如:

    • 在一个群组里面的时候,当有人@你要物联网学习资料的时候,可以直接回复发送出去,类似于公众号里面的自动回复
    • 对于一些重要的节日,能够给一些特别的朋友发送一些问候
    • 每天固定时间发送天气预报

    带着以上这些问题,来进入本篇的知识学习。

    学习QQ模块 oicq
    在这里插入图片描述

    2.实现思路

    在这里插入图片描述

    核心实现原理就是:

    • ① 在NodeJs服务器上搭建一个QQ客户端,这里使用OICQ模块来实现。因为是搭建客户端,QQ不允许多个地方同时登陆,所以一般手机上会被踢下线。建议群组机器人可以另外申请一个QQ号。
    • ② 让它实时去监听客户端上收到的所有消息(比如A好友发送过来的私聊消息、B好友发送过来的私聊消息、xxx群发送过来的群组消息)
    • ③ 核心业务处理:根据需求来回复信息,比如通过特定群组ID发送群消息实现群组自动回复,通过给特定用户(UID)发送私聊消息。基于这个模型可以进一步扩展自己的需求。

    所以核心学习还是在于了解OICQ模块。

    2.1 oicq模块

    2.1.1 安装模块

    npm install oicq --save
    在这里插入图片描述

    然后我们可以运行一个最简单的代码:

    const { createClient } = require("oicq")
    const account = 147258369 // 改为自己的qq号码
    const client = createClient(account)
    
    client.on("system.online", () => console.log("Logged in!"))
    client.on("message", e => {
      console.log(e)
      e.reply("hello world", true) //true表示引用对方的消息
    })
    
    client.on("system.login.qrcode", function (e) {
      //扫码后按回车登录
      process.stdin.once("data", () => {
        this.login()
      })
    }).login()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这时候会触发一个扫描二维码的操作,用手机QQ扫描一下,然后按下回车键即可。

    2.1.2 官方说明文档(必须看)

    官方文档也没有太多复杂内容,根据具体需求(私聊、群聊、好友等等)去翻阅即可。
    在这里插入图片描述
    大多数情况下我们关注Group、User、Events、消息体这几个,使用频率比较高,知道它们的意思即可(字面意思也很容易理解)。

    • 系统事件
      在这里插入图片描述
      在这里插入图片描述
    • 群组相关操作
      群。 notice.group 和 message.group 相关事件中含有此实例 ( e.group 访问)
      或者使用 client.pickGroup() 获得群实例。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
    • 私聊相关
      在这里插入图片描述
    2.1.3 常见API文档(重要)

    2.2 NodeJs服务器代码

    在这里插入图片描述
    整体代码不多,主要分为几块:

    • qq客户端监听
    • 私聊匹配词
    • 群聊匹配词
    • 提醒用户(暂未实现)
    2.2.1 qq客户端监听
    // 库说明: https://github.com/takayama-lily/oicq
    
    const {createClient} = require("oicq");
    const uin = xxxxxxx; // qq账号
    const bot = createClient(uin)
    const remindPrivate = require('./config/remind/remind_private.js')
    const responseGroup = require('./config/response/response_group.js')
    const responsePrivate = require('./config/response/response_private.js')
    
    bot.on("system.login.captcha", ()=>{
      process.stdin.once("data", input=>{
        bot.captchaLogin(input);
      });
    });
    
    bot.on("system.online", ()=>console.log("服务器:QQ上线"));
    // system.offline.kickoff 被其他客户端踢下线, 默认不自动重登(见相关配置 kickoff)
    bot.on("system.offline.kickoff", ()=>console.log("服务器踢下线"));
    // system.offline.network 网络不通畅或服务器繁忙, 默认自动重登(见相关配置 reconn_interval)
    bot.on("system.offline.network", ()=>console.log("网络错误导致下线"));
    
    bot.on("message.group", data=>{
        console.log('服务器:收到一条群组消息')
        console.log(data)
        var groupName = data.group_name
        var senderName = data.sender.nickname
        var message = data.raw_message
        console.log(`[${groupName}]${senderName}: ${message}`)
    
        var reply = responseGroup.getReply(message)
        if (reply) {
          bot.sendGroupMsg(data.group_id, reply);
        }
    });
    
    bot.on("message.private", data=>{
        console.log('服务器:收到一条私聊消息')
        // console.log(data);
        var senderName = data.sender.nickname
        var message = data.raw_message
        console.log(`[私聊]${senderName}: ${message}`)
        var reply = responsePrivate.getReply(message)
        if (reply) {
          bot.sendPrivateMsg(data.user_id, reply)
        }
    });
    
    bot.on("message.discuss", data=>{
        console.log('服务器:收到一条讨论组消息')
        console.log(`[${data.group_name}]${data.sender.nickname}: ${data.raw_message}`)
    });
    
    // bot.on("message", data=>{
    //   console.log(data);
    // //   if (data.group_id > 0)
    // //     bot.sendGroupMsg(data.group_id, "谁说只能回复hello");
    // //   else
    // //     bot.sendPrivateMsg(data.user_id, "hello");
    // });
    
    const psd = "xxxxxx";  // 填上密码
    bot.login(psd);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    这里需要改一下自己的qq账号和密码。

    在这里插入代码片
    
    • 1

    同时它主要是:

    • 监听私聊消息(message.private
    • 监听群聊消息(message.group

    注意:这里登陆会把自己客户端的账号踢下线

    2.2.2 私聊匹配词

    在这里插入图片描述

    就是当收到的私聊消息满足这些匹配词的时候自动回复给对方。

    • response_private.json 配置文件(这里可以继续添加新的)
    [{
    	"match": "你好",
    	"reply": "你好"
    }, {
    	"match": "鸟哥",
    	"reply": "怎么了?"
    }, {
    	"match": "博哥",
    	"reply": "怎么了?"
    }, {
    	"match": "菜鸟哥",
    	"reply": "怎么了?"
    }, {
    	"match": "菜鸟哥你好",
    	"reply": "你好"
    }, {
    	"match": "博哥你好",
    	"reply": "你好"
    }, {
    	"match": "博哥你做什么工作",
    	"reply": "偏软件方向工作"
    }]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • response_private.js 匹配判断
    const fs = require('fs')
    
    // 设备配置信息,需要通过配置校验才会通过
    var fileName = `${__dirname}/response_private.json`;
    var config = JSON.parse(fs.readFileSync(fileName));
    var matchToReplyMap = new Map()
    config.forEach(element => {
      var match = element.match
      var reply = element.reply
      if (matchToReplyMap.has(match)) {
        throw console.error('response_private 配置文件出现重复ID,请检查!' + uid);
      }
      matchToReplyMap.set(match, reply)
    })
    
    console.log("response_private 配置信息:")
    console.log(matchToReplyMap)
    
    function getReply(content) {
      var result = null
      matchToReplyMap.forEach((reply,match)=>{
        if(content.indexOf(match) > -1) {
          result = reply
        }
      })
    
       return result
    }
    
    module.exports = {
      getReply
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    现在的匹配逻辑比较简单,有兴趣的同学可以进一步优化。

    2.2.3 群聊匹配词

    在这里插入图片描述
    就是当收到的群聊消息满足这些匹配词的时候自动回复给到对应群。

    • response_group.json 配置文件(这里可以继续添加新的)
    [{
    	"match": "博哥你好",
    	"reply": "你好"
    },{
    	"match": "鸟哥",
    	"reply": "怎么了?"
    },{
    	"match": "博哥",
    	"reply": "怎么了?"
    },{
    	"match": "菜鸟哥",
    	"reply": "怎么了?"
    },{
    	"match": "博哥你做什么工作",
    	"reply": "偏软件方向工作"
    },{
    	"match": "@8266学习请Csdn搜单片机菜鸟哥",
    	"reply": "博哥有点忙,有事先留言"
    },{
    	"match": "@单片机菜鸟",
    	"reply": "博哥有点忙,有事先留言"
    }]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • response_group.js 匹配判断
    const fs = require('fs')
    
    // 设备配置信息,需要通过配置校验才会通过
    var fileName = `${__dirname}/response_group.json`;
    var config = JSON.parse(fs.readFileSync(fileName));
    var matchToReplyMap = new Map()
    config.forEach(element => {
      var match = element.match
      var reply = element.reply
      if (matchToReplyMap.has(match)) {
        throw console.error('response_group 配置文件出现重复ID,请检查!' + uid);
      }
      matchToReplyMap.set(match, reply)
    })
    
    console.log("response_group 配置信息:")
    console.log(matchToReplyMap)
    
    function getReply(content) {
      var result = null
      if (content.indexOf('来自群管理员') > -1 || content.indexOf('Q群管家') > -1) {
        return result
      }
      matchToReplyMap.forEach((reply,match)=>{
        if(content.indexOf(match) > -1) {
          result = reply
        }
      })
    
       return result
    }
    
    module.exports = {
      getReply
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    现在的匹配逻辑比较简单,有兴趣的同学可以进一步优化。

    2.3 测试效果

    在这里插入图片描述

    • 测试1:私聊,测试以上的关键字
      在这里插入图片描述
      在这里插入图片描述
    • 测试2:群聊,测试以上的关键字
      在这里插入图片描述
      在这里插入图片描述

    3.总结

    篇④结合ESP8266来开发qq机器人应用——自动回复某些特定匹配信息。麻雀虽小五脏俱全,初学者需要理解oicq并加以实际应用。

  • 相关阅读:
    在进行自动化测试,遇到验证码的问题,怎么办?
    如何修改 GUI 默认 shader 实现自定义 UI 表现
    象棋中的马跳步问题
    sphinx 部分高级功能汇总说明
    docker部署的redis集群 添加节点(扩容)
    狂神说-Springboot的入门初探
    小程序picker-view 初始值设置的坑
    【C语言】指针初阶
    Jenkins 配置邮件通知(腾讯企业邮箱)
    css前端入门(第二天)背景
  • 原文地址:https://blog.csdn.net/weixin_44614230/article/details/126845841