MiraiBot 简介

不写了

功能构想

群员可以自定义一些关键词和消息内容,当机器人检测到该关键词时回自动回复关键词对应的消息内容。

功能实现

构建一个自定义消息类,来保存关键字和消息内容等信息。监听每一条群消息并与表中关键字匹配,如匹配则查询出自定义内容,发送到对应群内。若群消息与狼宝内置关键词匹配,则优先执行狼宝对应功能,否则不予理会。

为了方便数据入库,使用的Kotlin ORM 框架是 Ktorm 使用说明 仓库链接

自定义消息实体的设计

字段: group(群号),kwy(关键词),message(自定义消息),sender(发送者号码)

1
2
3
4
5
6
7
8
//top.kagerou.data.CustomizeMessage.kt
interface CustomizeMessage : Entity<CustomizeMessage> {
companion object : Entity.Factory<CustomizeMessage>()
val group: Long
val key: String
val message: String
val sender :Long
}

自定义消息表对象的实现

在表对象中,将数据库的表名和表字段名和程序设计的类中的各字段名一一绑定起来。下面代码中引号中的内容为数据库对应名称

1
2
3
4
5
6
7
//top.kagerou.data.CustomizeMessages.kt
object CustomizeMessages : Table<CustomizeMessage>("t_customize_message") {
val group = long("group_number").primaryKey().bindTo { it.group }
val key = varchar("q_key").bindTo { it.key }
val message = varchar("q_message").bindTo { it.message }
val sender = long("sender_number").bindTo { it.sender }
}

自定义消息数据表的创建

1
2
3
4
5
6
7
create table t_customize_message
(
group_number NUMERIC not null,
q_key varchar(20),
q_message varchar(100),
sender_number NUMERIC
);

自定义消息数据操作对象的实现

根据业务简单的实现了部分方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* 自定义消息数据持久化的操作对象
* @author xiaohuliqibao
* @date 2023/6/25 15:38
*/
object CustomizeMessagesService {

//初始化配置信息
private val database = Database.connect("jdbc:sqlite:src/test/resources/Chinook.db")
/**
*描述: 保存自定义消息
* @param group 群号
* @param key 关键词
* @param message 自定义消息
* @param sender 发送人ID
*/
private fun save(group: Long,key: String,message: String,sender: Long){
database.insert(CustomizeMessages){
//set(it.id,1)
set(it.group,group)
set(it.key,key)
set(it.message,message)
set(it.sender, sender)
}
}
/**
* 描述: 通过关键词和群号查找对应的自定义消息,可能会查询不到,返回空字符串。
* @param group 群号
* @param key 关键词
*/
fun findByKey(group: Long, key: String): String? {
val messageList = database.from(CustomizeMessages).select()
.where { (CustomizeMessages.group eq group) and (CustomizeMessages.key eq key) }
.map { row -> CustomizeMessages.createEntity(row) }
return messageList.first()?.message
}
/**
* 描述: 通过群号和关键词更新自定义消息
* @param group 群号
* @param key 关键词
* @param message 自定义消息
* @param sender 发送人ID
*/
private fun update(group: Long,key: String,message: String,sender: Long){
database.update(CustomizeMessages){
set(it.message,message)
set(it.sender, sender)
where { (it.group eq group) and (it.key eq key) }
}
}

/**
* 描述: 判断是否存在关键词消息
* @param group 群号
* @param key 关键词
*/
fun exist(group: Long, key: String): Boolean {
val messageList = database.from(CustomizeMessages).select()
.where { (CustomizeMessages.group eq group) and (CustomizeMessages.key eq key) }
.map { row -> CustomizeMessages.createEntity(row) }
return messageList.isNotEmpty()
}
/**
* 描述: 存在了-> update,不存在-> save
* @see save
* @see update
*/
fun savePlus(group: Long,key: String,message: String,sender: Long){
if (this.exist(group,key)){
this.update(group, key, message, sender)
}
else{
this.save(group, key, message, sender)
}
}

/**
* 描述:删除自定义消息
* @param group 群号
* @param oldKey 要删除的关键词
*/
fun delete(group: Long, oldKey: String) {
database.delete(CustomizeMessages){
(it.group eq group) and (it.key eq oldKey)
}
}
}

在QQ群事件监听类中添加一个单独的消息事件监听

设置的增加监听的关键词为“有人发key你回message”,删除监听的关键词为“不再回复key”
以下市具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@EventHandler
suspend fun GroupMessageEvent.CustomizeMessage(): ListeningStatus{
val msg = message.contentToString()
if ( GroupService.exist(group.id)) {
when {
msg.startsWith("有人发") && msg.contains("你回") -> {
val split = msg.subSequence(3,msg.length).split("你回")
val newKey = split[0]
val newMessage = split[1]
CustomizeMessagesService.savePlus(group.id,newKey,newMessage,sender.id)
this.group.sendMessage("好的,狼宝记住了")
}
msg.startsWith("不再回复") -> {
val oldKey = msg.substring(4,msg.length)
CustomizeMessagesService.delete(group.id,oldKey)
this.group.sendMessage("好的,已经没有[$oldKey]")
}
!msg.startsWith("不再回复") || !msg.startsWith("有人发") || !msg.contains("你回") ->{
val customizeMessage = CustomizeMessagesService.findByKey(group.id, msg)
if (customizeMessage != null) {
//todo 实现回复自定义图片
this.group.sendMessage(customizeMessage)
}
}
}
}
return ListeningStatus.LISTENING
}

结语

自定义消息的实现,是机器人监听功能和数据库交互的一个简单的例子。其中//todo 还可以实现回复自定义的图片等其他非简单文本的消息,可以继续探索Mirai的消息系统来实现。

下一章应该是对网络api服务使用和实现了。