Skip to content

四、开发插件

Soulter edited this page Dec 22, 2023 · 16 revisions

⚠ 欢迎进群322154837讨论

插件支持什么消息?

  • 支持发送一切类型的QQ消息(语音、文本、图片、At 等)
  • 支持获取QQ平台的消息对象

如何创建插件?

  • 为了方便管理,本项目的插件一律为 git 仓库,因此如果您需要开发插件,首先需要创建一个Git仓库
  • 仓库名:任意
  • main.py中主类名的要求:插件名+Plugin格式或者直接为Main,否则将不会导入。如"HelloWorldPlugin"。不区分大小写。
  • 插件主类中必须实现两个函数runinfo,且返回值满足规范。规范详情请看下面的helloworld插件例子
  • 仓库内容:必须包含一个main.py用于程序识别,且上点提到的主类需要在这个文件中。
  • 指令的帮助信息请写在仓库下的README.md中。
  • 指令的依赖库请写在requirements.txt

info函数里的插件名可以自定义。

如何开发插件?

下面有例子,请先看下面的例子。

这里做几点补充说明:

  1. qq_platform: QQ平台对象,可以通过调用qq_platform.send()直接发送消息。详见Helloworld插件示例。send()接收两个参数,第一个是message_obj或者qq群号(int类型),第二个是消息内容,可以是字符串也可以是消息链列表。可以通过这个功能+线程来实现自行触发消息、发送消息
  2. run函数返回的内容:第一个参数是一个bool对象,意思是否此条信息(所有的消息均会调用每一个载入的插件, 如果没有处理或者不想处理此信息, 则应返回False);第二个参数是一个Tuple类型的值,如果没有处理或者不想处理此信息, 则应设置为None。第1个参数为指令是否调用成功, 第2个参数为返回的消息文本或者gocq的消息链列表, 第3个参数为指令名称。其中,gocq的消息链列表值得一提,这是一个列表类型的值,最终QQ上的信息会完全按照此列表的顺序和内容呈现出来。列表的内容是消息的类型,如Plain、Image。下面列举几个常用的消息类型
  • Plain("Hello World!!")
  • Image.fromURL(url=xxxx), xxx为图片的链接
  • At(qq=message_obj.user_id)

开发后的插件如何使用?

  • 首先需要上传到github。切记符合上面提到的创建插件的格式要求
  • 然后使用指令plugin i 仓库地址进行导入。如plugin i https://github.com/Soulter/helloworld
  • 开发好的插件可以通过issue提交至此项目,我们会将其放至相应位置供用户安装

更快捷地开发:

https://github.com/Soulter/helloworld 使用这个模板仓库

例子:helloworld插件

本插件当接收到消息为helloworld,则会返回Hello World!!和一张图片

from nakuru.entities.components import *
from nakuru import (
    GroupMessage,
    FriendMessage
)
from botpy.message import Message, DirectMessage
from model.platform.qq import QQ
import time
from cores.qqbot.global_object import AstrMessageEvent

'''
注意改插件名噢!格式:XXXPlugin 或 Main
小提示:把此模板仓库 fork 之后 clone 到机器人文件夹下的 addons/plugins/ 目录下,然后用 Pycharm/VSC 等工具打开可获更棒的编程体验(自动补全等)
'''
class HelloWorldPlugin:
    """
    初始化函数, 可以选择直接pass
    """
    def __init__(self) -> None:
        print("hello, world!")

    """
    机器人程序会调用此函数。
    返回规范: bool: 插件是否响应该消息 (所有的消息均会调用每一个载入的插件, 如果不响应, 则应返回 False)
             Tuple: Non e或者长度为 3 的元组。如果不响应, 返回 None; 如果响应, 第 1 个参数为指令是否调用成功, 第 2 个参数为返回的消息链列表, 第 3 个参数为指令名称
    例子:一个名为"yuanshen"的插件;当接收到消息为“原神 可莉”, 如果不想要处理此消息,则返回False, None;如果想要处理,但是执行失败了,返回True, tuple([False, "请求失败。", "yuanshen"]) ;执行成功了,返回True, tuple([True, "结果文本", "yuanshen"])
    """
    def run(self, ame: AstrMessageEvent):
        if ame.message_str == "helloworld":
            return True, tuple([True, "Hello World!!", "helloworld"])
        else:
            return False, None

    """
    插件元信息。
    当用户输入 plugin v 插件名称 时,会调用此函数,返回帮助信息。
    返回参数要求(必填):dict{
        "name": str, # 插件名称
        "desc": str, # 插件简短描述
        "help": str, # 插件帮助信息
        "version": str, # 插件版本
        "author": str, # 插件作者
        "repo": str, # 插件仓库地址 [ 可选 ]
        "homepage": str, # 插件主页  [ 可选 ]
    }
    """        
    def info(self):
        return {
            "name": "helloworld",
            "desc": "测试插件",
            "help": "测试插件, 回复 helloworld 即可触发",
            "version": "v1.2",
            "author": "Soulter"
        }

AstrMessageEvent 类:

run 函数中的参数 ame 的类型是 AstrMessageEvent,其内容是:

    message_str: str # 纯消息字符串
    message_obj: Union[GroupMessage, FriendMessage, GuildMessage, NakuruGuildMessage] # 消息对象
    gocq_platform: QQ
    qq_sdk_platform: QQChan
    platform: str # `gocq` 或 `qqchan`
    role: str # `admin` 或 `member`
    global_object: GlobalObject # 一些公用数据

NakuruGuildMessage、NakuruGuildMember 类:

class NakuruGuildMember():
    tiny_id: int # 发送者识别号
    user_id: int # 发送者识别号
    title: str 
    nickname: str # 昵称
    role: int # 角色
    icon_url: str # 头像url

class NakuruGuildMessage():
    type: str = "GuildMessage"
    self_id: int # bot的qq号
    self_tiny_id: int # bot的qq号
    sub_type: str # 消息类型
    message_id: str # 消息id
    guild_id: int # 频道号 
    channel_id: int # 子频道号
    user_id: int # 发送者qq号
    message: list # 消息内容
    sender: NakuruGuildMember # 发送者信息
    raw_message: Message

NakuruGuildMessage 中的 Message 类:

这是 qq 机器人 sdk 的 Message 类。

image