Mirai 对象
Mirai 对象表示一个机器人实例。我们要进行的一切操作几乎都是在这个对象上进行的。
Mirai
类定义在 mirai.bot
模块,同时也存在于顶层模块 mirai
的命名空间中,你可以通过 from mirai import Mirai
来导入。
创建 Mirai 对象
Mirai
类的构造函数包含两个参数:qq
和 adapter
。qq
是机器人的 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_image
和 upload_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
decline
或 ignore
方法。
@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, '拒绝请求。')
decline
和 ignore
还有一个另外的参数 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 实例。
可以使用 uvivorn
或 hypercorn
等 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 优先);设置为 uvicorn
或 hypercorn
则使用指定的服务器。
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()
MiraiRunner
的 run
方法的参数与 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')