Skip to main content

Mirai 对象

Mirai 对象表示一个机器人实例。我们要进行的一切操作几乎都是在这个对象上进行的。

Mirai 类定义在 mirai.bot 模块,同时也存在于顶层模块 mirai 的命名空间中,你可以通过 from mirai import Mirai 来导入。

创建 Mirai 对象

Mirai 类的构造函数包含两个参数:qqadapterqq 是机器人的 QQ 号,类型为整数。adapter 是网络适配器。

from mirai import Mirai, HTTPAdapter

adapter = HTTPAdapter(verify_key='your_verify_key', host='localhost', port=8080)
bot = Mirai(qq=12345678, adapter=adapter)

Single Mode

在 Single Mode 下,创建机器人实例不需要 qq 参数,此时,此参数可传入任意值。

bot = Mirai(qq=0, adapter=adapter)

登录之后,YiriMirai 会获取正确的 QQ 号,并将其保存在 bot.qq 中。

@bot.on(Startup)
async def startup(_: Startup):
print(bot.qq)

调用 API

可以直接通过在 Mirai 对象上使用点号调用 mirai-api-http 的 API。

await bot.send_group_message(12345678, [Plain('Hello, World!')]) # 发送群消息
profile = await bot.bot_profile.get() # 获取机器人账号的资料

更多信息,查看调用 API章节。

临时适配器切换

某些特殊的 API,比如 upload_imageupload_voice 只能在 HTTP 适配器下工作。如果想要在其他适配下使用这些 API,可以用 use_adpter 方法临时切换适配器。

use_adapter 返回一个异步上下文对象,用于 async with 中。

async with bot.use_adapter(HTTPAdapter.via(bot)):
...

辅助方法

Mirai 类对一些常用的 API 进行了封装。

发送消息

send 方法是对 send_friend_message send_group_message send_temp_message 三者的封装,可以自动判断消息目标类型,选择对应的 API。

send 方法的第一个参数是消息目标,第二个参数是消息内容。消息目标可以是 MessageEvent 或者 Entity,消息内容可以是消息链或者可转化为消息链的对象。

大多数情况下,在接收消息事件中,可以写为:

@bot.on(FriendMessage)
async def reply(event: FriendMessage):
await bot.send(event, 'Hello, World!')

send 方法还有第三个参数 quote,用于指定是否引用消息目标中包含的消息。

await bot.send(event, 'Hello, World!', quote=True)

处理请求

处理加好友、加群请求时,可以使用 allow declineignore 方法。

@bot.on(NewFriendRequestEvent)
async def allow_request(event: NewFriendRequestEvent):
await bot.allow(event)

使用 message 参数指定处理请求的原因:

@bot.on(NewFriendRequestEvent)
async def allow_request(event: NewFriendRequestEvent):
await bot.decline(event, '拒绝请求。')

declineignore 还有一个另外的参数 ban,表示是否拉黑。

@bot.on(NewFriendRequestEvent)
async def allow_request(event: NewFriendRequestEvent):
await bot.decline(event, '拒绝请求。', ban=True)

获取实体

使用 get_friend 通过 QQ 号获取对应的 Friend 对象。

friend = await bot.get_friend(12345678)

如果不是好友,或者因其他原因获取失败,此方法将返回 None。

同样地,可以通过 get_group 获取对应的 Group 对象,通过 get_group_member 获取对应的 GroupMember 对象。

group = await bot.get_group(12345678)
group_member = await bot.get_group_member(12345678, 12345678)

有些事件(比如 NudgeEvent)中的来源不是 Entity 类型,而是 Subject 类型,这时可以使用 get_entity 方法转化为 Entity

@bot.on(NudgeEvent)
async def handle_nudge(event: NudgeEvent):
entity = await bot.get_entity(event.subject)

处理事件

Mirai 对象的 on 方法用于注册事件处理器。

from mirai import GroupMessage

# 接受群消息
@bot.on(GroupMessage)
async def handle_group_message(event: GroupMessage):
print(str(event.message_chain)) # 打印消息内容

更多信息,查看事件处理章节。

运行

使用 run 方法

使用 run 方法启动机器人。

bot.run()

当使用 WebHook 时,在此处指定 WebHook 的地址和端口。

bot.run(host='127.0.0.1', port=8081)
端口冲突

即使不使用 WebHook,在不指定 run 的参数时,Mirai 默认占用 localhost:8080 的端口。

如果遇到端口冲突无法启动,试着指定一个别的端口。

使用 ASGI 服务器

另一种方式是使用 bot.asgi,这一属性可访问到 bot 的 ASGI 实例。

可以使用 uvivornhypercorn 等 ASGI 服务器运行机器人。

from mirai import Mirai
bot = Mirai(...)

...

app = bot.asgi

在命令行运行:

uvicorn main:app --host 127.0.0.1 --port 8081
# 或者
hypercorn main:app --bind 127.0.0.1:8081
在 run 方法中使用 ASGI

当你安装了 uvicorn 或 hypercorn 时,bot.run 会自动使用 ASGI 的方式启动。

默认优先使用 uvicorn。可以通过参数 asgi_server 来控制使用的服务器。此参数的默认值为 auto,表示自动选择(uvicorn 优先);设置为 uvicornhypercorn 则使用指定的服务器。

asgi_server 设置为其他值,或未找到可用的 ASGI 服务器,将禁用 ASGI。此时,WebHook 将不可用。

bot.run(host='127.0.0.1', port=8081, asgi_server='uvicorn')

多例运行

使用 MiraiRunner 类可以同时运行多个 Mirai 对象。

from mirai import MiraiRunner
bot1 = Mirai(...)
bot2 = Mirai(...)

runner = MiraiRunner(bot1, bot2)
runner.run()

MiraiRunnerrun 方法的参数与 bot.run 的参数相同。

tip

MiraiRunner 本身是一个 ASGI 实例,可以用于 uvicorn 等 ASGI 服务器。

uvicorn main:runner --host 127.0.0.1 --port 8081
caution

MiraiRunner 是单例类,请不要使用不同的参数多次创建 MiraiRunner 实例。

SimpleMirai

warning

SimpleMirai 已废弃。将在 0.3 版本删除,其中内容将合并到 Mirai 中。

SimpleMirai 是工作在模型层之下的 Mirai。

note

模型层(model 层)提供了对 mirai-api-http 发回的原始数据的封装,让我们可以以更加 pythonic 的方式来处理这些数据。

关于模型层的更多信息,参看YiriMirai 的架构章节。

SimpleMirai 不含模型层封装,这意味着一切都必须和 mirai-api-http 的原始定义一致,并且只能使用基本类型,比如 dict 来描述数据。

创建 SimpleMirai 对象和创建 Mirai 对象的方式相同:

from mirai import SimpleMirai, HTTPAdapter

adapter = HTTPAdapter(verify_key='your_verify_key', host='localhost', port=8080)
bot = SimpleMirai(qq=12345678, adapter=adapter)

SimpleMirai 对象也可以通过 on 注册事件处理器,但由于没有模型层封装,所以只能使用字符串型的事件名称,并且不会发生事件传播

SimpleMirai 的事件处理器接收到的 event 参数是字典类型,存放 mirai-api-http 发回的原始数据。

@bot.on('FriendMessage')
async def handle_group_message(event: dict):
print(f"收到来自{event['sender']['nickname']}的消息。")

# # FriendMessage 不会被传播到 Event
# @bot.on('Event')
# async def handle_event(event: dict):
# print("这里不会被执行。")

SimpleMirai 对象也能通过点号调用 API。此时,API 的名称必须与 mirai-api-http 的原始定义一致,比如,只能使用 bot.sendFriendMessage 而不能使用 bot.send_friend_message。同时,必须指出 API 的类型(GET/POST)。

await bot.sendGroupMessage(target=12345678, messageChain=[
{'type': 'Plain', 'text': 'Hello, World!'}
], method='POST')

对于名称中含有 / 的 API,需要使用 call_api 方法。

file_list = await bot.call_api('file/list', id="", target=12345678, method='GET')