如何开发 - Strelizia02/AngelinaBot GitHub Wiki
AngelinaFrame是一个基于SpringBoot的QQ机器人开发框架,旨在与简化开发流程。将登录、收发消息等操作融入框架,开发人员只需专注于实际的业务代码。
当前已集成:Mirai(QQ群聊框架),QQChanel(QQ频道官方接口)
AngelinaFrame包含了一些对于Bot的个人理解,使用AngelinaFrame框架,即视为同意并遵从AngelinaFrame的定义。
群聊Bot在设计自身功能之前,首先应做到“不打扰”。Bot不应该打扰群友的正常群聊,因此AngelinaFrame规定:必须以Bot的名称开头才能唤起Bot。
AngelinaFrame中维护了一个账号池,映射了Bot的所有账号 -> 服务的群聊。
通过账号池,AngelinaFrame保证:
若一个群中有多个Bot账号,接受唤起命令时,有且仅有一个账号进行回复,不会出现多账号同时回复的情况。
10秒内超过3条消息,不会调用功能,并提示超出速率;超过5条消息不再回复。防止恶意刷屏或多个bot互相循环调用。
AngelinaCenter是AngelinaBot的数据中心,用于统计每个Bot的调用次数、在线情况,并提供数据更新等服务(数据更新指AngelinaBot的游戏数据更新)。
AngelinaFrame默认对接AngelinaCenter以下接口:
每3分钟向AngelinaCenter发送心跳消息,心跳内容包括:QQ账号,在线情况。不会发送密码等隐私信息。此数据用于统计AngelinaFrame的登录情况。
每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
字段 | 描述 | 类型 |
---|---|---|
loginQq | 收到账号的QQ(频道ID) | String |
text | 原始消息文字内容 | String |
keyword | 触发到的关键字 | String |
args | 将文字消息按空格切分 | List |
发送人的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由框架进行构造,用户无需处理。
字段 | 描述 | 类型 | 是否必填 |
---|---|---|---|
loginQq | 实际发送消息的QQ | String | 私聊必填 |
发送目标的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 |
任何一个Angelina注解修饰的方法,都应以MessageInfo作为唯一参数,ReplayInfo作为返回值。AngelinaFrame会在程序启动时对所有注解方法进行检查,不符合要求的话会报错中止程序。
参数 | 描述 | 入参类型 |
---|---|---|
keyWords | 触发方法的关键字 | String[] |
dHash | 触发方法的图片(性能开销大,慎用) | String[] |
description | 功能描述 | String |
author | 作者(默认是我) | String |
funcClass | 功能分类 | FunctionType |
permission | 最低运行权限 | PermissionEnum |
参数 | 描述 | 入参类型 |
---|---|---|
keyWords | 触发方法的关键字 | String[] |
description | 功能描述 | String |
参数 | 描述 | 入参类型 |
---|---|---|
event | 触发方法的事件 | EventEnum |
description | 功能描述 | String |
以上注解只能够满足一条消息,一次回复,且必须以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 |
** 其他功能不推荐重写**
有一些逻辑,可能需要在程序启动时就要允许,而AngelinaFrame已经实现了SpringBoot的SmartInitializingSingleton,因此对外提供自定义init接口,用户实现该接口,即可将逻辑添加至程序启动时。
@Service
public class InitAngelinaService implements top.angelinaBot.service.InitAngelinaService {
@Override
public void init() {
//TODO 这里是你的启动时自定义逻辑
}
}
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。