如何开发 - Strelizia02/AngelinaBot GitHub Wiki

AngelinaFrame简介

AngelinaFrame是一个基于SpringBoot的QQ机器人开发框架,旨在与简化开发流程。将登录、收发消息等操作融入框架,开发人员只需专注于实际的业务代码。

当前已集成:Mirai(QQ群聊框架),QQChanel(QQ频道官方接口)

框架使用协议

AngelinaFrame包含了一些对于Bot的个人理解,使用AngelinaFrame框架,即视为同意并遵从AngelinaFrame的定义。

1.唤起

群聊Bot在设计自身功能之前,首先应做到“不打扰”。Bot不应该打扰群友的正常群聊,因此AngelinaFrame规定:必须以Bot的名称开头才能唤起Bot。

2.账号池

AngelinaFrame中维护了一个账号池,映射了Bot的所有账号 -> 服务的群聊。

通过账号池,AngelinaFrame保证:

若一个群中有多个Bot账号,接受唤起命令时,有且仅有一个账号进行回复,不会出现多账号同时回复的情况。

3.消息速率控制

10秒内超过3条消息,不会调用功能,并提示超出速率;超过5条消息不再回复。防止恶意刷屏或多个bot互相循环调用。

4.数据中心

AngelinaCenter是AngelinaBot的数据中心,用于统计每个Bot的调用次数、在线情况,并提供数据更新等服务(数据更新指AngelinaBot的游戏数据更新)。

AngelinaFrame默认对接AngelinaCenter以下接口:

4.1登录心跳

每3分钟向AngelinaCenter发送心跳消息,心跳内容包括:QQ账号,在线情况。不会发送密码等隐私信息。此数据用于统计AngelinaFrame的登录情况。

4.2数据统计

每24小时向AngelinaCenter发送数据统计,统计内容包括:接受消息总数、发送消息总数、各个功能调用总数、内存占用。此数据用于统计AngelinaFrame的使用情况。

快速开发

引入

采用Maven引入,具体版本请自行选择,此处以2.0.1版本示例。

框架中已包含了Mirai、SpringBoot和Mybatis等, 无需额外引入。因Mirai是Kotlin项目,需要引入kotlin相关依赖。

        <dependency>
            <groupId>top.angelina-bot</groupId>
            <artifactId>angelinaFrame</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-core</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-core-jvm</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

启动类

package top.strelitzia;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication(scanBasePackages = {"top.angelinaBot", "top.strelitzia"})
@EnableSwagger2
@EnableScheduling
@EnableAsync
public class AngelinaApplication {
    public static void main(String[] args) {
        SpringApplication.run(AngelinaApplication.class, args);
    }
}

逻辑代码示例

@Service//由Spring容器对实例进行托管
public class HelloWorldService {
    @AngelinaGroup(keyWords = {"Hello", "hello"})//当QQ群聊中呼叫【洁哥Hello】或【洁哥hello】时,调用该方法
    public ReplayInfo helloWorld(MessageInfo messageInfo) {
        ReplayInfo replayInfo = new ReplayInfo(messageInfo);
        replayInfo.setReplayMessage("Angelina Hello World!");
        return replayInfo;//将你的返回结果封装成ReplayInfo
    }
}

详细的Bot示例请参考AngelinaBot

AngelinaFrame提供的Api

基础消息类

接收到的消息MessageInfo

字段 描述 类型
loginQq 收到账号的QQ(频道ID) String
text 原始消息文字内容 String
keyword 触发到的关键字 String
args 将文字消息按空格切分 List
qq 发送人的QQ(频道ID) String
name 发送人昵称 String
groupId 消息群号(子频道号) String
imgUrlList 消息中图片的url List
imgTypeList Mirai中对应的图片类型 List
isCallMe 判断是否在呼叫Bot Boolean
atQQList 艾特了哪些人 List
time 消息时间戳 Integer
eventString 消息缩略字符串(用于缩小日志) String
event 接收到的事件 EventEnum
isReplay 是否要回复消息 Boolean
userAdmin 用户拥有的最大权限 PermissionEnum
frame 哪个框架接收到的消息 String

MessageInfo由框架进行构造,用户无需处理。

发送的消息ReplayInfo

字段 描述 类型 是否必填
loginQq 实际发送消息的QQ String 私聊必填
qq 发送目标的QQ String 私聊必填
name 发送目标昵称 String 选填
groupId 发送给哪些群 List 群聊必须保证size > 1
replayMessage 回复消息的文字 String 选填
replayImg 回复消息的图片 List 选填
mp3 语音文件 File 选填
kick 是否踢出去 Boolean 选填
muted 禁言多少分钟(为null是不操作,为0是解除禁言) Integer 选填
isNudged 是否戳一戳他 String 选填
frame 使用哪个框架发送 String 不建议修改

特殊重载:

为方便开发者构造ReplayInfo,除基础的getter/setter/constructor外,额外提供了其他重载。

方法名 参数 描述
ReplayInfo MessageInfo 构造函数的重载,通过直接以MessageInfo作为入参,能够自动将qq,LoginQQ,name,groupId进行赋值。推荐使用本构造方法,后续只需设计回复的内容即可使用。
setGroupId String 因ReplayInfo要满足群发的功能,因此GroupId的类型是List,重载set方法,直接将GroupId添加到List中。
setGroupId Collection 如上,是一个批量添加的重载。
setReplayImg BufferedImage 为消息中添加一个BufferImage类型的图片
setReplayImg File 为消息中添加一个本地文件图片
setReplayImg String 为消息中添加一个网络图片的URL

基础api

任何一个Angelina注解修饰的方法,都应以MessageInfo作为唯一参数,ReplayInfo作为返回值。AngelinaFrame会在程序启动时对所有注解方法进行检查,不符合要求的话会报错中止程序。

1.@AngelinaGroup()

参数 描述 入参类型
keyWords 触发方法的关键字 String[]
dHash 触发方法的图片(性能开销大,慎用) String[]
description 功能描述 String
author 作者(默认是我) String
funcClass 功能分类 FunctionType
permission 最低运行权限 PermissionEnum

2.@AngelinaFriend()

参数 描述 入参类型
keyWords 触发方法的关键字 String[]
description 功能描述 String

3.@AngelinaEvent()

参数 描述 入参类型
event 触发方法的事件 EventEnum
description 功能描述 String

高级自定义

AngelinaListener

以上注解只能够满足一条消息,一次回复,且必须以BotName为开头才能触发。

某些场景下携带BotName过于繁琐,并且需要监听某些特定消息,注解已经不能满足当前的要求,因此提供Listener方法。

AngelinaListener的逻辑:将该线程挂起,监听到某群的某一种消息后,唤起线程并将该消息返回。

举例:

答题功能,当用户调用功能@AngelinaGroup(keyWords = {"答题"})后,需要监听用户的答案。此时用户只需回答"ABCD"即可,无需再额外增加前缀。代码如下:

@AngelinaGroup(keyWords = {"答题"})
public ReplayInfo questions(MessageInfo messageInfo) {
    ReplayInfo replayInfo = new ReplayInfo(messageInfo);
    //TODO 此处要发送题目

    //TODO 这里监听用户的回答
    AngelinaListener angelinaListener = new AngelinaListener() {
       @Override
       public boolean callback(MessageInfo message) {
            //只监听文字为ABCD的消息
            return message.getText().equals("A") || message.getText().equals("B") ||message.getText().equals("C") ||message.getText().equals("D");
        }
    };
    //监听哪个群的消息
    angelinaListener.setGroupId(messageInfo.getGroupId());
    //多少秒超时
    angelinaListener.setSecond (120);
    //如果超时,返回null,如果未超时,则返回监听到的消息
    MessageInfo recall = AngelinaEventSource.waiter(angelinaListener).getMessageInfo();
    //TODO 自行判断答案是否正确;
    if (recall == null) {
        replayInfo.setMessage("超时");
        return replayInfo;
    }

    if (recall.getText.equals("正确")) {
        replayInfo.setMessage("答对了");
    } else {
        replayInfo.setMessage("答错了");
    }
    return replayInfo;
}

默认功能的重写

可能某些框架自带的默认功能并不符合开发者的需求,需要对功能进行重写,可以利用SpringBoot注入Bean的方式进行重写。

以重写菜单方法为例:

创建一个你的菜单Service类,继承菜单的Service。

注:该重写类不可以被@Service修饰

public class TestService extends FunctionListService{

    @AngelinaGroup(keyWords = {"菜单", "功能", "会什么"})
    public ReplayGroupInfo getFunctionListService(MessageInfo messageInfo) {
        ReplayInfo replayInfo = new ReplayGroupInfo(messageInfo);
        log.info("TestService extend FunctionListService");
        //TODO 以下是你自定义的菜单业务逻辑

        return replayInfo ;
    }
}

然后在config目录中新增一个AngelinaBeanConfig,强制将你的类实例注入到菜单类中。

@Component
public class AngelinaBeanConfig {

    /**
     * 当用户需要重写框架中的某段代码时,重写代码后通过@Bean注入覆盖掉原有实例
     */
    @Bean("functionListService")
    public TestService getFunctionListService() {
        return new TestService();
    }
}

此时FunctionListService的实例就被替换为你重写的类实例,AngelinaFrame框架的Service就被覆盖掉,因此当你需要关闭默认功能时,创建一个空类并继承注入即可。

可以被重写的默认功能

功能 Service BeanName
菜单 FunctionListService functionListService
功能开关 FunctionSwitchService functionSwitchService
关于 AboutService aboutService

** 其他功能不推荐重写**

自定义init

有一些逻辑,可能需要在程序启动时就要允许,而AngelinaFrame已经实现了SpringBoot的SmartInitializingSingleton,因此对外提供自定义init接口,用户实现该接口,即可将逻辑添加至程序启动时。

@Service
public class InitAngelinaService implements top.angelinaBot.service.InitAngelinaService {
    @Override
    public void init() {
        //TODO 这里是你的启动时自定义逻辑
    }
}

其他接口

TextLine()

TextLine是一个文字转图片的方法,当文字过多的时候,容易引起风控,这种情况下,将文字转换为图片发送可以避免风控。 Java使用Graphics画图操作有一点点冗杂,AngelinaFrame封装了一个TextLine模型类,可以基于文字生成图片。

TextLine类似于txt的操作,提供以下几个Api

  • 构造函数,包含有参构造和无参构造,参数maxWidth为每行允许的最多文字数量,无参构造时默认为20字符。
    public TextLine()
    public TextLine(int maxWidth)
  • 添加一行居中字符串并换行。
public void addCenterStringLine(String s)
  • 添加一个图片,默认缩放至长为字符大小的正方形,前后各增加一个空格,共占据三个字符的长度,效果类似聊天emoji。
public void addImage(BufferedImage image)
  • 添加一个字符串,如果长度超长会自动换行。
public void addString(String s)
  • 添加一个空格,包含有参和无参两种方式,其中参数为空格数量,无参默认增加一个空格。
public void addSpace(int spaceNum)
public void addSpace()
  • 换行
public void nextLine()
  • 生成图片,包含有参和无参两种,参数为字符的像素高度,返回一个BufferImage。
public BufferedImage drawImage(int size)
public BufferedImage drawImage()

该类可能存在一定的Bug(如半角字符导致右方大量空白),目前仅为AngelinaFrame内部使用,具体效果可以参阅默认功能"洁哥菜单"。如需使用请充分进行测试。

框架默认功能

群聊功能

触发关键字 描述 最低运行权限
关于 返回框架地址 普通成员
菜单 全部功能(根据注解自动生成,也可通过文件替换) 普通成员
切换 当一个群里有该Bot的多个QQ时,通过该功能切换活跃QQ 群管理员
在线Bot 当前Bot中有哪些QQ在线 普通成员
关闭 关闭群聊中的某个功能 群管理员
开启,打开 打开群聊中的某个功能 群管理员
已关闭,功能开关 查看本群关闭了哪些功能 普通成员
停用 全局停用某个功能 超级管理员
启用 全局启用某个功能 超级管理员
已停用 查看停用了哪些功能 普通成员
拉黑 将某个用户加入黑名单 超级管理员
取消拉黑 将某个用户移除黑名单 超级管理员
黑名单 查看拉黑了哪些用户 普通成员

私聊功能

触发关键字 描述
验证 洁哥主页的登录验证

后注

这些api如果不满足你的需求,那就改框架源码吧,欢迎提PR

⚠️ **GitHub.com Fallback** ⚠️