本文作者: YOOZIKI
本文链接: https://yooziki.github.io/2020/08/297095/
Python版本:py37
安装相关模块,源码在这里
pip install graia-application-mirai |
添加选择器子模块
pip install graia-component-selector |
mirai环境配置
自定义方式(推荐)
在mirai仓库中的shadow
下找到对应的包体并下载
如果出现无法下载的情况下载文件时将https://github.com替换成http://github-proxy.yobot.win即可
cd /tmp |
经测试的可用版本:
console = "mirai-console-1.0-M4-dev-3.jar" |
使用简易的python启动器即可启动,首次启动后会创建一系列文件夹,使用stop
命令正常停止,将mirai-api-http
放到plugins
下,再次启动plugins会自动生成配置文件存放在config\MiraiAPIHTTP
下,使用文本方式打开后可以修改其中的一些配置,完成后再次用stop
命令正常停止,之后使用:login user passwd
登录即可
强行停止mirai会造成mirai-api-http
没有结束的问题,如果出现请在任务管理器中关闭OpenJDK Platform binary
进程
建议只修改autuKey增加安全性,其它改动可能会造成Graia无法连接
#!/usr/bin/env python3 |
mirua方式(一键懒人包)
可以在这里获得
git colne https://github.com/ieew/mirua |
miraiOK方式
首先找到miraiOK仓库或者使用我的fork仓库并且根据说明文件下载可执行程序到miraoOK目录下
git clone https://github.com/LXY1226/MiraiOK |
执行对应的可执行文件,等待第一次执行结束
为了保证程序的正确性,第一次执行结束后,请创建一个.nonupdate文件禁用更新功能,或者可以试试更新一次会不会出问题
对应的mirai相关jar包可以在这里查看
执行第一次之后,在miraiOK的目录下会有一个plugins
文件夹,将mirai-api-http-version.jar
包放到这里,插件源码
如果miraiOK给到的./content/中mirai-core版本为1.0一下,则只能使用1.7版本的mirai-api-http
为了保证py程序的正确运行,再次运行可执行文件
然后回到plugins
文件夹下,新生成了一个文件夹,里面有一个yml配置文件,使用txt方式打开即可。(如果没有生成文件夹,则手动创建./MiraiAPIHTTP/setting.yml
)
写入
##该配置为分段配置,对所有会话有效 |
如果希望每次都自动登录,可以在miraiOK更目录下的config.txt
中根据模板提示写入内容
程序框架
可以从这里查看
# 所有事件监听都在entry中可以找到 |
# 监听 |
其中的bcc
是一个广播,会将从miraiOK获得的信息在程序内广播传递。
app
是一个像mirai框架传递信息的通道
# 写入监听事件handler |
# 程序固定尾 |
API
MessageChain
from graia.application.message.chain import MessageChain |
用于处理消息的数据结构,包含一个有序列表
- MessageChain.asDisplay()
得到字符串形式的消息表示,返回字符串 - MessageChain.root
返回消息链列表 - MessageChain.doc
返回消息链的API文档说明 - MessageChain.module
返回消息链的模块绝对引用 - MessageChain.create(<list/tuple>)
创建一个消息链结构,其中list/tuple可以包含能够获取的类型元素,返回创建的消息链 - MessageChain.isImmutable()
判断消息链是否为可变,可变返回True
,不可变返回False
,默认接受的消息为不可变 - MessageChain.asMutable()
将消息链转换为可变的,返回可变的消息链 - MessageChain.isSendable()
检查消息链是否可以被正确发送,可发送返回True
,不可发送返回False
- MessageChain.asSendable()
将消息链转换为可以发送的新消息链,返回可能可以正确发送的消息链 - MessageChain.has(T)
消息链中是否存在某种消息元素,亦可使用T in MessageChain
如果有则返回True
否则返回False
- MessageChain.get(T)
取出消息链中某种消息元素,以列表方式返回
亦可以使用MessageChain[T] - MessageChain.join(*MessageChains)
将多个MessageChain按顺序拼合“
返回拼合后的消息链 - MessageChain.plusWith(*MessageChain)
方法将在现有的基础上将另一消息链拼接到原来实例的尾部, 并生成, 返回新的实例; 该方法不改变原有和传入的实例. - MessageChain.plus(*MessageChain)
方法将在现有的基础上将另一消息链拼接到原来实例的尾部; 该方法更改了原有的实例, 并要求isMutable
方法返回True
才可以执行. - MessageChain.asSerializationString()
将消息链对象转为以 “Mirai 码” 表示特殊对象的字符串
返回字符串 - MessageChain.fromSerializationString(string)
将以 “Mirai 码” 表示特殊对象的字符串解析为消息链, 不过可能不完整
返回消息链,不可变 - MessageChain.asMerged()
把相邻的Plain元素合并为一个Plain元素 - MessageChain.subchain(slice)
切片操作
类似list切片方式
返回切片后的MessageChain - MessageChain.exclude(T)
将消息链中某种元素排除
返回新的消息链 - MessageChain.include(T)
只保留消息链中某种元素
返回新消息链
Elements
import graia.application.message.elements.internal as Elements |
Elements.Plain(string)
实例化一个Plain元素,用于承载消息中的文字Elements.Source
表示消息在一个特定聊天区域内的唯一标识,收到的消息链中存在,只能够获取Elements.Quote(id,groupID,senderID,targetID,origin)
表示消息中回复功能,
id:回复的消息在群内的唯一标识,通过Elements.Source得到
groupID:群号
senderID:原消息发送人
targetID:群号
oringin:发送的消息链消息链中应该有:原消息链的root列表, At(type=‘At’,target=qq号,display=’@谁谁谁(群内id)’), Plain(’ ‘),Plain(“内容”)
Elements.At(id)
表示@某人Elements.AtAll()
管理员有效,@全体成员Elements.Face(id)
表示一个表现,QQ内置的表情,id是表情的idElements.ImageType(Enum)
Friend = “Friend”
Group = “Group”
Temp = “Temp”
Unknown = “Unknow”
是一个类型的定义,不需要直接调用Elements.Image()
imageID:是一个16进制字符串
url:链接位置
path
type:图片属于哪里(ImageType定义)
[关于Image的方法](# Image)Elements.FlashImage(Image)
发送闪照,需要先通过Image方法创建一个Image对象
亦可以直接Image.asFlash()
Elements.Xml(str)
xml消息Elements.Json(str)
Elements.App(str)
app消息Elements.PokeMethods(Enum)
是一个类型定义,不需要直接调用
Poke = “Poke”
ShowLove = “ShowLove”
Like =“Like”
Heartbroken=“Heartbroken”
SixSixSix=“SixSixSix”
FangDaZhao = “FangDaZhao”Elements.Poke(PokeMethods)
Image
from graia.application.message.elements.internal import Image |
[返回到Elements](# Elements)
- Image.fromLoacalFile(filepath)
从本地获取一张图片
返回ShadowElement,包含了一个asFlash方法,可以作为闪照发送Image.fromLocalFile(path).asFlash()
- Image.fromUnsafePath(filepath)
不检查路径安全性,让上层协议(mirai-api-http)处理图片文件 - Image.fromUnsafeBytes()
从不保证有效性的bytes中创建一个ShadowElement,并且上传,同样包含一个asFlash方法
不推荐,安全性低 - Image.fromNetworkAddress(url)
从不保证有效性的网络位置中创建一个ShadowElement,在发送的时候从url获得图片并且上传
可能抛出任何形式的网络错误
可以使用asFlash方法 - Image.fromUnsafeAddress(url)
让上层协议(mirai-apii-http)处理图片文件 - Image.asDisplay()
返回字符串”[图片]” - Image.http_to_bytes(url)
从远端服务器获取图片的 bytes, 注意, 你无法获取并不包含 url 属性的本元素的 bytes - Image.asFlash()
设为闪照发送 - Image.asSerializationString()
将消息链对象转为以 “Mirai 码” 表示特殊对象的字符串
Massages
定义了几种消息的类型
import graia.application.event.messages as Messages |
- FriendMessage
好友对话事件 - GroupMessage
群对话事件 - TempMessage
临时对话事件
Friend模块
定义了friend的几种属性,需要在监听中声明
from graia.application.friend import Friend |
- id:qq号
- nickname:昵称
remark:好像访问不到??
Group模块
定义了group的一些属性,需要在监听中声明,例如:async def group_message_handler(app: GraiaMiraiApplication, message: MessageChain, group: Group,member: Member):
import graia.application.group as Group |
Group.Group
- Group.Group.id:群id
- Group.Group.name:群名称
- Group.Group.accountPerm:账号在群中的权限
Group.MemberPerm
作为字典枚举,并不需要主动调用
- .Member # 普通成员
- .Administrator # 管理员
- .Owner # 群主
Group.Member
描述用户在群组中所具备的有关状态,包括所在群组,群中昵称,所具备的权限,唯一的ID
- .id:说话人的QQ号
- .name:说话人的群昵称
- .permission:说话人的权限等级
- .group:上面的Group.Group所有内容
Group.GroupConfig
描述群内各项功能的设置(使用方法不明)
- name
- announcement
- confessTalk
- allowMemberInvite
- autoApprove
- anonymousChat
Group.MemberInfo
描述群组成员的可修改状态,修改需要权限(使用方法不明)
- name
- specialTitle
GraiaMiraiApplication类
大多数的功能都被存在这个类中
from graia.application import GraiaMiraiApplication |
.getVersion()
返回mirai-api-http
的版本
.getGroup(int)
返回对应群号的群组信息(为空则None)
id,name,accountPermprint(app.getGroup(<Id>))
.groupList()
print(await app.groupList())
.getMember(Group int,member int)
从已知群组和已知成员的id获得成员的信息
print(await app.getMember(<ID>,<ID>))
.memberList(Group int)
从已知群组中获取群内所有成员的信息列表
.friendList()
获取所有好友的信息列表
print(await app.friendList())
.getFriend(int)
根据好友的id获取Friend实例
.sendFriendMessage(Friend,MessageChain[,quote])
向好友发送消息,quote为回复信息断,可以选择
.sendGroupMessage(Group,MessageChain[,quote])
向群组发送消息
.sendTempMessage(Group/ID,Member/ID,messageChain[,quote])
向群内成员发起临时会话
.revokeMessage(target)
撤回消息(2min以内)
target (Union[Source, BotMessage, int]): 特定信息的 messageId
, 可以是 Source
实例, BotMessage
实例或者是单纯的 int 整数.
.messageFromId(source[Source, int])
尝试从已知的 messageId
获取缓存中的消息
.muteAll(group)&.unmuteAll(group)
全员禁言
.mute(group,member,time)、unmute(group,membder)
禁言指定群友
time指禁言时长
.kick(group,membder)
群内踢掉某人
.quit(group)
退群
Event模块
通过Graia.application.entry可以导入MiraiApiHttp支持的所有事件类型
from graia.application.entry import ( |
BotOnlineEvent
当该事件发生时, 应用实例所辖账号登录成功
qq: int
BotOfflineEventActive
当该事件发生时, 应用实例所辖账号主动离线
qq: int
BotOfflineEventForce
当该事件发生时, 应用实例所辖账号被迫离线
qq: int
BotOfflineEventDropped
当该事件发生时, 应用实例所辖账号与服务器的连接被服务器主动断开, 或因网络原因离线
qq: int
BotReloginEvent
当该事件发生时, 应用实例所辖账号正尝试重新登录
qq: int
BotGroupPermissionChangeEvent
当该事件发生时, 应用实例所辖账号在一特定群组内所具有的权限发生变化
origin: MemberPerm
current: MemberPerm
group: Group
BotMuteEvent
当该事件发生时, 应用实例所辖账号在一特定群组内被管理员/群主禁言
Allowed Extra Parameters(提供的额外注解支持):
GraiaMiraiApplication (annotation): 发布事件的应用实例
Member (annotation, optional = None): 执行解除禁言操作的管理员/群主, 若为 None 则为应用实例所辖账号操作
Group (annotation, optional = None): 发生该事件的群组
durationSeconds: int
operator: Optional[Member]
BotUnmuteEvent
当该事件发生时, 应用实例所辖账号在一特定群组内被管理员/群主解除禁言
operator: Optional[Member]
BotJoinGroupEvent
当该事件发生时, 应用实例所辖账号加入指定群组
group: Group
BotLeaveEventActive
当该事件发生时, 应用实例所辖账号主动退出了某群组.
group: Group
BotLeaveEventKick
当该事件发生时, 应用实例所辖账号被某群组的管理员/群主从该群组中删除.
group: Group
GroupRecallEvent
当该事件发生时, 有群成员在指定群组撤回了一条消息
注意, 这里的群成员若具有管理员/群主权限, 则他们可以撤回其他普通群员的消息, 且不受发出时间限制
authorId: int
messageId: int
time: datetime
group: Group
operator: Optional[Member]
FriendRecallEvent
当该事件发生时, 有一位与应用实例所辖账号为好友关系的用户撤回了一条消息
authorId: int
messageId: int
time: int
operator: int
GroupNameChangeEvent
该事件发生时, 有一群组被修改了群名称
origin: str
current: str
group: Group
operator: Optional[Member] = None
GroupEntranceAnnouncementChangeEvent
该事件发生时, 有一群组被修改了入群公告
origin: str
current: str
group: Group
operator: Optional[Member]
GroupMuteAllEvent
该事件发生时, 有一群组开启了全体禁言
origin: bool
current: bool
group: Group
operator: Optional[Member]
GroupAllowAnonymousChatEvent
该事件发生时, 有一群组修改了有关匿名聊天的相关设定
origin: bool
current: bool
group: Group
operator: Optional[Member]
GroupAllowConfessTalkEvent
该事件发生时, 有一群组修改了有关坦白说的相关设定
origin: bool
current: bool
group: Group
isByBot: bool
GroupAllowMemberInviteEvent
该事件发生时, 有一群组修改了有关是否允许已有成员邀请其他用户加入群组的相关设定
origin: bool
current: bool
group: Group
operator: Optional[Member]
MemberJoinEvent
该事件发生时, 有一新成员加入了一特定群组
member: Member
MemberLeaveEventKick
该事件发生时, 有一群组成员被管理员/群主从群组中删除, 当 operator
为 None
时, 执行者为应用实例所辖账号.
type = “MemberLeaveEventKick”
member: Member
operator: Optional[Member]
MemberLeaveEventQuit
该事件发生时, 有一群组成员主动退出群组.
member: Member
MemberCardChangeEvent
该事件发生时, 有一群组成员的群名片被更改, 执行者可能是管理员/群主, 该成员自己, 也可能是应用实例所辖账号(这时, operator
为 None
).
origin: str
current: str
member: Member
operator: Optional[Member]
MemberSpecialTitleChangeEvent
该事件发生时, 有一群组成员的群头衔被更改, 执行者只可能是群组的群主.
origin: str
current: str
member: Member
MemberPermissionChangeEvent
该事件发生时, 有一群组成员的权限被更改/调整, 执行者只可能是群组的群主.
origin: str
current: str
member: Member
MemberMuteEvent
该事件发生时, 有一群组成员被管理员/群组禁言, 当 operator
为 None
时为应用实例所辖账号操作.
durationSeconds: int
member: Member
operator: Optional[Member]
MemberUnmuteEvent
该事件发生时, 有一群组成员被管理员/群组解除禁言, 当 operator
为 None
时为应用实例所辖账号操作.
member: Member
operator: Optional[Member]
NewFriendRequestEvent
当该事件发生时, 有一用户向机器人提起好友请求.
该事件的处理需要你获取原始事件实例.
- 读取该事件的基础信息:
event.supplicant: int # 发起加好友请求的用户的 ID |
同意请求: `await event.accept()`, 具体查看该方法所附带的说明. |
requestId: int = Field(…, alias=“eventId”)
supplicant: int = Field(…, alias=“fromId”) # 即请求方 QQ
sourceGroup: Optional[int] = Field(…, alias=“groupId”)
nickname: str = Field(…, alias=“nick”)
message: str
accept(message:str=””)
同意对方的加好友请求.
message (str, optional): 附带给对方的消息. 默认为 “”.
reject(message: str = “”)
拒绝对方的加好友请求.
message (str, optional): 附带给对方的消息. 默认为 “”.
rejectAndBlock(message: str = “”)
拒绝对方的加好友请求, 并不再接受来自对方的加好友请求.
message (str, optional): 附带给对方的消息. 默认为 “”.
MemberJoinRequestEvent
当该事件发生时, 有一用户向机器人作为管理员/群主的群组申请加入群组.
该事件的处理需要你获取原始事件实例.
- 读取该事件的基础信息:
5event.supplicant: int # 申请加入群组的用户的 ID
event.groupId: Optional[int] # 对方试图加入的群组的 ID
event.groupName: str # 对方试图加入的群组的名称
event.nickname: str # 对方的昵称
event.message: str # 对方发起请求时填写的描述同意请求: `await event.accept()`, 具体查看该方法所附带的说明.
拒绝请求: `await event.reject()`, 具体查看该方法所附带的说明.
忽略请求: `await event.ignore()`, 具体查看该方法所附带的说明.
拒绝并不再接受来自对方的请求: `await event.rejectAndBlock()`, 具体查看该方法所附带的说明.
忽略并不再接受来自对方的请求: `await event.ignoreAndBlock()`, 具体查看该方法所附带的说明.
requestId: int = Field(…, alias=“eventId”)
supplicant: int = Field(…, alias=“fromId”) # 即请求方 QQ
groupId: Optional[int] = Field(…, alias=“groupId”)
groupName: str = Field(…, alias=“groupName”)
nickname: str = Field(…, alias=“nick”)
message: str
accept(message: str = “”)
同意对方加入群组.
message (str, optional): 附带给对方的消息. 默认为 “”.
reject(message: str = “”)
拒绝对方加入群组.
message (str, optional): 附带给对方的消息. 默认为 “”.
ignore(self, message: str = “”)
忽略对方加入群组的请求.
message (str, optional): 附带给对方的消息. 默认为 “”.
rejectAndBlock(self, message: str = “”)
拒绝对方加入群组的请求, 并不再接受来自对方加入群组的请求
message (str, optional): 附带给对方的消息. 默认为 “”.
BotInvitedJoinGroupRequestEvent
当该事件发生时, 应用实例所辖账号接受到来自某个账号的邀请加入某个群组的请求.
该事件的处理需要你获取原始事件实例.
- 读取该事件的基础信息:
int # 邀请所辖账号加入群组的用户的 ID event.groupId: Optional[int] # 对方邀请所辖账号加入的群组的 ID
event.groupName: str # 对方邀请所辖账号加入的群组的名称
event.nickname: str # 对方的昵称
event.message: str # 对方发起请求时填写的描述同意请求: `await event.accept()`, 具体查看该方法所附带的说明.
拒绝请求: `await event.reject()`, 具体查看该方法所附带的说明.
requestId: int = Field(…, alias=“eventId”)
supplicant: int = Field(…, alias=“fromId”) # 即请求方 QQ
groupId: Optional[int] = Field(…, alias=“groupId”)
groupName: str = Field(…, alias=“groupName”)
nickname: str = Field(…, alias=“nick”)
message: str
accept(message: str = “”)
同意对方加入群组.
message (str, optional): 附带给对方的消息. 默认为 “”.
reject(message: str = “”)
拒绝对方加入群组.
message (str, optional): 附带给对方的消息. 默认为 “”.
GraiaScheduler模块
from graia.scheduler import ( |
timers为一些常用的Scheduler时间设置
对于timers
中自造方法,使用croniter
模块
from datetime import datetime, timedelta |