mhy_botsdk

package module
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 13, 2023 License: MIT Imports: 0 Imported by: 0

README

mhy_botsdk

Language License Go Codacy Badge

✨ 一款米哈游大别野机器人的 Go SDK✨

  • 基本完善所有事件和 API,并支持同时运行多个实例(支持同端口、同路径运行多个拥有不同监听器的机器人)
  • 特别针对消息类型事件,配有 OnCommand、Preprocessor、Reply、WaifForCommand 等拓展处理器
  • 具备 Plugins 模块,允许使用外部模块直接编写应用
  • 内置消息过滤器,自动过滤重复消息
  • 底层使用gin构建,允许加入自定义路由(内部机制处理同端口同路径等复杂情况),方便集成页面应用供机器人使用(并校验用户)
  • 支持http和ws的反向代理配置和使用,具体请参考example5

go version >= 1.18(要求来自gin

实例

请参阅examples

  • example1:简单的机器人,包含了消息处理器、指令处理器、事件监听器
  • example2:多机器人同时允许
  • example3:简单的插件结构
  • example4:机器人暂停当前消息处理链,等待用户输入(以简单的猜数字机器人为例子,修改bot id等机器人参数后可直接使用)
  • example5:基于反向代理的实例

实用工具

请参阅tools

由于官方文档与实际存在不少差异,目前并不能确保所有消息事件和 API 完全正确

Import

  • "github.com/GLGDLY/mhy_botsdk/bot":机器人基础模块,包含机器人实例、事件监听器、消息处理器等
  • "github.com/GLGDLY/mhy_botsdk/events":事件模块,包含所有事件的模型
  • "github.com/GLGDLY/mhy_botsdk/apis":API 模块,包含所有 API 的处理器
  • "github.com/GLGDLY/mhy_botsdk/api_models":API 模块,包含所有 API 的模型
  • "github.com/GLGDLY/mhy_botsdk/commands":指令模块,包含指令处理器
  • "github.com/GLGDLY/mhy_botsdk/plugins":插件模块,包含插件处理器
  • "github.com/GLGDLY/mhy_botsdk/utils":辅助工具模块,包含一些实用函数

简易使用

package main

import (
    "strings"

    bot_api_models "github.com/GLGDLY/mhy_botsdk/api_models"
    bot_base "github.com/GLGDLY/mhy_botsdk/bot"
    bot_commands "github.com/GLGDLY/mhy_botsdk/commands"
    bot_events "github.com/GLGDLY/mhy_botsdk/events"
)

// NewBot参数: id, secret, 路径, 端口
// 下方例子会监听 localhost:8888/ 获取消息
// 并验证事件的机器人ID是否符合
var bot = bot_base.NewBot("bot_id", "bot_secret", "bot_pubkey", "/", ":8888")

func msg_preprocessor(data bot_events.EventSendMessage) { // 借助preprocessor为所有消息记录log
    bot.Logger.Info("收到来自 " + data.Data.Nickname + " 的消息:" + data.GetContent(true))
}

func MyCommand1(data bot_events.EventSendMessage) {
    bot.Logger.Info("MyCommand1")
    reply, _ := bot_api_models.NewMsg(bot_api_models.MsgTypeImage)  // 创建图片类型的消息体

    // 设置图片消息内容
	reply.SetImage("https://webstatic.mihoyo.com/vila/bot/doc/message_api/img/text_case.jpg")
	bot.Logger.Info(data.ReplyCustomize(reply))

	// 设置本地图片消息内容
	resp, http_code, err := bot.Api.UploadFileImage(data.Robot.VillaId, "head.jpg")
	if err != nil {
		bot.Logger.Error(err)
		reply := fmt.Sprintf("上传图片失败,错误信息(%d):%v", http_code, err)
		bot.Logger.Info(data.Reply(reply))
		return
	}
	reply.SetImage(resp.Data.NewURL)
	bot.Logger.Info(data.ReplyCustomize(reply))
}

func MyCommand2(data bot_events.EventSendMessage) {
    bot.Logger.Info("MyCommand2")
    bot.Logger.Info(data.Reply(fmt.Sprintf("MyCommand2 <@%v> <@%v> <@everyone> <#%v>",
		data.Robot.Template.Id, data.Data.FromUserId, data.Data.RoomId))) // 使用内嵌格式发送文本消息,内嵌格式按顺序为:@机器人(自己)、@发送者、@全体、#跳转房间
}

func msg_handler(data bot_events.EventSendMessage) { // 最后触发监听器,一般用于确保任何消息都有回复
    bot.Logger.Info("default msg handler")
    reply, _ := bot_api_models.NewMsg(bot_api_models.MsgTypeText) // 创建文本类型的消息体
    if strings.Contains(data.GetContent(true), "hello") { // 判断消息内容是否包含 "hello"
        reply.SetText("Hello World!",
            bot_api_models.MsgEntityMentionUser{ // 为回复的消息加入@发送者的消息
                Text:   "@" + data.Data.Nickname,
                UserID: data.Data.FromUserId,
            },
            "\n",
        )
        reply.AppendText(bot_api_models.MsgEntityVillaRoomLink{ // 为回复的消息加入大别野房间链接
            Text:    "#跳转房间",
            VillaID: data.Robot.VillaId,
            RoomID:  data.Data.RoomId,
        })
        reply.AppendText(bot_api_models.MsgEntityMentionAll{
            Text: "@全体成员",
        })
        bot.Logger.Info(data.ReplyCustomize(reply))
    } else {
        reply.SetText("你好,我是机器人,你可以输入 hello 来和我",
            bot_api_models.MsgEntityMentionRobot{ // 艾特机器人
                Text:  "@" + data.Robot.Template.Name ,
                BotID: data.Robot.Template.Id,
            }, " 打招呼")
        bot.Logger.Info(data.ReplyCustomize(reply))
    }
}

func main() {
    bot.AddPreprocessor(msg_preprocessor)

    bot.AddOnCommand(bot_commands.OnCommand{
        Command:        []string{"MyCommand1", "hello world"}, // 命令匹配:包含 "MyCommand1" 或 "hello world" 的消息
        Listener:       MyCommand1, // 设置回调函数为 MyCommand1
        RequireAT:      true, // 是否需要 @ 机器人才能触发
        RequireAdmin:   false, // 是否需要管理员权限才能触发
        IsShortCircuit: true, // 是否短路,即触发后不再继续匹配后续指令和监听器
    })
    bot.AddOnCommand(bot_commands.OnCommand{
        Regex:          "/?MyCommand2", // 正则匹配:内容为 "MyCommand2" 或 "/MyCommand2" 的消息
        Listener:       MyCommand2,
        RequireAT:      true,
        RequireAdmin:   false,
        IsShortCircuit: true,
    })
    bot.AddListenerSendMessage(msg_handler)
    /* NewBot 创建一个机器人实例,bot_id 为机器人的id,bot_secret 为机器人的secret,path 为接收事件的路径(如"/"),addr 为接收事件的地址(如":8888");
     * 机器人实例创建后,需要调用 Run() 方法启动机器人;
     * 对于消息处理,可以通过 AddPreprocessor() 方法添加预处理器,通过 AddOnCommand() 方法添加命令处理器,通过 AddListener() 方法添加事件监听器;
     * 对于插件,可以通过 AddPlugin() 方法添加插件;
     * 整体消息处理的运行与短路顺序为: [main]预处理器 -> [插件]预处理器 -> [插件]令处理器 -> [main]命令处理器 -> [main]事件监听器;
     * 如以上例子,如输入"hello world",将会执行MyCommand1,然后短路,不执行msg_handler的"hello"指令;而如果输入"hello 123",则会执行msg_handler的"hello"指令 */

    bot_base.StartAll() // 开始运行所有机器人和 HTTP 服务器
}

消息结构

  • SDK 的事件类型模型存放在"github.com/GLGDLY/mhy_botsdk/events"中
  • 事件类型 EventType 分为 6 种 event:JoinVilla,SendMessage,CreateRobot,DeleteRobot,AddQuickEmoticon,AuditCallback
    • AddListener的注册监听器也相应分为了 6 种:AddListenerJoinVilla,AddListenerSendMessage,AddListenerCreateRobot,AddListenerDeleteRobot,AddListenerAddQuickEmoticon,AddListenerAuditCallback
  • 事件数据结构 Event 细分成 6 个子事件:EventJoinVilla,EventSendMessage,EventCreateRobot,EventDeleteRobot,EventAddQuickEmoticon,EventAuditCallback
    • 事件数据结构将作为参数传入注册的事件回调函数
  • 由于本 SDK 针对不同事件,设置了不同的消息监听器函数接口,我们得以减少官方事件数据中 extend_data 的“套娃”设计,事件的数据结构,原来的Event->extend_data->event_data->JoinVilla/SendMessage....将简化为Event->DataData下直接包含各个事件的扩展数据

API

  • API 基本遵从官方 API 的结构,但存在特例:

    • SendMessage(EventSendMessageReply为对其的包装器):传入string类型的参数,会自动解析其中的内嵌格式并转换为entity:

      • <@xxx>为艾特机器人或用户,<@everyone>为艾特全体,<#xxx>为跳转房间,<$xxx>为跳转连接
      • 艾特用户会自动获取用户昵称,跳转房间会自动获取房间名称;艾特机器人会显示文字“@机器人”,艾特全体会显示“@全体成员”,跳转连接会显示链接自身
    • SendMessageCustomize(EventSendMessageReplyCustomize为对其的包装器):最后一个 msg 参数要求使用"github.com/GLGDLY/mhy_botsdk/api_models"中的NewMsg构造并传入

      • NewMsg需要传入MsgTypeText, MsgTypeImage, MsgTypePost之一指定类型
      • NewMsg会返回一个MsgInputModel结构,其中包含仅限MsgTypeText的方法:AppendText, SetText, SetTextQuote;仅限MsgTypeImage的方法: SetImage;仅限MsgTypePost的方法:SetPost
      • 这种设计模式是为了分段式内部处理entities,方便用户无需执行配置消息 json 序列
    • Audit:最后一个参数要求传入"github.com/GLGDLY/mhy_botsdk/api_models"中的UserInputAudit结构体

      • 方便处理可选参数

简易插件编写

  • 插件的 OnCommand 回调函数会增加一个 AbstractBot 参数,以使用当前机器人的基础功能,如 API、Logger、WaitForCommand 等
  • 以下分为两个文件,其中plugin1.go为介绍插件的编写,my_bot.go为介绍加载插件

plugin1.go:编写插件

package plugin1

import (
    bot_api_models "github.com/GLGDLY/mhy_botsdk/api_models"
    bot_events "github.com/GLGDLY/mhy_botsdk/events"
    bot_plugins "github.com/GLGDLY/mhy_botsdk/plugins"
)

func command1(data bot_events.EventSendMessage, bot *bot_plugins.AbstractBot) {
    bot.Logger.Info("plugin1::command1")
    bot.Logger.Info(data.Reply("plugin1::command1"))
}

func command2(data bot_events.EventSendMessage, bot *bot_plugins.AbstractBot) {
    bot.Logger.Info("plugin1::command2")
    bot.Logger.Info(data.Reply("plugin1::command2"))
}

func init() {
    bot_plugins.RegisterPlugin( // 注册插件
        "plugin1", // 插件名
        &bot_plugins.Plugin{ // 插件内容
            OnCommand: []bot_plugins.OnCommand{
                {
                    Command:        []string{"command1"},
                    Listener:       command1,
                    RequireAT:      true,
                    RequireAdmin:   false,
                    IsShortCircuit: true,
                },
                {
                    Command:        []string{"command2"},
                    Listener:       command2,
                    RequireAT:      true,
                    RequireAdmin:   false,
                    IsShortCircuit: true,
                },
            },
        },
    )
}

my_bot.go

package main

import (
    bot_base "github.com/GLGDLY/mhy_botsdk/bot"
    _ "path_to_plugin1" // 使用import导入plugin1
)

// 创建NewBot时会自动加载import了的插件
var bot = bot_base.NewBot("bot_id", "bot_secret", "bot_pubkey", "/", ":8888")

func main() {
    bot.SetPluginsShortCircuitAffectMain(true) // 设置插件的短路是否影响main中注册的指令和消息处理器
    bot_base.StartAll() // 开始运行所有机器人和 HTTP 服务器
}

相关链接

Documentation

Index

Constants

View Source
const (
	VERSION       = "v0.5.2"
	VERSION_MAJOR = 0
	VERSION_MINOR = 5
	VERSION_PATCH = 2
)

Variables

This section is empty.

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL