# 简单说明
AmiyaBot 功能开发的关键模块一共有三个,分别是 core 模块下的 bot、Message、Chain。
bot为主要入口,包含了消息和事件的注册器,以及一些注册工具函数。Message为接收的消息主体,内含预解析的消息内容,以及一些相关操作函数。Message 对象在此仅用于参数类型注解,供编辑器智能提示使用,任何时候,你都不需要实例化 Message 对象。Chain为 Mirai 消息链的创建工具。所有需要发送的消息,都必须由 Chain 类创建。核心会调用 Chain 类的 build 方法生成 Mirai 消息链。
编写功能函数的文件,统一创建在 function 目录内,目录层级不限。
了解以上内容,下面让我们注册一个简单的群聊功能。
# 创建功能函数文件
我们在 function 目录内创建一个 hello.py
.
└── functions
├── __init__.py
└── hello.py
2
3
4
随后,在 __init__.py 内,添加刚刚新建的 hello 模块。
from . import (
...
hello
)
2
3
4
# 注册一个功能
# 示例一
当对话内容带有 你好 关键字时,回复 你好,世界
在刚刚新建的 hello.py 内,编写如下代码。
from core import bot, Message, Chain
@bot.on_group_message(keywords='你好')
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
现在,在你的群聊里发送 阿米娅你好,不出意外的话,你将会收到如下的回复。
「这是个人迈出的一小步,但却是人类迈出的一大步。」———— 阿姆斯特朗
接下来,我们了解一下上述代码的构成。
# 功能函数装饰器
功能函数装饰器作用于你的业务逻辑主体函数,其选择监听接收消息的目标。目前装饰器分为 私聊(on_private_message),群聊(on_group_message) 和 临时聊天(on_temp_message)
from core import bot
# 私聊
@bot.on_private_message(...)
async def _(data):
...
# 群聊
@bot.on_group_message(...)
async def _(data):
...
# 临时聊天
@bot.on_temp_message(...)
async def _(data):
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 参数列表
| 参数名 | 类型 | 释义 | 默认值 |
|---|---|---|---|
| function_id | String | 功能ID,不唯一,仅用于记录该功能的使用数量 | |
| keywords | KEYWORDS | 触发关键字,支持字符串、正则、全等句(equal)或由它们构成的列表 | |
| verify | VERIFY_CORO | 自定义校验方法,当该参数被赋值时,keywords 将会失效 | |
| check_prefix | PREFIX | 是否校验前缀或指定需要校验的前缀 | True |
| level | Int | 关键字校验成功后函数的候选默认等级 | 0 |
check_prefix 在私聊函数(on_private_message)内默认值为 False
# 接收不包含前缀或指定前缀的消息
AmiyaBot 默认需要对话中包含指定前缀才能进入消息分配器,我们认为机器人都应该遵守这一约定。但有时候,人性化一点也未必是一件坏事。
让我们回到 示例一 ,要触发示例一的功能,必须要求对话内容的前缀为 阿米娅 (指定的前缀之一),我们稍加修改,即可在对话没有携带指定前缀时,也能触发功能。
# 示例二
from core import bot, Message, Chain
# 在原来的基础上添加参数 check_prefix=False 可忽略前缀检查
@bot.on_group_message(keywords='你好', check_prefix=False)
async def _(data: Message):
return Chain(data).text('你好,世界')
# 也可以让前缀检查临时改为你指定的单词
@bot.on_group_message(keywords='你好', check_prefix=['兔兔', '🐰'])
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
7
8
9
10
11
12
13
注意
除特定用法之外,任何时候都是需要检查指定前缀!
# 接收全等句式
全等句式指对话的内容完全为设定的句子,并非通过关键词触发,使用工具 bot.equal 即可达到效果。
# 示例三
from core import bot, Message, Chain
@bot.on_group_message(keywords=bot.equal('你好'))
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
小技巧
示例三同样也能达到示例二的接收不包含前缀的消息的效果,因为全等句式不会检查前缀。
# 接收符合正则检查的句式
关键词传入 re.compile 对象,即可使用正则检查。
# 示例四
import re
from core import bot, Message, Chain
@bot.on_group_message(keywords=re.compile(r'你好,\d+'))
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
7
8
# 组合多个和多种关键词
关键字支持由 字符串、正则、全等句 构成的列表,组合中包含全等句时,全等句依然会无视前缀检查。
# 示例五
import re
from core import bot, Message, Chain
@bot.on_group_message(keywords=['你好', '您好', bot.equal('你好'), re.compile(r'你好,(\d+)')])
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
7
8
# 优先级
当关键词校验存在冲突时,可以通过指定优先级供消息分配器选择。
分配器的工作原理,是在完成检查之后,将通过校验的候选函数列表按优先级倒序排序,然后选取第一个执行。
所有函数的默认优先级都为 1,如果不指定优先级,分配器会按照加载的先后顺序选择。
# 示例六
from core import bot, Message, Chain
# 如果不指定优先级,当对话内容为 "世界你好" 时,第一个函数会首先通过校验并输出。
# 因为在模块加载阶段,第一个函数更早注册完毕。
@bot.on_group_message(keywords='你好', level=1)
async def _(data: Message):
return Chain(data).text('你好,世界')
@bot.on_group_message(keywords='世界你好', level=2)
async def _(data: Message):
return Chain(data).text('世界,你好')
2
3
4
5
6
7
8
9
10
11
12
13
14
# 自定义检查
内置的检查终究存在上限,如果需要制作复杂的功能,自定义检查必不可少。
自定义检查是一个协程函数,参数为 Message 对象,返回一个布尔值(必选)、优先级(可选)、关键词(可选)的元祖。
async def my_verify(data: Message):
if ...:
return True
return False
2
3
4
在自定义检查里,你可以动态输出优先级的值。
async def my_verify(data: Message):
if ...:
return True, 2
elif ...:
return True, 1
return False
2
3
4
5
6
输出关键词可将其赋值到 Verify 对象的 keywords 属性内,Verify 对象我们会在后续详细说明。
async def my_verify(data: Message):
return True, 1, ['关键词', ...]
2
# 示例七
from core import bot, Message, Chain
async def my_verify(data: Message):
if '你好' in data.text:
return True
return False
@bot.on_group_message(verify=my_verify)
async def _(data: Message):
return Chain(data).text('你好,世界')
2
3
4
5
6
7
8
9
10
11
12
# 结语
现在,你已经知道功能的各种基本的注册方式了。下一节,我们去了解功能函数的参数 Message 对象。