• 2023年最新 Nonobot2 制作QQ聊天机器人详细教程(每周更新中)


    协议端 go-cqhttp 安装

    使用 mirai 以及 MiraiGo 开发的 cqhttp golang 原生实现,并在 cqhttp 原版 的基础上做了部分修改和拓展。

    测试版下载地址:https://github.com/Mrs4s/go-cqhttp/releases

    正式版下载地址:https://github.com/Mrs4s/go-cqhttp/releases

    例如:宝塔 centos 系统服务器 Linux 版本

    go-cqhttp_linux_amd64.tar.gz	4.8 MB	Jun 27
    
    • 1

    window 版本 zip 解压
    在这里插入图片描述
    go-cqhttp 接口

    在 PowerShell 窗口进行运行:shift + 右击 进入 PowerShell 窗口运行

    Windows 标准启动方法
    双击 go-cqhttp_*.exe,根据提示生成运行脚本
    双击运行脚本
    
    • 1
    • 2
    • 3
    PS C:\Users\Administrator\Desktop\go-cqhttp_windows_amd64> .\go-cqhttp.exe
    未找到配置文件,正在为您生成配置文件中!
    请选择你需要的通信方式:
    > 0: HTTP通信
    > 1: 云函数服务
    > 2: 正向 Websocket 通信
    > 3: 反向 Websocket 通信
    请输入你需要的编号(0-9),可输入多个,同一编号也可输入多个(: 233)
    您的选择是: 3
    默认配置文件已生成,请修改 config.yml 后重新启动!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在当前目录生成 config.yml 配置文件

    HTTP API反向 HTTP POST正向 WebSocket反向 WebSocket

    go-cqhttp 性能

    在关闭数据库的情况下, 加载 25 个好友 128 个群运行 24 小时后内存使用为 10MB 左右. 开启数据库后内存使用将根据消息量增加 10-20MB , 如果系统内存小于 128M 建议关闭数据库使用。

    go-cqhttp 交互

    在 go-cqhttp 成功运行之后, 你就可以通过自己写的程序, 使用 HTTP 或者 WebSocket 与 go-cqhttp 进行通讯, 实现 QQ 机器人. 在这个过程中, 你的程序只需要把一些数据发送给 go-cqhttp, 关于 QQ 的通信协议, go-cqhttp 会帮你解决.

    你也可以将 go-cqhttp 部署在你的服务器上, 并加上验证, 这样, 你就可以在各个地方使用自己的程序连接到远程的 go-cqhttp.

    想要与 go-cqhttp 进行通信, 你可以使用专门为 go-cqhttp 开发的开源 SDK, 这是最好的选择. 不过你也可以直接使用实现 OneBot 协议的开源 SDK, 只是他们可能并不包含 go-cqhttp 中的某些 API 或者消息类型, 这或许会影响你的使用体验。

    跳过启动 5s 延时

    使用命令行参数 faststart即可跳过启动的五秒钟延时,例如

    # Windows
    .\go-cqhttp.exe -faststart
    
    • 1
    • 2

    go-cqhttp config.yml 配置文件

    CQ Code CQ 码

    CQ 码是指 CQ 中特殊消息类型的文本格式, 这是它的基本语法:

    CQ 码文档地址:https://docs.go-cqhttp.org/cqcode

    [CQ:类型,参数=,参数=]
    
    • 1

    在 QQ 中, 一个消息由多个部分构成, 例如一段文本, 一个图片, at 某人的一个部分. CQ 中定义了与这些消息相符的 CQ 码, 以方便用户使用。

    QSign 签名服务器

    对于qq机器人来说,最难过的就是因为腾讯风控,导致消息发不出去、qq小号被冻结。所以才有了签名服务,虽然可以解决部分账号的风控。但该冻结还是冻结!!!

    最新很不幸的消息:由于腾狗的脑瘫行为,QSign 已经被请喝茶了!!!

    Docker QSign 容器

    安装 Docker 版 go-cqhttp 的签名服务器容器

    docker run -d --restart=always --name qsign -p 5709:8080 -e ANDROID_ID={android_id} xzhouqd/qsign:8.9.63
    
    • 1

    案例例如:

    docker run -d --restart=always --name qsign -p 5709:8080 -e ANDROID_ID=ebefad01e3964c11 xzhouqd/qsign:8.9.63
    
    • 1

    android_id 这只需要在 go-cqhttp 的 device.json 里面

    在这里插入图片描述

    C:\Users\Administrator>docker run -d --restart=always --name qsign -p 5709:8080 -e ANDROID_ID=ebefad01e3964c11 xzhouqd/qsign:8.9.63
    Unable to find image 'xzhouqd/qsign:8.9.63' locally
    8.9.63: Pulling from xzhouqd/qsign
    
    • 1
    • 2
    • 3

    本机对接配置

    sign-server:'http://127.0.0.1:5709'
    
    • 1

    云服务器对接配置

    sign-server:'http://服务器ipv4ip:5709'
    
    • 1

    最后确认你的 docker 在运行 打开浏览器:网页显示 IAA

    http://localhost:【你的本地端口号】/
    
    • 1

    ffmpeg 安装

    如果想要在liunx端进行发送任意格式的视频或者音频,那么就需要借助ffmpeg音视频转换工具,在linux安装比在windows端安装过程要复杂,接下来就详细的介绍下。

    官网下载:http://ffmpeg.org/download.html
    在这里插入图片描述
    下载之后上传至Linux任意的文件夹(一般是home下)准备安装,首先解压安装包

    tar -xjvf ffmpeg-snapshot.tar.bz2
    
    • 1

    执行上述的命令,会在压缩包的同级目录下,生成解压后的文件夹。

    如果现在执行configure配置的话,可能会报如下的错误:
    在这里插入图片描述
    错误的意思是 yasm/nasm 包不存在或者很旧,可以使用–disable-yasm禁用这个选项编译,yasm是一款汇编器,并且是完全重写了nasm的汇编环境,接收nasm和gas语法,支持x86和amd64指令集,所以这里安装一下yasm即可。

    安装yasm过程介绍如下所示:

    官网下载:http://yasm.tortall.net/Download.html

    下载之后上传至Linux准备安装,首先解压安装包,然后依次进行如下的操作:

    tar -xvzf yasm-1.3.0.tar.gz
    cd yasm-1.3.0/
    ./configure
    make
    make install
    
    • 1
    • 2
    • 3
    • 4
    • 5

    编译参数都是默认的,直接安装到系统中即可。

    继续安装ffmpeg,接下来就是编译安装,配置环境变量操作

    安装成功之后继续回到ffmpeg解压后的目录,执行下面命令编译并安装

    ./configure --enable-shared --prefix=/usr/local/ffmpeg
    make
    make install
    
    • 1
    • 2
    • 3

    --prefix=[安装地址],make编译过程有点长,耐心等待。

    make install会把ffmpeg相关执行程序、头文件、lib库安装在/usr/local/ffmpeg/下 耐心等待完成之后执行。

    耐心等待完成之后执行:

    cd /usr/local/ffmpeg/
    
    • 1

    进入安装目录,查看一下发现有bin, include, lib, share这4个目录

    bin是ffmpeg主程序二进制目录
    include是C/C++头文件目录
    lib是编译好的库文件目录
    share是文档目录
    
    • 1
    • 2
    • 3
    • 4

    接下来cd 到 bin 目录:执行./ffmpeg -version,正常情况出现如下报错:原因是lib目录未加载到链接到系统库中。
    请添加图片描述
    系统ld目录列表在/etc/ld.so.conf中,打开文件,在底部插入/usr/local/ffmpeg/lib,之后保存并退出,然后执行 ldconfig 使配置生效,现在再次执行 ./ffmpeg -version 显示就正常了。

    第二种方式:系统ld目录列表在/etc/ld.so.conf中,打开文件会发现,里面引用了/etc/ld.so.conf.d/下面所有的.conf文件,比如mysql-x86_64.conf,创建一个文件并写入lib路径即可,执行命令: vim /etc/ld.so.conf.d/ffmpeg.conf,然后添加一行内容: /usr/local/ffmpeg/lib,然后执行 ldconfig 使配置生效,现在再次执行 ./ffmpeg -version 显示就正常了。
    在这里插入图片描述
    执行结果如下所示:
    请添加图片描述
    ffmpeg相关的库主要是以下7个

    libavutil:用于多媒体编程,主要包含安全合适的字符串操作函数、数学运算函数、随机数字生产器、数据结构、多媒体处理的相关函数(如对像素和采样格式的计数)等,但它不是libavcodec和libavformat所需的库代码;

    libavcodec、libavformat:有些视频文件格式(如AVI)没有指出应该使用哪种编码(如h.264)来解析音频和视频数据,它们只是按视频格式封装音视频数据,所以经常碰到打开视频文件只能听到声音而没有画面,则用libavformat来解析视频文件并将编码流分离出来,libavcodec对流进行解码;

    libavdevice:为一些常见的多媒体输入或输出设备提供了抓取和渲染的通用架构,并且很多输入和输出设备,如Video4Linux2, VfW, DShow, and ALSA;

    libavfilter:提供了一个通用规定音视频过滤架构,包括一些过滤器、源、汇(什么是源、汇,我也没搞清楚,待研究)

    libswscale:执行高度优化的图像缩放、色彩、像素格式转换操作

    libswresample:执行高度优化的音频重采样、重换算、样本格式转换操作

    在环境变量中添加ffmpeg

    为了在任何目录在都能使用ffmpeg,则需要在环境变量中添加,打开/etc/profile文件,添加新的环境变量,展示如下:
    在这里插入图片描述
    为了让服务器不重启就生效修改后的profile配置文件,执行source /etc/profile

    测试ffmpeg,转换视频格式,比如:将mp4格式转换成avi格式

    ffmpeg -i /home/apple.mp4 -acodec copy -vcodec copy /home/apple2.avi
    
    • 1

    安装 nonebot 环境

    NoneBot2 是一个现代、跨平台、可扩展的 Python 聊天机器人框架(下称 NoneBot),它基于 Python 的类型注解和异步优先特性(兼容同步),能够为你的需求实现提供便捷灵活的支持。同时,NoneBot 拥有大量的开发者为其开发插件,用户无需编写任何代码,仅需完成环境配置及插件安装,就可以正常使用 NoneBot。
    在这里插入图片描述

    脚手架安装(官方推荐)

    pip install nb-cli
    
    • 1

    NoneBot 基于 Python asyncio 编写,并在异步机制的基础上进行了一定程度的同步函数兼容。

    插件系统

    插件系统是 NoneBot 的核心,通过它可以实现机器人的模块化以及功能扩展,便于维护和管理。

    nonebot 撤回消息

    在 NoneBot 中,你可以使用 bot.finish() 方法来撤回发送的消息。该方法可以用在任何消息处理函数中。以下是一个示例代码:

    from nonebot import on_command, CommandSession, get_bot
    
    @on_command('撤回', aliases=['recall'])
    async def recall_message(session: CommandSession):
        # 获取 bot 对象
        bot = get_bot()
    
        # 获取原始消息
        message = session.ctx['message']
    
        # 撤回消息
        await bot.delete_msg(message['message_id'])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在上述代码中,我们定义了一个名为 recall_message 的命令处理函数,并将其绑定到了 撤回 和 recall 这两个命令别名。当用户发送这两个命令时,NoneBot 将会调用这个处理函数。

    在函数中,我们通过 get_bot() 方法获取了 bot 对象,在这个对象上调用 delete_msg() 方法来撤回消息。message['message_id'] 是原始消息的消息 ID,通过这个 ID 来指定要撤回的消息。

    需要注意的是,撤回消息的功能需要满足一些条件,比如消息必须是机器人自己发送的,并且距离发送时间不能超过一定的时限。具体的限制条件可以参考对应的聊天机器人平台文档。

    APScheduler 定时任务

    APScheduler (Advanced Python Scheduler) 是一个 Python 第三方库,其强大的定时任务功能被广泛应用于各个场景。在 NoneBot 中,定时任务作为一个额外功能,依赖于基于 APScheduler 开发的 nonebot-plugin-apscheduler 插件进行支持。

    安装插件

    nb plugin install nonebot-plugin-apscheduler
    
    • 1

    使用插件

    nonebot-plugin-apscheduler 本质上是对 APScheduler 进行了封装以适用于 NoneBot 开发,因此其使用方式与 APScheduler 本身并无显著区别。

    调度器

    由于 nonebot_plugin_apscheduler 作为插件,因此需要在使用前对其进行加载并导入其中的 scheduler 调度器来创建定时任务。

    from nonebot import require
    
    require("nonebot_plugin_apscheduler")
    
    from nonebot_plugin_apscheduler import scheduler
    
    @scheduler.scheduled_job("cron", hour=18, minute=35, second=40)
    async def timer_task():
        # 获取 bot 信息
        (bot, ) = nonebot.get_bots().values()
        msg = f"测试消息"
        await bot.send_group_msg(group_id=642122283, message=msg)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    读取 env 环境变量

    nonebot 项目目录有 .env 文件配置环境变量

    ENVIRONMENT=dev
    APSCHEDULER_AUTOSTART=true
    APSCHEDULER_CONFIG={"apscheduler.timezone": "Asia/Shanghai"}
    
    • 1
    • 2
    • 3

    加载环境变量

    import os
    from dotenv import load_dotenv
    load_dotenv()
    os.getenv("APSCHEDULER_AUTOSTART")
    
    • 1
    • 2
    • 3
    • 4

    读取 sender 群昵称

    通过 event 事件对象进行读取 sender 发送者信息

    @chat.handle()
    async def listen_chat(bot: Bot, event: GroupMessageEvent, state: T_State):
        sender = event.sender
        print(sender.nickname)
        await bot.call_api("send_group_message", group_id=642122283, message="测试信息")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    sender:user_id=1620444902 nickname=‘唤醒手腕’ sex=‘unknown’ age=0 card=‘’ area=‘’ level=‘’ role=‘member’ title=‘’

    发送 tts 语音消息

    from nonebot import on_command
    from nonebot.adapters.onebot.v11 import Bot, PrivateMessageEvent, Message
    from nonebot.typing import T_State
    
    msg = on_command(cmd="img")
    
    @msg.handle()
    async def chat_listener(bot: Bot, event: PrivateMessageEvent, state: T_State):
        tts = "[CQ:tts,text=这是一条测试消息]"
        await bot.send(event, Message(tts))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试效果

    在这里插入图片描述

    发送 img 图片资源

    MessageSegment 发送图片

    @msg.handle()
    async def chat_listener(bot: Bot, event: PrivateMessageEvent, state: T_State):
        print("img")
        await bot.call_api("send_private_msg", user_id=1620444902, message="hello")
        await bot.send(event, MessageSegment.image("https://q4.qlogo.cn/headimg_dl?dst_uin=1620444902&spec=640"))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解析 CQ 码 发送图片

    @msg.handle()
    async def chat_listener(bot: Bot, event: PrivateMessageEvent, state: T_State):
        print("img")
        await bot.call_api("send_private_msg", user_id=1620444902, message="hello")
        image = "[CQ:image,file=https://q4.qlogo.cn/headimg_dl?dst_uin=1620444902&spec=640,type=show,id=40004]"
        await bot.send(event, Message(image))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    会话控制 询问操作

    msg = on_command(cmd="test")
    
    @msg.handle()
    async def chat_listener(bot: Bot, event: PrivateMessageEvent, state: T_State):
        tts = "[CQ:tts,text=这是一条测试消息]"
        await bot.send(event, Message(tts))
    
    
    @msg.got(key="name", prompt="请告诉我你的名字?")
    async def got_listener(name: str = ArgPlainText()):
        await msg.send(f"你的名字是{name}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在上面的代码中,我们使用 got 事件响应器操作来向用户发送 prompt 消息,并等待用户的回复。用户的回复消息将会被作为 location 参数存储于事件响应器状态中。

    在这里插入图片描述

    会话轮询操作

    msg = on_command(cmd="test")
    
    @msg.handle()
    async def chat_listener(bot: Bot, event: PrivateMessageEvent, state: T_State):
        tts = "[CQ:tts,text=考考你的智商水平]"
        await bot.send(event, Message(tts))
    
    
    @msg.got(key="name", prompt="请猜猜我的名字?")
    async def got_listener(name: str = ArgPlainText()):
        if name == "边缘骇客":
            await msg.send(f"恭喜你回答正确!!!")
        else:
            await msg.reject("请重新继续猜猜?")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

  • 相关阅读:
    哪款护眼灯最适合孩子?分享真正适合孩子的护眼台灯品牌
    彻底清除Mac缓存数据的方法,这样清理Mac缓存数据太干净了
    说一下 TCP/IP 协议?以及每层的作用?
    vue分片上传视频并转换为m3u8文件并播放
    C ++ 学习之分文件 实现类
    怎样用一周时间研究 ChatGPT
    机器学习算法——集成学习4(Bagging)
    python如何用矩阵计算的方式,对两两元素进行自定义计算
    【SpringBoot学习】46、SpringBoot 集成 Uniapp 实现微信公众号授权登录
    RabbitMQ(八)【高级 - 过期时间 TTL】
  • 原文地址:https://blog.csdn.net/qq_47452807/article/details/132643336