Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
205432db
Commit
205432db
authored
Feb 28, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove old files
parent
69abf7a5
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
0 additions
and
9586 deletions
+0
-9586
mirai-api-http/EventType_CH.md
mirai-api-http/EventType_CH.md
+0
-727
mirai-api-http/README.md
mirai-api-http/README.md
+0
-58
mirai-api-http/README_CH.md
mirai-api-http/README_CH.md
+0
-927
mirai-api-http/build.gradle.kts
mirai-api-http/build.gradle.kts
+0
-73
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
...ain/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
+0
-67
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/Session.kt
...-http/src/main/kotlin/net/mamoe/mirai/api/http/Session.kt
+0
-138
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt
...rc/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt
+0
-32
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt
...otlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt
+0
-126
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
...kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
+0
-53
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt
...c/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt
+0
-31
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
...kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
+0
-133
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/exceptions.kt
...c/main/kotlin/net/mamoe/mirai/api/http/data/exceptions.kt
+0
-42
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
...ain/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
+0
-56
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
.../kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
+0
-66
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt
...c/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt
+0
-214
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
...kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
+0
-11
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt
.../net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt
+0
-152
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt
.../kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt
+0
-39
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
...tlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
+0
-168
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/MiraiJson.kt
...rc/main/kotlin/net/mamoe/mirai/api/http/util/MiraiJson.kt
+0
-89
mirai-plugins/build.gradle
mirai-plugins/build.gradle
+0
-0
mirai-plugins/image-sender/artifact/mirai-plugin-image-sender.jar
...ugins/image-sender/artifact/mirai-plugin-image-sender.jar
+0
-0
mirai-plugins/image-sender/build.gradle.kts
mirai-plugins/image-sender/build.gradle.kts
+0
-50
mirai-plugins/image-sender/src/main/java/net/mamoe/mirai/imageplugin/ImageSenderMain.kt
.../main/java/net/mamoe/mirai/imageplugin/ImageSenderMain.kt
+0
-155
mirai-plugins/image-sender/src/main/resources/Test.kt
mirai-plugins/image-sender/src/main/resources/Test.kt
+0
-144
mirai-plugins/image-sender/src/main/resources/data.yml
mirai-plugins/image-sender/src/main/resources/data.yml
+0
-6030
mirai-plugins/image-sender/src/main/resources/plugin.yml
mirai-plugins/image-sender/src/main/resources/plugin.yml
+0
-5
No files found.
mirai-api-http/EventType_CH.md
deleted
100644 → 0
View file @
69abf7a5
#### Bot登录成功
```
json5
{
"type": "BotOnlineEvent",
"qq": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ------------------- |
| qq | Long | 登录成功的Bot的QQ号 |
#### Bot主动离线
```
json5
{
"type": "BotOfflineEventActive",
"qq": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ------------------- |
| qq | Long | 主动离线的Bot的QQ号 |
#### Bot被挤下线
```
json5
{
"type": "BotOfflineEventForce",
"qq": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ------------------- |
| qq | Long | 被挤下线的Bot的QQ号 |
#### Bot被服务器断开或因网络问题而掉线
```
json5
{
"type": "BotOfflineEventDropped",
"qq": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ----------------------------------------- |
| qq | Long | 被服务器断开或因网络问题而掉线的Bot的QQ号 |
#### Bot主动重新登录.
```
json5
{
"type": "BotReloginEvent",
"qq": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ----------------------- |
| qq | Long | 主动重新登录的Bot的QQ号 |
#### Bot在群里的权限被改变. 操作人一定是群主
```
json5
{
"type": "BotGroupPermissionChangeEvent",
"origin": "MEMBER",
"new": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "ADMINISTRATOR"
}
}
```
| 名字 | 类型 | 说明 |
| ---------------- | ------ | --------------------------------------------- |
| origin | String | Bot的原权限,OWNER、ADMINISTRATOR或MEMBER |
| new | String | Bot的新权限,OWNER、ADMINISTRATOR或MEMBER |
| group | Object | 权限改变所在的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
#### Bot被禁言
```
json5
{
"type": "BotMuteEvent",
"durationSeconds": 600,
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------------- | ------ | ------------------------------------------------ |
| durationSeconds | Int | 禁言时长,单位为秒 |
| operator | Object | 操作的管理员或群主信息 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator.group | Object | Bot被禁言所在群的信息 |
| operator.group.id | Long | 群号 |
| operator.group.name | String | 群名 |
| operator.group.permission | String | Bot在群中的权限,OWNER或ADMINISTRATOR |
#### Bot被取消禁言
```
json5
{
"type": "BotUnmuteEvent",
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------------- | ------ | ------------------------------------------------ |
| operator | Object | 操作的管理员或群主信息 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator.group | Object | Bot被取消禁言所在群的信息 |
| operator.group.id | Long | 群号 |
| operator.group.name | String | 群名 |
| operator.group.permission | String | Bot在群中的权限,OWNER或ADMINISTRATOR |
#### Bot加入了一个新群
```
json5
{
"type": "BotJoinGroupEvent",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
```
| 名字 | 类型 | 说明 |
| ---------------- | ------ | ------------------------------------------------------------ |
| group | Object | Bot新加入群的信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER(新加入群通常是Member) |
#### 某个群名改变
```
json5
{
"type": "GroupNameChangeEvent",
"origin": "miral technology",
"new": "MIRAI TECHNOLOGY",
"group": {
"id": 123456789,
"name": "MIRAI TECHNOLOGY",
"permission": "MEMBER"
},
"isByBot": false
}
```
| 名字 | 类型 | 说明 |
| ---------------- | ------- | --------------------------------------------- |
| origin | String | 原群名 |
| new | String | 新群名 |
| group | Object | 群名改名的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| isByBot | Boolean | 是否Bot进行该操作 |
#### 某群入群公告改变
```
json5
{
"type": "GroupEntranceAnnouncementChangeEvent",
"origin": "abc",
"new": "cba",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------- | ------- | --------------------------------------------- |
| origin | String | 原公告 |
| new | String | 新公告 |
| group | Object | 公告改变的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作的管理员或群主信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER或ADMINISTRATOR |
| operator.group | Object | 同group |
#### 全员禁言
```
json5
{
"type": "GroupMuteAllEvent",
"origin": false,
"new": true,
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------- | ------- | --------------------------------------------- |
| origin | Boolean | 原本是否处于全员禁言 |
| new | Boolean | 现在是否处于全员禁言 |
| group | Object | 全员禁言的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作的管理员或群主信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER或ADMINISTRATOR |
| operator.group | Object | 同group |
#### 匿名聊天
```
json5
{
"type": "GroupAllowAnonymousChatEvent",
"origin": false,
"new": true,
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------- | ------- | --------------------------------------------- |
| origin | Boolean | 原本匿名聊天是否开启 |
| new | Boolean | 现在匿名聊天是否开启 |
| group | Object | 匿名聊天状态改变的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作的管理员或群主信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER或ADMINISTRATOR |
| operator.group | Object | 同group |
#### 坦白说
```
json5
{
"type": "GroupAllowConfessTalkEvent",
"origin": false,
"new": true,
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
},
"isByBot": false
}
```
| 名字 | 类型 | 说明 |
| ---------------- | ------- | --------------------------------------------- |
| origin | Boolean | 原本坦白说是否开启 |
| new | Boolean | 现在坦白说是否开启 |
| group | Object | 坦白说状态改变的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| isByBot | Boolean | 是否Bot进行该操作 |
#### 允许群员邀请好友加群
```
json5
{
"type": "GroupAllowMemberInviteEvent",
"origin": false,
"new": true,
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ------------------- | ------- | --------------------------------------------- |
| origin | Boolean | 原本是否允许群员邀请好友加群 |
| new | Boolean | 现在是否允许群员邀请好友加群 |
| group | Object | 允许群员邀请好友加群状态改变的群信息 |
| group.id | Long | 群号 |
| group.name | String | 群名 |
| group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作的管理员或群主信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER或ADMINISTRATOR |
| operator.group | Object | 同group |
#### 新人入群的事件
```
json5
{
"type": "MemberJoinEvent",
"member": {
"id": 123456789,
"memberName": "我是新人",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------ | ------------------------------------------------------------ |
| member | Object | 新人信息 |
| member.id | Long | 新人的QQ号 |
| member.memberName | String | 新人的群名片 |
| member.permission | String | 新人在群中的权限,OWNER、ADMINISTRATOR或MEMBER(新入群通常是MEMBER) |
| member.group | Object | 新人入群的群信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
#### 成员被踢出群(该成员不是Bot)
```
json5
{
"type": "MemberLeaveEventKick",
"member": {
"id": 123456789,
"memberName": "我是被踢的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------- | --------------------------------------------- |
| member | Object | 被踢者的信息 |
| member.id | Long | 被踢者的QQ号 |
| member.memberName | String | 被踢者的群名片 |
| member.permission | String | 被踢者在群中的权限,ADMINISTRATOR或MEMBER |
| member.group | Object | 被踢者所在的群 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作的管理员或群主信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER或ADMINISTRATOR |
| operator.group | Object | 同member.group |
#### 成员主动离群(该成员不是Bot)
```
json5
{
"type": "MemberLeaveEventQuit",
"member": {
"id": 123456789,
"memberName": "我是被踢的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------ | --------------------------------------------- |
| member | Object | 退群群员的信息 |
| member.id | Long | 退群群员的QQ号 |
| member.memberName | String | 退群群员的群名片 |
| member.permission | String | 退群群员在群中的权限,ADMINISTRATOR或MEMBER |
| member.group | Object | 退群群员所在的群信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
#### 群名片改动
```
json5
{
"type": "MemberCardChangeEvent",
"origin": "origin name",
"new": "我是被改名的",
"member": {
"id": 123456789,
"memberName": "我是被改名的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
},
"operator": {
"id": 123456789,
"memberName": "我是管理员,也可能是我自己",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------- | -------------------------------------------------------- |
| member | Object | 名片改动的群员的信息 |
| member.id | Long | 名片改动的群员的QQ号 |
| member.memberName | String | 名片改动的群员的群名片 |
| member.permission | String | 名片改动的群员在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| member.group | Object | 名片改动的群员所在群的信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作者的信息,可能为该群员自己,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator.group | Object | 同member.group |
#### 群头衔改动(只有群主有操作限权)
```
json5
{
"type": "MemberSpecialTitleChangeEvent",
"origin": "origin title",
"new": "new title",
"member": {
"id": 123456789,
"memberName": "我是被改头衔的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------ | -------------------------------------------------------- |
| origin | String | 原头衔 |
| new | String | 现头衔 |
| member | Object | 头衔改动的群员的信息 |
| member.id | Long | 头衔改动的群员的QQ号 |
| member.memberName | String | 头衔改动的群员的群名片 |
| member.permission | String | 头衔改动的群员在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| member.group | Object | 头衔改动的群员所在群的信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
#### 成员权限改变的事件(该成员不可能是Bot,见BotGroupPermissionChangeEvent)
```
json5
{
"type": "MemberPermissionChangeEvent",
"origin": "MEMBER",
"new": "ADMINISTRATOR",
"member": {
"id": 123456789,
"memberName": "我是被改权限的",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------ | ------------------------------------------------- |
| origin | String | 原权限 |
| new | String | 现权限 |
| member | Object | 权限改动的群员的信息 |
| member.id | Long | 权限改动的群员的QQ号 |
| member.memberName | String | 权限改动的群员的群名片 |
| member.permission | String | 权限改动的群员在群中的权限,ADMINISTRATOR或MEMBER |
| member.group | Object | 权限改动的群员所在群的信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
#### 群成员被禁言事件(该成员不可能是Bot,见BotMuteEvent)
```
json5
{
"type": "MemberMuteEvent",
"durationSeconds": 600,
"member": {
"id": 123456789,
"memberName": "我是被禁言的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------- | ----------------------------------------------- |
| durationSeconds | Long | 禁言时长,单位为秒 |
| member | Object | 被禁言的群员的信息 |
| member.id | Long | 被禁言的群员的QQ号 |
| member.memberName | String | 被禁言的群员的群名片 |
| member.permission | String | 被禁言的群员在群中的权限,ADMINISTRATOR或MEMBER |
| member.group | Object | 被禁言的群员所在群的信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作者的信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER、ADMINISTRATOR |
| operator.group | Object | 同member.group |
#### 群成员被取消禁言事件(该成员不可能是Bot,见BotUnmuteEvent)
```
json5
{
"type": "MemberUnmuteEvent",
"member": {
"id": 123456789,
"memberName": "我是被取消禁言的",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
},
"operator": {
"id": 123456789,
"memberName": "我是管理员",
"permission": "ADMINISTRATOR",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}
```
| 名字 | 类型 | 说明 |
| ----------------------- | ------- | --------------------------------------------------- |
| member | Object | 被取消禁言的群员的信息 |
| member.id | Long | 被取消禁言的群员的QQ号 |
| member.memberName | String | 被取消禁言的群员的群名片 |
| member.permission | String | 被取消禁言的群员在群中的权限,ADMINISTRATOR或MEMBER |
| member.group | Object | 被取消禁言的群员所在群的信息 |
| member.group.id | Long | 群号 |
| member.group.name | String | 群名 |
| member.group.permission | String | Bot在群中的权限,OWNER、ADMINISTRATOR或MEMBER |
| operator | Object? | 操作者的信息,当null时为Bot操作 |
| operator.id | Long | 操作者的QQ号 |
| operator.memberName | String | 操作者的群名片 |
| operator.permission | String | 操作者在群中的权限,OWNER、ADMINISTRATOR |
| operator.group | Object | 同member.group |
mirai-api-http/README.md
deleted
100644 → 0
View file @
69abf7a5
# mirai-api-http
<b>
Mirai-API-http provides adapter for ALL langugae to access mirai via HTTP protocol.
<br>
</b>
**[中文](README_CH.md)**
### Start Session-Authorize
```
php
Path
:
/
auth
Method
:
POST
```
this verify your session to one bot and you could have full access to that bot
<br>
NOTE that only 1 bot could be control under 1 session, you could have multiple session to control all bots.
#### Request:<br>
| name | type | optional|example|note|
| --- | --- | --- | --- | --- |
| key | String |false|U9HSaDXl39ksd918273hU|MIRAI API HTTP key, this could be found after initialize|
| qq | String |false|1040400290|bot QQ number you want to access|
#### Response if success:<br>
| name | type | example|note|
| --- | --- | --- | --- |
| success |Boolean |true|if this session is authorized|
| session |String |UANSHDKSLAOISN|your session key|
#### Response if failed:<br>
| name | type | example|note|
| --- | --- | --- | --- |
| success |Boolean |false|if this session is authorized|
| session |String |null|your session key|
| error |int |0|error code|
#### Error:<br>
| code | reason|
| --- | --- |
| 0 | wrong MIRAI API HTTP key |
| 1 | unknown bot number |
without session key, you are not able to access any method below.
</br>
session key should be attached to your
<b>
cookies
</b>
like this:
| name | value |
| --- | --- |
| session |your session key here |
if you were getting HTTP error code 403, you should ask for a new session key.
\ No newline at end of file
mirai-api-http/README_CH.md
deleted
100644 → 0
View file @
69abf7a5
# mirai-api-http
<b>
Mirai-API-http 提供HTTP API供所有语言使用mirai
</b>
## 快速开始
```
kotlin
fun
main
()
{
val
bot
=
Bot
(
123456789
,
"password"
)
bot
.
login
()
MiraiHttpAPIServer
.
start
()
bot
.
join
()
}
```
## 认证相关
### 开始会话-认证(Authorize)
```
[POST] /auth
```
使用此方法验证你的身份,并返回一个会话
#### 请求:
```
json5
{
"authKey": "U9HSaDXl39ksd918273hU"
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------- | ------ | ----- | ----------------------- | ---------------------------------------------------------- |
| authKey | String | false | "U9HSaDXl39ksd918273hU" | 创建Mirai-Http-Server时生成的key,可在启动时指定或随机生成 |
#### 响应: 返回(成功):
```
json5
{
"code": 0,
"session": "UnVerifiedSession"
}
```
| 名字 | 类型 | 举例 | 说明 |
| ------- | ------ | ------------------- | --------------- |
| code | Int | 0 | 返回状态码 |
| session | String | "UnVerifiedSession" | 你的session key |
#### 状态码:
| 代码 | 原因 |
| ---- | ----------------------------- |
| 0 | 正常 |
| 1 | 错误的MIRAI API HTTP auth key |
session key 是使用以下方法必须携带的
session key 使用前必须进行校验和绑定指定的Bot,
**每个Session只能绑定一个Bot,但一个Bot可有多个Session**
session Key 在未进行校验的情况下,一定时间后将会被自动释放
### 校验Session
```
[POST] /verify
```
使用此方法校验并激活你的Session,同时将Session与一个
**已登录**
的Bot绑定
#### 请求:
```
json5
{
"sessionKey": "UnVerifiedSession",
"qq": 123456789
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ---------- | ------ | ----- | ------------------- | -------------------------- |
| sessionKey | String | false | "UnVerifiedSession" | 你的session key |
| qq | Long | false | 123456789 | Session将要绑定的Bot的qq号 |
#### 响应: 返回统一状态码(后续不再赘述)
```
json5
{
"code": 0,
"msg": "success"
}
```
| 状态码 | 原因 |
| ------ | ---------------------------------------- |
| 0 | 正常 |
| 1 | 错误的auth key |
| 2 | 指定的Bot不存在(常发生在Session认证时) |
| 3 | Session失效或不存在 |
| 4 | Session未认证(未激活) |
| 5 | 发送消息目标不存在(指定对象不存在) |
| 10 | 无操作权限,指Bot没有对应操作的限权 |
| 20 | Bot被禁言,指Bot当前无法向指定群发送消息 |
| 400 | 错误的访问,如参数错误等 |
### 释放Session
```
[POST] /release
```
使用此方式释放session及其相关资源(Bot不会被释放)
**不使用的Session应当被释放,否则Session持续保存Bot收到的消息**
**长时间(30分钟)未被使用的Session会被系统自动释放,以避免内存泄露**
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"qq": 123456789
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ---------- | ------ | ----- | -----------------| -------------------------- |
| sessionKey | String | false | "YourSessionKey" | 你的session key |
| qq | Long | false | 123456789 | 与该Session绑定Bot的QQ号码 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
> SessionKey与Bot 对应错误时将会返回状态码5:指定对象不存在
## 消息相关
### 发送好友消息
```
[POST] /sendFriendMessage
```
使用此方法向指定好友发送消息
#### 请求
```
json5
{
"sessionKey": "YourSession",
"target": 987654321,
"messageChain": [
{ "type": "Plain", "text":"hello\n" },
{ "type": "Plain", "text":"world" }
]
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | -------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| target | Long | false | 987654321 | 发送消息目标好友的QQ号 |
| quote | Long | true | 135798642 | 引用一条消息的messageId进行回复 |
| messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 |
#### 响应: 返回统一状态码(并携带messageId)
```
json5
{
"code": 0,
"msg": "success",
"messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复
}
```
### 发送群消息
```
[POST] /sendGroupMessage
```
使用此方法向指定群发送消息
#### 请求
```
json5
{
"sessionKey": "YourSession",
"target": 987654321,
"messageChain": [
{ "type": "Plain", "text":"hello\n" },
{ "type": "Plain", "text":"world" }
]
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | -------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| target | Long | false | 987654321 | 发送消息目标群的群号 |
| quote | Long | true | 135798642 | 引用一条消息的messageId进行回复 |
| messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 |
#### 响应: 返回统一状态码(并携带messageId)
```
json5
{
"code": 0,
"msg": "success",
"messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复
}
```
### 发送图片消息(通过URL)
```
[POST] /sendImageMessage
```
使用此方法向指定对象(群或好友)发送图片消息
#### 请求
```
json5
{
"sessionKey": "YourSession",
"target": 987654321,
"qq": 1234567890,
"group": 987654321,
"urls": [
"https://xxx.yyy.zzz/",
"https://aaa.bbb.ccc/"
]
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | ---------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| target | Long | true | 987654321 | 发送对象的QQ号或群号,可能存在歧义 |
| qq | Long | true | 123456789 | 发送对象的QQ号 |
| group | Long | true | 987654321 | 发送对象的群号 |
| urls | Array | false | [] | 是一个url字符串构成的数组 |
#### 响应: 图片的imageId数组
```
json5
[
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}.jpg",
"{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}.jpg"
]
```
### 图片文件上传
```
[POST] /uploadImage
```
使用此方法上传图片文件至服务器并返回ImageId
#### 请求
Content-Type:multipart/form-data
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | ---------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| type | String | false | "friend " | "friend" 或 "group" |
| img | File | false | - | 图片文件 |
#### 响应: 图片的imageId(好友图片与群聊图片Id不同)
```
{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}.jpg
```
### 撤回消息
```
[POST] /recall
```
使用此方法撤回指定消息。对于bot发送的消息,又2分钟时间限制。对于撤回群聊中群员的消息,需要有相应权限
#### 请求
```
json5
{
"sessionKey": "YourSession",
"target": 987654321
}
```
| 名字 | 类型 | 可选 | 举例 | 说明 |
| ------------ | ------ | ----- | ----------- | -------------------------------- |
| sessionKey | String | false | YourSession | 已经激活的Session |
| target | Long | false | 987654321 | 需要撤回的消息的messageId |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 获取Bot收到的消息和事件
```
[GET] /fetchMessage?sessionKey=YourSessionKey&count=10
```
使用此方法获取bot接收到的消息和各类事件
#### 请求:
| 名字 | 可选 | 举例 | 说明 |
| ---------- | ----- | -------------- | -------------------- |
| sessionKey | false | YourSessionKey | 你的session key |
| count | false | 10 | 获取消息和事件的数量 |
#### 响应: 返回JSON对象
```
json5
[{
"type": "GroupMessage", // 消息类型:GroupMessage或FriendMessage或各类Event
"messageChain": [{ // 消息链,是一个消息对象构成的数组
"type": "Source",
"uid": 123456
},{
"type": "Plain",
"text": "Miral牛逼"
}],
"sender": { // 发送者信息
"id": 123456789, // 发送者的QQ号码
"memberName": "化腾", // 发送者的群名片
"permission": "MEMBER", // 发送者的群限权:OWNER、ADMINISTRATOR或MEMBER
"group": { // 消息发送群的信息
"id": 1234567890, // 发送群的群号
"name": "Miral Technology", // 发送群的群名称
"permission": "MEMBER" // 发送群中,Bot的群限权
}
}
},{
"type": "FriendMessage", // 消息类型:GroupMessage或FriendMessage或各类Event
"messageChain": [{ // 消息链,是一个消息对象构成的数组
"type": "Source",
"uid": 123456
},{
"type": "Plain",
"text": "Miral牛逼"
}],
"sender": { // 发送者信息
"id": 1234567890, // 发送者的QQ号码
"nickName": "", // 发送者的昵称
"remark": "" // 发送者的备注
}
},{
"type": "MemberMuteEvent", // 消息类型:GroupMessage或FriendMessage或各类Event
"durationSeconds": 600,
"member":{
"id": 123456789,
"memberName": "禁言对象",
"permission": "MEMBER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
},
"operator":{
"id": 987654321,
"memberName": "群主大人",
"permission": "OWNER",
"group": {
"id": 123456789,
"name": "Miral Technology",
"permission": "MEMBER"
}
}
}]
```
### 事件类型一览
[
事件类型一览
](
EventType_CH.md
)
> 事件为Bot被动接收的信息,无法主动构建
### 消息类型一览
#### 消息是构成消息链的基本对象,目前支持的消息类型有
+
[x] At,@消息
+
[x] AtAll,@全体成员
+
[x] Face,表情消息
+
[x] Plain,文字消息
+
[x] Image,图片消息
+
[ ] Xml,Xml卡片消息
+
[ ] 敬请期待
#### Source
```
json5
{
"type": "Source",
"id": 123456
}
```
| 名字 | 类型 | 说明 |
| ---- | ---- | ------------------------------------------------------------ |
| id | Long | 消息的识别号,用于引用回复(Source类型只在群消息中返回,且永远为chain的第一个元素) |
#### At
```
json5
{
"type": "At",
"target": 123456,
"display": "@Mirai"
}
```
| 名字 | 类型 | 说明 |
| ------- | ------ | ---------------------------------------------- |
| target | Long | 群员QQ号 |
| dispaly | String | At时显示的文字,发送消息时无效,自动使用群名片 |
#### AtAll
```
json5
{
"type": "AtAll"
}
```
| 名字 | 类型 | 说明 |
| ------- | ------ | ------------------------- |
| - | - | - |
#### Face
```
json5
{
"type": "Face",
"faceId": 123
}
```
| 名字 | 类型 | 说明 |
| ------ | ---- | ---------- |
| faceId | Int | QQ表情编号 |
#### Plain
```
json5
{
"type": "Plain",
"text": "Mirai牛逼"
}
```
| 名字 | 类型 | 说明 |
| ---- | ------ | -------- |
| text | String | 文字消息 |
#### Image
```
json5
{
"type": "Image",
"imageId": "{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png" //群图片格式
//"imageId": "/f8f1ab55-bf8e-4236-b55e-955848d7069f" //好友图片格式
}
```
| 名字 | 类型 | 说明 |
| ------- | ------ | --------------------------------------- |
| imageId | String | 图片的imageId,群图片与好友图片格式不同 |
#### Xml
```
json5
{
"type": "Xml",
"xml": "XML"
}
```
| 名字 | 类型 | 说明 |
| ---- | ------ | ------- |
| xml | String | XML文本 |
## 管理相关
### 获取好友列表
使用此方法获取bot的好友列表
```
[GET] /friendList?sessionKey=YourSessionKey
```
#### 请求:
| 名字 | 可选 | 举例 | 说明 |
| ---------- | ----- | -------------- | --------------- |
| sessionKey | false | YourSessionKey | 你的session key |
#### 响应: 返回JSON对象
```
json5
[{
"id":123456789,
"nickName":"",
"remark":""
},{
"id":987654321,
"nickName":"",
"remark":""
}]
```
### 获取群列表
使用此方法获取bot的群列表
```
[GET] /groupList?sessionKey=YourSessionKey
```
#### 请求:
| 名字 | 可选 | 举例 | 说明 |
| ---------- | ----- | -------------- | --------------- |
| sessionKey | false | YourSessionKey | 你的session key |
#### 响应: 返回JSON对象
```
json5
[{
"id":123456789,
"name":"群名1",
"permission": "MEMBER"
},{
"id":987654321,
"name":"群名2",
"permission": "MEMBER"
}]
```
### 获取群成员列表
使用此方法获取bot指定群种的成员列表
```
[GET] /memberList?sessionKey=YourSessionKey
```
#### 请求:
| 名字 | 可选 | 举例 | 说明 |
| ---------- | ----- | -------------- | --------------- |
| sessionKey | false | YourSessionKey | 你的session key |
| target | false | 123456789 | 指定群的群号 |
#### 响应: 返回JSON对象
```
json5
[{
"id":1234567890,
"memberName":"",
"permission":"MEMBER",
"group":{
"id":12345,
"name":"群名1",
"permission": "MEMBER"
}
},{
"id":9876543210,
"memberName":"",
"permission":"OWNER",
"group":{
"id":54321,
"name":"群名2",
"permission": "MEMBER"
}
}]
```
### 群全体禁言
使用此方法令指定群进行全体禁言(需要有相关限权)
```
[POST] /muteAll
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
}
```
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ---------- | ----- | ------ | ---------------- | --------------- |
| sessionKey | false | String | "YourSessionKey" | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 群解除全体禁言
使用此方法令指定群解除全体禁言(需要有相关限权)
```
[POST] /unmuteAll
```
#### 请求:
同全体禁言
#### 响应
同全体禁言
### 群禁言群成员
使用此方法指定群禁言指定群员(需要有相关限权)
```
[POST] /mute
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
"memberId": 987654321,
"time": 1800
}
```
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ---------- | ----- | ------ | ---------------- | ------------------------------------- |
| sessionKey | false | String | "YourSessionKey" | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
| memberId | false | Long | 987654321 | 指定群员QQ号 |
| time | true | Int | 1800 | 禁言时长,单位为秒,最多30天,默认为0 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 群解除群成员禁言
使用此方法令指定群解除全体禁言(需要有相关限权)
```
[POST] /unmute
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
"memberId": 987654321
}
```
#### 响应
同群禁言群成员
### 移除群成员
使用此方法移除指定群成员(需要有相关限权)
```
[POST] /kick
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
"memberId": 987654321,
"msg": "您已被移出群聊"
}
```
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ---------- | ----- | ------ | ---------------- | --------------- |
| sessionKey | false | String | "YourSessionKey" | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
| memberId | false | Long | 987654321 | 指定群员QQ号 |
| msg | true | String | "" | 信息 |
#### 响应
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 群设置
使用此方法修改群设置(需要有相关限权)
```
[POST] /groupConfig
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
"config": {
"name": "群名称",
"announcement": "群公告",
"confessTalk": true,
"allowMemberInvite": true,
"autoApprove": true,
"anonymousChat": true
}
}
```
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ----------------- | ----- | ------- | ---------------- | -------------------- |
| sessionKey | false | String | "YourSessionKey" | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
| config | false | Object | {} | 群设置 |
| name | true | String | "Name" | 群名 |
| announcement | true | Boolean | true | 群公告 |
| confessTalk | true | Boolean | true | 是否开启坦白说 |
| allowMemberInvite | true | Boolean | true | 是否运行群员邀请 |
| autoApprove | true | Boolean | true | 是否开启自动审批入群 |
| anonymousChat | true | Boolean | true | 是否允许匿名聊天 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 获取群设置
使用此方法获取群设置
```
[Get] /groupConfig?sessionKey=YourSessionKey&target=123456789
```
#### 请求:
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ----------------- | ----- | ------- | ---------------- | -------------------- |
| sessionKey | false | String | YourSessionKey | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
#### 响应
```
json5
{
"name": "群名称",
"announcement": "群公告",
"confessTalk": true,
"allowMemberInvite": true,
"autoApprove": true,
"anonymousChat": true
}
```
### 修改群员资料
使用此方法修改群员资料(需要有相关限权)
```
[POST] /memberInfo
```
#### 请求:
```
json5
{
"sessionKey": "YourSessionKey",
"target": 123456789,
"memberId": 987654321,
"info": {
"name": "群名片",
"specialTitle": "群头衔"
}
}
```
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ----------------- | ----- | ------- | ---------------- | -------------------- |
| sessionKey | false | String | "YourSessionKey" | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
| memberId | false | Long | 987654321 | 群员QQ号 |
| info | false | Object | {} | 群员资料 |
| name | true | String | "Name" | 群名片,即群昵称 |
| specialTitle | true | String | "Title" | 群头衔 |
#### 响应: 返回统一状态码
```
json5
{
"code": 0,
"msg": "success"
}
```
### 获取群员资料
使用此方法获取群员资料
```
[Get] /memberInfo?sessionKey=YourSessionKey&target=123456789
```
#### 请求:
| 名字 | 可选 | 类型 | 举例 | 说明 |
| ----------------- | ----- | ------- | ---------------- | -------------------- |
| sessionKey | false | String | YourSessionKey | 你的session key |
| target | false | Long | 123456789 | 指定群的群号 |
| memberId | false | Long | 987654321 | 群员QQ号 |
#### 响应
```
json5
{
"name": "群名片",
"announcement": "群头衔"
}
```
\ No newline at end of file
mirai-api-http/build.gradle.kts
deleted
100644 → 0
View file @
69abf7a5
@
file
:
Suppress
(
"UNUSED_VARIABLE"
)
plugins
{
id
(
"kotlinx-atomicfu"
)
kotlin
(
"jvm"
)
id
(
"kotlinx-serialization"
)
}
group
=
"net.mamoe.mirai"
version
=
rootProject
.
ext
[
"mirai_version"
].
toString
()
description
=
"Mirai Http Api"
val
kotlinVersion
:
String
by
rootProject
.
ext
val
atomicFuVersion
:
String
by
rootProject
.
ext
val
coroutinesVersion
:
String
by
rootProject
.
ext
val
kotlinXIoVersion
:
String
by
rootProject
.
ext
val
coroutinesIoVersion
:
String
by
rootProject
.
ext
val
klockVersion
:
String
by
rootProject
.
ext
val
ktorVersion
:
String
by
rootProject
.
ext
val
serializationVersion
:
String
by
rootProject
.
ext
fun
kotlinx
(
id
:
String
,
version
:
String
)
=
"org.jetbrains.kotlinx:kotlinx-$id:$version"
fun
ktor
(
id
:
String
,
version
:
String
=
this
@Build_gradle
.
ktorVersion
)
=
"io.ktor:ktor-$id:$version"
kotlin
{
sourceSets
[
"main"
].
apply
{
dependencies
{
implementation
(
project
(
":mirai-core-qqandroid"
))
implementation
(
kotlin
(
"stdlib-jdk8"
,
kotlinVersion
))
implementation
(
kotlin
(
"stdlib-jdk7"
,
kotlinVersion
))
implementation
(
kotlin
(
"reflect"
,
kotlinVersion
))
implementation
(
ktor
(
"server-cio"
))
implementation
(
kotlinx
(
"io-jvm"
,
kotlinXIoVersion
))
implementation
(
ktor
(
"http-jvm"
))
implementation
(
"org.slf4j:slf4j-simple:1.7.30"
)
}
}
sourceSets
[
"test"
].
apply
{
dependencies
{
}
kotlin
.
outputDir
=
file
(
"build/classes/kotlin/jvm/test"
)
kotlin
.
setSrcDirs
(
listOf
(
"src/$name/kotlin"
))
}
sourceSets
.
all
{
languageSettings
.
enableLanguageFeature
(
"InlineClasses"
)
languageSettings
.
useExperimentalAnnotation
(
"kotlin.Experimental"
)
dependencies
{
implementation
(
kotlin
(
"stdlib"
,
kotlinVersion
))
implementation
(
kotlin
(
"serialization"
,
kotlinVersion
))
implementation
(
"org.jetbrains.kotlinx:atomicfu:$atomicFuVersion"
)
implementation
(
kotlinx
(
"io"
,
kotlinXIoVersion
))
implementation
(
kotlinx
(
"coroutines-io"
,
coroutinesIoVersion
))
implementation
(
kotlinx
(
"coroutines-core"
,
coroutinesVersion
))
implementation
(
kotlinx
(
"serialization-runtime"
,
serializationVersion
))
implementation
(
ktor
(
"server-core"
))
implementation
(
ktor
(
"http"
))
}
}
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http
import
io.ktor.application.Application
import
io.ktor.server.cio.CIO
import
io.ktor.server.engine.applicationEngineEnvironment
import
io.ktor.server.engine.connector
import
io.ktor.server.engine.embeddedServer
import
io.ktor.util.KtorExperimentalAPI
import
kotlinx.coroutines.CoroutineExceptionHandler
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.launch
import
net.mamoe.mirai.api.http.route.mirai
import
net.mamoe.mirai.utils.DefaultLogger
import
net.mamoe.mirai.utils.MiraiLogger
import
org.slf4j.helpers.NOPLoggerFactory
import
kotlin.coroutines.CoroutineContext
object
MiraiHttpAPIServer
:
CoroutineScope
{
var
logger
:
MiraiLogger
=
DefaultLogger
(
"Mirai HTTP API"
)
override
val
coroutineContext
:
CoroutineContext
=
CoroutineExceptionHandler
{
_
,
throwable
->
logger
.
error
(
throwable
)
}
init
{
SessionManager
.
authKey
=
generateSessionKey
()
//用于验证的key, 使用和SessionKey相同的方法生成, 但意义不同
}
fun
setAuthKey
(
key
:
String
)
{
SessionManager
.
authKey
=
key
}
@UseExperimental
(
KtorExperimentalAPI
::
class
)
fun
start
(
port
:
Int
=
8080
,
authKey
:
String
,
callback
:
(()
->
Unit
)?
=
null
)
{
require
(
authKey
.
length
in
8
..
128
)
{
"Expected authKey length is between 8 to 128"
}
SessionManager
.
authKey
=
authKey
// TODO: start是无阻塞的,理应获取启动状态后再执行后续代码
launch
{
embeddedServer
(
CIO
,
environment
=
applicationEngineEnvironment
{
this
.
parentCoroutineContext
=
coroutineContext
this
.
log
=
NOPLoggerFactory
().
getLogger
(
"NMYSL"
)
this
.
module
(
Application
::
mirai
)
connector
{
this
.
port
=
port
}
}).
start
(
wait
=
true
)
}
logger
.
info
(
"Http api server is running with authKey: ${SessionManager.authKey}"
)
callback
?.
invoke
()
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/Session.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http
import
kotlinx.coroutines.*
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.api.http.queue.MessageQueue
import
net.mamoe.mirai.event.Listener
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.utils.currentTimeSeconds
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
tailrec
fun
generateSessionKey
():
String
{
fun
generateRandomSessionKey
():
String
{
val
all
=
"QWERTYUIOPASDFGHJKLZXCVBNM1234567890qwertyuiopasdfghjklzxcvbnm"
return
buildString
(
capacity
=
8
)
{
repeat
(
8
)
{
append
(
all
.
random
())
}
}
}
val
key
=
generateRandomSessionKey
()
if
(!
SessionManager
.
allSession
.
containsKey
(
key
))
{
return
key
}
return
generateSessionKey
()
}
internal
object
SessionManager
{
val
allSession
:
MutableMap
<
String
,
Session
>
=
mutableMapOf
()
lateinit
var
authKey
:
String
fun
createTempSession
():
TempSession
=
TempSession
(
EmptyCoroutineContext
).
also
{
newTempSession
->
allSession
[
newTempSession
.
key
]
=
newTempSession
//设置180000ms后检测并回收
newTempSession
.
launch
{
delay
(
180000
)
allSession
[
newTempSession
.
key
]
?.
run
{
if
(
this
is
TempSession
)
closeSession
(
newTempSession
.
key
)
}
}
}
fun
createAuthedSession
(
bot
:
Bot
,
originKey
:
String
):
AuthedSession
=
AuthedSession
(
bot
,
originKey
,
EmptyCoroutineContext
).
also
{
session
->
closeSession
(
originKey
)
allSession
[
originKey
]
=
session
}
operator
fun
get
(
sessionKey
:
String
)
=
allSession
[
sessionKey
]
?.
also
{
if
(
it
is
AuthedSession
)
it
.
latestUsed
=
currentTimeSeconds
}
fun
containSession
(
sessionKey
:
String
):
Boolean
=
allSession
.
containsKey
(
sessionKey
)
fun
closeSession
(
sessionKey
:
String
)
=
allSession
.
remove
(
sessionKey
)
?.
also
{
it
.
close
()
}
fun
closeSession
(
session
:
Session
)
=
closeSession
(
session
.
key
)
}
/**
* 管理不同 Client 与 Mirai HTTP 的会话
*
* [Session] 均为内部操作用类
* @see [SessionManager]
* @author NaturalHG
*/
internal
abstract
class
Session
internal
constructor
(
coroutineContext
:
CoroutineContext
,
val
key
:
String
=
generateSessionKey
()
)
:
CoroutineScope
{
private
val
supervisorJob
=
SupervisorJob
(
coroutineContext
[
Job
])
final
override
val
coroutineContext
:
CoroutineContext
=
supervisorJob
+
coroutineContext
internal
open
fun
close
()
{
supervisorJob
.
complete
()
}
}
/**
* 任何新链接建立后分配一个[TempSession]
*
* TempSession在建立180s内没有转变为[AuthedSession]应被清除
*/
internal
class
TempSession
internal
constructor
(
coroutineContext
:
CoroutineContext
)
:
Session
(
coroutineContext
)
/**
* 任何[TempSession]认证后转化为一个[AuthedSession]
* 在这一步[AuthedSession]应该已经有assigned的bot
*/
internal
class
AuthedSession
internal
constructor
(
val
bot
:
Bot
,
originKey
:
String
,
coroutineContext
:
CoroutineContext
)
:
Session
(
coroutineContext
,
originKey
)
{
companion
object
{
const
val
CHECK_TIME
=
1800L
// 1800s aka 30min
}
val
messageQueue
=
MessageQueue
()
private
val
_listener
:
Listener
<
BotEvent
>
private
val
releaseJob
:
Job
//手动释放将会在下一次检查时回收Session
internal
var
latestUsed
=
currentTimeSeconds
init
{
_listener
=
bot
.
subscribeAlways
{
this
.
run
(
messageQueue
::
add
)
}
releaseJob
=
launch
{
while
(
true
)
{
delay
(
CHECK_TIME
*
1000
)
if
(
currentTimeSeconds
-
latestUsed
>=
CHECK_TIME
)
{
SessionManager
.
closeSession
(
this
@AuthedSession
)
break
}
}
}
}
override
fun
close
()
{
messageQueue
.
clear
()
_listener
.
complete
()
super
.
close
()
}
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.api.http.data.common.DTO
@Serializable
open
class
StateCode
(
val
code
:
Int
,
var
msg
:
String
)
:
DTO
{
object
Success
:
StateCode
(
0
,
"success"
)
// 成功
object
NoBot
:
StateCode
(
2
,
"指定Bot不存在"
)
object
IllegalSession
:
StateCode
(
3
,
"Session失效或不存在"
)
object
NotVerifySession
:
StateCode
(
4
,
"Session未认证"
)
object
NoElement
:
StateCode
(
5
,
"指定对象不存在"
)
object
PermissionDenied
:
StateCode
(
10
,
"无操作权限"
)
object
BotMuted
:
StateCode
(
20
,
"Bot被禁言"
)
// KS bug: 主构造器中不能有非字段参数 https://github.com/Kotlin/kotlinx.serialization/issues/575
@Serializable
class
IllegalAccess
()
:
StateCode
(
400
,
""
)
{
// 非法访问
constructor
(
msg
:
String
)
:
this
()
{
this
.
msg
=
msg
}
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data.common
import
kotlinx.serialization.SerialName
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.event.events.*
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
@Serializable
sealed
class
BotEventDTO
:
EventDTO
()
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
suspend
fun
BotEvent
.
toDTO
()
=
when
(
this
)
{
is
MessagePacket
<
*
,
*
>
->
toDTO
()
else
->
when
(
this
)
{
is
BotOnlineEvent
->
BotOnlineEventDTO
(
bot
.
uin
)
is
BotOfflineEvent
.
Active
->
BotOfflineEventActiveDTO
(
bot
.
uin
)
is
BotOfflineEvent
.
Force
->
BotOfflineEventForceDTO
(
bot
.
uin
,
title
,
message
)
is
BotOfflineEvent
.
Dropped
->
BotOfflineEventDroppedDTO
(
bot
.
uin
)
is
BotReloginEvent
->
BotReloginEventDTO
(
bot
.
uin
)
// is MessageSendEvent.GroupMessageSendEvent -> {}
// is MessageSendEvent.FriendMessageSendEvent -> {}
// is BeforeImageUploadEvent -> {}
// is ImageUploadEvent.Succeed -> {}
is
BotGroupPermissionChangeEvent
->
BotGroupPermissionChangeEventDTO
(
origin
,
new
,
GroupDTO
(
group
))
is
BotMuteEvent
->
BotMuteEventDTO
(
durationSeconds
,
MemberDTO
(
operator
))
is
BotUnmuteEvent
->
BotUnmuteEventDTO
(
MemberDTO
(
operator
))
is
BotJoinGroupEvent
->
BotJoinGroupEventDTO
(
GroupDTO
(
group
))
// is GroupSettingChangeEvent<*> -> {} // 不知道会改什么
is
GroupNameChangeEvent
->
GroupNameChangeEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
isByBot
)
is
GroupEntranceAnnouncementChangeEvent
->
GroupEntranceAnnouncementChangeEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
operator
?.
let
(
::
MemberDTO
))
is
GroupMuteAllEvent
->
GroupMuteAllEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
operator
?.
let
(
::
MemberDTO
))
is
GroupAllowAnonymousChatEvent
->
GroupAllowAnonymousChatEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
operator
?.
let
(
::
MemberDTO
))
is
GroupAllowConfessTalkEvent
->
GroupAllowConfessTalkEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
isByBot
)
is
GroupAllowMemberInviteEvent
->
GroupAllowMemberInviteEventDTO
(
origin
,
new
,
GroupDTO
(
group
),
operator
?.
let
(
::
MemberDTO
))
is
MemberJoinEvent
->
MemberJoinEventDTO
(
MemberDTO
(
member
))
is
MemberLeaveEvent
.
Kick
->
MemberLeaveEventKickDTO
(
MemberDTO
(
member
),
operator
?.
let
(
::
MemberDTO
))
is
MemberLeaveEvent
.
Quit
->
MemberLeaveEventQuitDTO
(
MemberDTO
(
member
))
is
MemberCardChangeEvent
->
MemberCardChangeEventDTO
(
origin
,
new
,
MemberDTO
(
member
),
operator
?.
let
(
::
MemberDTO
))
is
MemberSpecialTitleChangeEvent
->
MemberSpecialTitleChangeEventDTO
(
origin
,
new
,
MemberDTO
(
member
))
is
MemberPermissionChangeEvent
->
MemberPermissionChangeEventDTO
(
origin
,
new
,
MemberDTO
(
member
))
is
MemberMuteEvent
->
MemberMuteEventDTO
(
durationSeconds
,
MemberDTO
(
member
),
operator
?.
let
(
::
MemberDTO
))
is
MemberUnmuteEvent
->
MemberUnmuteEventDTO
(
MemberDTO
(
member
),
operator
?.
let
(
::
MemberDTO
))
else
->
IgnoreEventDTO
}
}
@Serializable
@SerialName
(
"BotOnlineEvent"
)
data class
BotOnlineEventDTO
(
val
qq
:
Long
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotOfflineEventActive"
)
data class
BotOfflineEventActiveDTO
(
val
qq
:
Long
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotOfflineEventForce"
)
data class
BotOfflineEventForceDTO
(
val
qq
:
Long
,
val
title
:
String
,
val
message
:
String
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotOfflineEventDropped"
)
data class
BotOfflineEventDroppedDTO
(
val
qq
:
Long
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotReloginEvent"
)
data class
BotReloginEventDTO
(
val
qq
:
Long
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotGroupPermissionChangeEvent"
)
data class
BotGroupPermissionChangeEventDTO
(
val
origin
:
MemberPermission
,
val
new
:
MemberPermission
,
val
group
:
GroupDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotMuteEvent"
)
data class
BotMuteEventDTO
(
val
durationSeconds
:
Int
,
val
operator
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotUnmuteEvent"
)
data class
BotUnmuteEventDTO
(
val
operator
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"BotJoinGroupEvent"
)
data class
BotJoinGroupEventDTO
(
val
group
:
GroupDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupNameChangeEvent"
)
data class
GroupNameChangeEventDTO
(
val
origin
:
String
,
val
new
:
String
,
val
group
:
GroupDTO
,
val
isByBot
:
Boolean
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupEntranceAnnouncementChangeEvent"
)
data class
GroupEntranceAnnouncementChangeEventDTO
(
val
origin
:
String
,
val
new
:
String
,
val
group
:
GroupDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupMuteAllEvent"
)
data class
GroupMuteAllEventDTO
(
val
origin
:
Boolean
,
val
new
:
Boolean
,
val
group
:
GroupDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupAllowAnonymousChatEvent"
)
data class
GroupAllowAnonymousChatEventDTO
(
val
origin
:
Boolean
,
val
new
:
Boolean
,
val
group
:
GroupDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupAllowConfessTalkEvent"
)
data class
GroupAllowConfessTalkEventDTO
(
val
origin
:
Boolean
,
val
new
:
Boolean
,
val
group
:
GroupDTO
,
val
isByBot
:
Boolean
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"GroupAllowMemberInviteEvent"
)
data class
GroupAllowMemberInviteEventDTO
(
val
origin
:
Boolean
,
val
new
:
Boolean
,
val
group
:
GroupDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberJoinEvent"
)
data class
MemberJoinEventDTO
(
val
member
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberLeaveEventKick"
)
data class
MemberLeaveEventKickDTO
(
val
member
:
MemberDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberLeaveEventQuit"
)
data class
MemberLeaveEventQuitDTO
(
val
member
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberCardChangeEvent"
)
data class
MemberCardChangeEventDTO
(
val
origin
:
String
,
val
new
:
String
,
val
member
:
MemberDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberSpecialTitleChangeEvent"
)
data class
MemberSpecialTitleChangeEventDTO
(
val
origin
:
String
,
val
new
:
String
,
val
member
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberPermissionChangeEvent"
)
data class
MemberPermissionChangeEventDTO
(
val
origin
:
MemberPermission
,
val
new
:
MemberPermission
,
val
member
:
MemberDTO
)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberMuteEvent"
)
data class
MemberMuteEventDTO
(
val
durationSeconds
:
Int
,
val
member
:
MemberDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
@Serializable
@SerialName
(
"MemberUnmuteEvent"
)
data class
MemberUnmuteEventDTO
(
val
member
:
MemberDTO
,
val
operator
:
MemberDTO
?)
:
BotEventDTO
()
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data.common
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
@Serializable
abstract
class
ContactDTO
:
DTO
{
abstract
val
id
:
Long
}
@Serializable
data class
QQDTO
(
override
val
id
:
Long
,
val
nickName
:
String
,
val
remark
:
String
)
:
ContactDTO
()
{
// TODO: queryProfile.nickname & queryRemark.value not support now
constructor
(
qq
:
QQ
)
:
this
(
qq
.
id
,
""
,
""
)
}
@Serializable
data class
MemberDTO
(
override
val
id
:
Long
,
val
memberName
:
String
,
val
permission
:
MemberPermission
,
val
group
:
GroupDTO
)
:
ContactDTO
()
{
constructor
(
member
:
Member
)
:
this
(
member
.
id
,
member
.
nameCardOrNick
,
member
.
permission
,
GroupDTO
(
member
.
group
)
)
}
@Serializable
data class
GroupDTO
(
override
val
id
:
Long
,
val
name
:
String
,
val
permission
:
MemberPermission
)
:
ContactDTO
()
{
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
constructor
(
group
:
Group
)
:
this
(
group
.
id
,
group
.
name
,
group
.
botPermission
)
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data.common
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
net.mamoe.mirai.api.http.AuthedSession
interface
DTO
@Serializable
data class
AuthDTO
(
val
authKey
:
String
)
:
DTO
@Serializable
abstract
class
VerifyDTO
:
DTO
{
abstract
val
sessionKey
:
String
@Transient
internal
lateinit
var
session
:
AuthedSession
// 反序列化验证成功后传入
}
@Serializable
abstract
class
EventDTO
:
DTO
object
IgnoreEventDTO
:
EventDTO
()
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data.common
import
kotlinx.serialization.SerialName
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.message.uploadImage
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
java.net.URL
/*
* DTO data class
* */
// MessagePacket
@Serializable
@SerialName
(
"FriendMessage"
)
data class
FriendMessagePacketDTO
(
val
sender
:
QQDTO
)
:
MessagePacketDTO
()
@Serializable
@SerialName
(
"GroupMessage"
)
data class
GroupMessagePacketDTO
(
val
sender
:
MemberDTO
)
:
MessagePacketDTO
()
// Message
@Serializable
@SerialName
(
"Source"
)
data class
MessageSourceDTO
(
val
id
:
Long
)
:
MessageDTO
()
@Serializable
@SerialName
(
"At"
)
data class
AtDTO
(
val
target
:
Long
,
val
display
:
String
=
""
)
:
MessageDTO
()
@Serializable
@SerialName
(
"AtAll"
)
data class
AtAllDTO
(
val
target
:
Long
=
0
)
:
MessageDTO
()
// target为保留字段
@Serializable
@SerialName
(
"Face"
)
data class
FaceDTO
(
val
faceId
:
Int
)
:
MessageDTO
()
@Serializable
@SerialName
(
"Plain"
)
data class
PlainDTO
(
val
text
:
String
)
:
MessageDTO
()
@Serializable
@SerialName
(
"Image"
)
data class
ImageDTO
(
val
imageId
:
String
?
=
null
,
val
url
:
String
?
=
null
)
:
MessageDTO
()
@Serializable
@SerialName
(
"Xml"
)
data class
XmlDTO
(
val
xml
:
String
)
:
MessageDTO
()
@Serializable
@SerialName
(
"Unknown"
)
object
UnknownMessageDTO
:
MessageDTO
()
/*
* Abstract Class
* */
@Serializable
sealed
class
MessagePacketDTO
:
EventDTO
()
{
lateinit
var
messageChain
:
MessageChainDTO
}
typealias
MessageChainDTO
=
List
<
MessageDTO
>
@Serializable
sealed
class
MessageDTO
:
DTO
/*
Extend function
*/
suspend
fun
MessagePacket
<*,
*>.
toDTO
()
=
when
(
this
)
{
is
FriendMessage
->
FriendMessagePacketDTO
(
QQDTO
(
sender
))
is
GroupMessage
->
GroupMessagePacketDTO
(
MemberDTO
(
sender
))
else
->
IgnoreEventDTO
}.
apply
{
if
(
this
is
MessagePacketDTO
)
{
// 将MessagePacket中的所有Message转为DTO对象,并添加到messageChain
// foreachContent会忽略MessageSource,一次主动获取
messageChain
=
mutableListOf
(
messageDTO
(
message
[
MessageSource
])).
apply
{
message
.
foreachContent
{
content
->
messageDTO
(
content
).
takeUnless
{
it
==
UnknownMessageDTO
}
?.
let
(
::
add
)
}
}
// else: `this` is bot event
}
}
suspend
fun
MessageChainDTO
.
toMessageChain
(
contact
:
Contact
)
=
buildMessageChain
{
this
@
toMessageChain
.
forEach
{
it
.
toMessage
(
contact
)
?.
let
(
::
add
)
}
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
suspend
fun
MessagePacket
<*,
*>.
messageDTO
(
message
:
Message
)
=
when
(
message
)
{
is
MessageSource
->
MessageSourceDTO
(
message
.
id
)
is
At
->
AtDTO
(
message
.
target
,
message
.
display
)
is
AtAll
->
AtAllDTO
(
0L
)
is
Face
->
FaceDTO
(
message
.
id
)
is
PlainText
->
PlainDTO
(
message
.
stringValue
)
is
Image
->
ImageDTO
(
message
.
imageId
,
message
.
url
())
is
XMLMessage
->
XmlDTO
(
message
.
stringValue
)
else
->
UnknownMessageDTO
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
suspend
fun
MessageDTO
.
toMessage
(
contact
:
Contact
)
=
when
(
this
)
{
is
AtDTO
->
At
((
contact
as
Group
)[
target
])
is
AtAllDTO
->
AtAll
is
FaceDTO
->
Face
(
faceId
)
is
PlainDTO
->
PlainText
(
text
)
is
ImageDTO
->
when
{
!
imageId
.
isNullOrBlank
()
->
Image
(
imageId
)
!
url
.
isNullOrBlank
()
->
contact
.
uploadImage
(
URL
(
url
))
else
->
null
}
is
XmlDTO
->
XMLMessage
(
xml
)
is
MessageSourceDTO
,
is
UnknownMessageDTO
->
null
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/exceptions.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.data
/**
* 错误请求. 抛出这个异常后将会返回错误给一个请求
*/
@Suppress
(
"unused"
)
open
class
IllegalAccessException
:
Exception
{
override
val
message
:
String
get
()
=
super
.
message
!!
constructor
(
message
:
String
)
:
super
(
message
,
null
)
constructor
(
cause
:
Throwable
)
:
super
(
cause
.
toString
(),
cause
)
constructor
(
message
:
String
,
cause
:
Throwable
?)
:
super
(
message
,
cause
)
}
/**
* Session失效或不存在
*/
object
IllegalSessionException
:
IllegalAccessException
(
"Session失效或不存在"
)
/**
* Session未激活
*/
object
NotVerifiedSessionException
:
IllegalAccessException
(
"Session未激活"
)
/**
* 指定Bot不存在
*/
object
NoSuchBotException
:
IllegalAccessException
(
"指定Bot不存在"
)
/**
* 错误参数
*/
class
IllegalParamException
(
message
:
String
)
:
IllegalAccessException
(
message
)
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.queue
import
net.mamoe.mirai.api.http.data.common.EventDTO
import
net.mamoe.mirai.api.http.data.common.IgnoreEventDTO
import
net.mamoe.mirai.api.http.data.common.toDTO
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.utils.firstKey
import
java.util.concurrent.ConcurrentLinkedDeque
class
MessageQueue
:
ConcurrentLinkedDeque
<
BotEvent
>()
{
val
cacheSize
=
4096
val
cache
=
LinkedHashMap
<
Long
,
MessagePacket
<
*
,
*
>>()
suspend
fun
fetch
(
size
:
Int
):
List
<
EventDTO
>
{
var
count
=
size
val
ret
=
ArrayList
<
EventDTO
>(
count
)
while
(!
this
.
isEmpty
()
&&
count
>
0
)
{
val
event
=
pop
()
event
.
toDTO
().
also
{
if
(
it
!=
IgnoreEventDTO
)
{
ret
.
add
(
it
)
count--
}
}
if
(
event
is
MessagePacket
<
*
,
*
>)
{
addQuoteCache
(
event
)
}
}
return
ret
}
fun
cache
(
messageId
:
Long
)
=
cache
[
messageId
]
?:
throw
NoSuchElementException
()
fun
addQuoteCache
(
msg
:
MessagePacket
<
*
,
*
>)
{
cache
[
msg
.
message
[
MessageSource
].
id
]
=
msg
if
(
cache
.
size
>
cacheSize
)
{
cache
.
remove
(
cache
.
firstKey
())
}
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
import
io.ktor.application.Application
import
io.ktor.application.call
import
io.ktor.routing.routing
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.api.http.AuthedSession
import
net.mamoe.mirai.api.http.SessionManager
import
net.mamoe.mirai.api.http.data.NoSuchBotException
import
net.mamoe.mirai.api.http.data.StateCode
import
net.mamoe.mirai.api.http.data.common.DTO
import
net.mamoe.mirai.api.http.data.common.VerifyDTO
import
kotlin.coroutines.EmptyCoroutineContext
fun
Application
.
authModule
()
{
routing
{
miraiAuth
(
"/auth"
)
{
if
(
it
.
authKey
!=
SessionManager
.
authKey
)
{
call
.
respondStateCode
(
StateCode
(
1
,
"Auth Key错误"
))
}
else
{
call
.
respondDTO
(
AuthRetDTO
(
0
,
SessionManager
.
createTempSession
().
key
))
}
}
miraiVerify
<
BindDTO
>(
"/verify"
,
verifiedSessionKey
=
false
)
{
val
bot
=
getBotOrThrow
(
it
.
qq
)
SessionManager
.
createAuthedSession
(
bot
,
it
.
sessionKey
)
call
.
respondStateCode
(
StateCode
.
Success
)
}
miraiVerify
<
BindDTO
>(
"/release"
)
{
val
bot
=
getBotOrThrow
(
it
.
qq
)
val
session
=
SessionManager
[
it
.
sessionKey
]
as
AuthedSession
if
(
bot
.
uin
==
session
.
bot
.
uin
)
{
SessionManager
.
closeSession
(
it
.
sessionKey
)
call
.
respondStateCode
(
StateCode
.
Success
)
}
else
{
throw
NoSuchElementException
()
}
}
}
}
@Serializable
private
data class
AuthRetDTO
(
val
code
:
Int
,
val
session
:
String
)
:
DTO
@Serializable
private
data class
BindDTO
(
override
val
sessionKey
:
String
,
val
qq
:
Long
)
:
VerifyDTO
()
private
fun
getBotOrThrow
(
qq
:
Long
)
=
try
{
Bot
.
getInstance
(
qq
)
}
catch
(
e
:
NoSuchElementException
)
{
throw
NoSuchBotException
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
import
io.ktor.application.Application
import
io.ktor.application.ApplicationCall
import
io.ktor.application.call
import
io.ktor.application.install
import
io.ktor.features.CallLogging
import
io.ktor.features.DefaultHeaders
import
io.ktor.http.ContentType
import
io.ktor.http.HttpMethod
import
io.ktor.http.HttpStatusCode
import
io.ktor.http.content.PartData
import
io.ktor.request.receive
import
io.ktor.response.defaultTextContentType
import
io.ktor.response.respond
import
io.ktor.response.respondText
import
io.ktor.routing.Route
import
io.ktor.routing.route
import
io.ktor.util.pipeline.ContextDsl
import
io.ktor.util.pipeline.PipelineContext
import
net.mamoe.mirai.api.http.AuthedSession
import
net.mamoe.mirai.api.http.SessionManager
import
net.mamoe.mirai.api.http.TempSession
import
net.mamoe.mirai.api.http.data.*
import
net.mamoe.mirai.api.http.data.common.AuthDTO
import
net.mamoe.mirai.api.http.data.common.DTO
import
net.mamoe.mirai.api.http.data.common.VerifyDTO
import
net.mamoe.mirai.api.http.util.jsonParseOrNull
import
net.mamoe.mirai.api.http.util.toJson
import
net.mamoe.mirai.contact.PermissionDeniedException
import
org.slf4j.helpers.NOPLoggerFactory
fun
Application
.
mirai
()
{
install
(
DefaultHeaders
)
install
(
CallLogging
)
{
logger
=
NOPLoggerFactory
().
getLogger
(
"NMSL"
)
}
authModule
()
messageModule
()
infoModule
()
groupManageModule
()
}
/**
* Auth,处理http server的验证
* 为闭包传入一个AuthDTO对象
*/
@ContextDsl
internal
fun
Route
.
miraiAuth
(
path
:
String
,
body
:
suspend
PipelineContext
<
Unit
,
ApplicationCall
>.(
AuthDTO
)
->
Unit
):
Route
{
return
route
(
path
,
HttpMethod
.
Post
)
{
intercept
{
val
dto
=
context
.
receiveDTO
<
AuthDTO
>()
?:
throw
IllegalParamException
(
"参数格式错误"
)
this
.
body
(
dto
)
}
}
}
/**
* Get,用于获取bot的属性
* 验证请求参数中sessionKey参数的有效性
*/
@ContextDsl
internal
fun
Route
.
miraiGet
(
path
:
String
,
body
:
suspend
PipelineContext
<
Unit
,
ApplicationCall
>.(
AuthedSession
)
->
Unit
):
Route
{
return
route
(
path
,
HttpMethod
.
Get
)
{
intercept
{
val
sessionKey
=
call
.
parameters
[
"sessionKey"
]
?:
throw
IllegalParamException
(
"参数格式错误"
)
if
(!
SessionManager
.
containSession
(
sessionKey
))
throw
IllegalSessionException
when
(
val
session
=
SessionManager
[
sessionKey
])
{
is
TempSession
->
throw
NotVerifiedSessionException
is
AuthedSession
->
this
.
body
(
session
)
}
}
}
}
/**
* Verify,用于处理bot的行为请求
* 验证数据传输对象(DTO)中是否包含sessionKey字段
* 且验证sessionKey的有效性
*
* @param verifiedSessionKey 是否验证sessionKey是否被激活
*
* it 为json解析出的DTO对象
*/
@ContextDsl
internal
inline
fun
<
reified
T
:
VerifyDTO
>
Route
.
miraiVerify
(
path
:
String
,
verifiedSessionKey
:
Boolean
=
true
,
crossinline
body
:
suspend
PipelineContext
<
Unit
,
ApplicationCall
>.(
T
)
->
Unit
):
Route
{
return
route
(
path
,
HttpMethod
.
Post
)
{
intercept
{
val
dto
=
context
.
receiveDTO
<
T
>()
?:
throw
IllegalParamException
(
"参数格式错误"
)
SessionManager
[
dto
.
sessionKey
]
?.
let
{
when
{
it
is
TempSession
&&
verifiedSessionKey
->
throw
NotVerifiedSessionException
it
is
AuthedSession
->
dto
.
session
=
it
}
}
?:
throw
IllegalSessionException
this
.
body
(
dto
)
}
}
}
/**
* 统一捕获并处理异常
*/
internal
inline
fun
Route
.
intercept
(
crossinline
blk
:
suspend
PipelineContext
<
Unit
,
ApplicationCall
>.()
->
Unit
)
=
handle
{
try
{
blk
(
this
)
}
catch
(
e
:
NoSuchBotException
)
{
// Bot不存在
call
.
respondStateCode
(
StateCode
.
NoBot
)
}
catch
(
e
:
IllegalSessionException
)
{
// Session过期
call
.
respondStateCode
(
StateCode
.
IllegalSession
)
}
catch
(
e
:
NotVerifiedSessionException
)
{
// Session未认证
call
.
respondStateCode
(
StateCode
.
NotVerifySession
)
}
catch
(
e
:
NoSuchElementException
)
{
// 指定对象不存在
call
.
respondStateCode
(
StateCode
.
NoElement
)
}
catch
(
e
:
PermissionDeniedException
)
{
// 缺少权限
call
.
respondStateCode
(
StateCode
.
PermissionDenied
)
}
catch
(
e
:
IllegalStateException
)
{
// Bot被禁言
call
.
respondStateCode
(
StateCode
.
BotMuted
)
}
catch
(
e
:
IllegalAccessException
)
{
// 错误访问
call
.
respondStateCode
(
StateCode
(
400
,
e
.
message
),
HttpStatusCode
.
BadRequest
)
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
call
.
respond
(
HttpStatusCode
.
InternalServerError
,
e
.
message
!!
)
}
}
/*
extend function
*/
internal
suspend
inline
fun
<
reified
T
:
StateCode
>
ApplicationCall
.
respondStateCode
(
code
:
T
,
status
:
HttpStatusCode
=
HttpStatusCode
.
OK
)
=
respondJson
(
code
.
toJson
(
StateCode
.
serializer
()),
status
)
internal
suspend
inline
fun
<
reified
T
:
DTO
>
ApplicationCall
.
respondDTO
(
dto
:
T
,
status
:
HttpStatusCode
=
HttpStatusCode
.
OK
)
=
respondJson
(
dto
.
toJson
(),
status
)
internal
suspend
fun
ApplicationCall
.
respondJson
(
json
:
String
,
status
:
HttpStatusCode
=
HttpStatusCode
.
OK
)
=
respondText
(
json
,
defaultTextContentType
(
ContentType
(
"application"
,
"json"
)),
status
)
internal
suspend
inline
fun
<
reified
T
:
DTO
>
ApplicationCall
.
receiveDTO
():
T
?
=
receive
<
String
>().
jsonParseOrNull
()
fun
PipelineContext
<
Unit
,
ApplicationCall
>.
illegalParam
(
expectingType
:
String
?,
paramName
:
String
,
actualValue
:
String
?
=
call
.
parameters
[
paramName
]
):
Nothing
=
throw
IllegalParamException
(
"Illegal param. A $expectingType is required for `$paramName` while `$actualValue` is given"
)
@Suppress
(
"IMPLICIT_CAST_TO_ANY"
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
internal
inline
fun
<
reified
R
>
PipelineContext
<
Unit
,
ApplicationCall
>.
paramOrNull
(
name
:
String
):
R
=
when
(
R
::
class
)
{
Byte
::
class
-> call.parameters[name]?.to
Byte
()
Int
::
class
-> call.parameters[name]?.to
Int
()
Short
::
class
-> call.parameters[name]?.to
Short
()
Float
::
class
-> call.parameters[name]?.to
Float
()
Long
::
class
-> call.parameters[name]?.to
Long
()
Double
::
class
-> call.parameters[name]?.to
Double
()
Boolean
::
class
-> when (call.parameters[name]) {
"true" -> true
"false" -> false
"0" -> false
"1" -> true
null -> null
else -> illegal
Param
(
"boolean"
,
name
)
}
String
::
class
-> call.parameters[name]
UByte
::
class
-> call.parameters[name]?.to
UByte
()
UInt
::
class
-> call.parameters[name]?.to
UInt
()
UShort
::
class
-> call.parameters[name]?.to
UShort
()
else
->
error
(
name
::
class
.
simpleName
+
" is not supported"
)
}
as
R
?:
illegalParam
(
R
::
class
.
simpleName
,
name
)
/**
* multi part
*/
internal
fun
List
<
PartData
>.
value
(
name
:
String
)
=
try
{
(
filter
{
it
.
name
==
name
}[
0
]
as
PartData
.
FormItem
).
value
}
catch
(
e
:
Exception
)
{
throw
IllegalParamException
(
"参数格式错误"
)
}
internal
fun
List
<
PartData
>.
file
(
name
:
String
)
=
try
{
filter
{
it
.
name
==
name
}[
0
]
as
?
PartData
.
FileItem
}
catch
(
e
:
Exception
)
{
throw
IllegalParamException
(
"参数格式错误"
)
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
import
io.ktor.application.Application
import
io.ktor.application.call
import
io.ktor.routing.routing
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.api.http.data.StateCode
import
net.mamoe.mirai.api.http.data.common.DTO
import
net.mamoe.mirai.api.http.data.common.VerifyDTO
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Member
fun
Application
.
groupManageModule
()
{
routing
{
/**
* 禁言(需要相关权限)
*/
miraiVerify
<
MuteDTO
>(
"/muteAll"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
).
isMuteAll
=
true
call
.
respondStateCode
(
StateCode
.
Success
)
}
miraiVerify
<
MuteDTO
>(
"/unmuteAll"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
).
isMuteAll
=
false
call
.
respondStateCode
(
StateCode
.
Success
)
}
miraiVerify
<
MuteDTO
>(
"/mute"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
)[
it
.
memberId
].
mute
(
it
.
time
)
call
.
respondStateCode
(
StateCode
.
Success
)
}
miraiVerify
<
MuteDTO
>(
"/unmute"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
).
members
[
it
.
memberId
].
unmute
()
call
.
respondStateCode
(
StateCode
.
Success
)
}
/**
* 移出群聊(需要相关权限)
*/
miraiVerify
<
KickDTO
>(
"/kick"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
)[
it
.
memberId
].
kick
(
it
.
msg
)
call
.
respondStateCode
(
StateCode
.
Success
)
}
/**
* 群设置(需要相关权限)
*/
miraiGet
(
"/groupConfig"
)
{
val
group
=
it
.
bot
.
getGroup
(
paramOrNull
(
"target"
))
call
.
respondDTO
(
GroupDetailDTO
(
group
))
}
miraiVerify
<
GroupConfigDTO
>(
"/groupConfig"
)
{
dto
->
val
group
=
dto
.
session
.
bot
.
getGroup
(
dto
.
target
)
with
(
dto
.
config
)
{
name
?.
let
{
group
.
name
=
it
}
announcement
?.
let
{
group
.
entranceAnnouncement
=
it
}
confessTalk
?.
let
{
group
.
isConfessTalkEnabled
=
it
}
allowMemberInvite
?.
let
{
group
.
isAllowMemberInvite
=
it
}
// TODO: 待core接口实现设置可改
// autoApprove?.let { group.autoApprove = it }
// anonymousChat?.let { group.anonymousChat = it }
}
call
.
respondStateCode
(
StateCode
.
Success
)
}
/**
* 群员信息管理(需要相关权限)
*/
miraiGet
(
"/memberInfo"
)
{
val
member
=
it
.
bot
.
getGroup
(
paramOrNull
(
"target"
))[
paramOrNull
(
"memberId"
)]
call
.
respondDTO
(
MemberDetailDTO
(
member
))
}
miraiVerify
<
MemberInfoDTO
>(
"/memberInfo"
)
{
dto
->
val
member
=
dto
.
session
.
bot
.
getGroup
(
dto
.
target
)[
dto
.
memberId
]
with
(
dto
.
info
)
{
name
?.
let
{
member
.
nameCard
=
it
}
specialTitle
?.
let
{
member
.
specialTitle
=
it
}
}
call
.
respondStateCode
(
StateCode
.
Success
)
}
}
}
@Serializable
private
data class
MuteDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
,
val
memberId
:
Long
=
0
,
val
time
:
Int
=
0
)
:
VerifyDTO
()
@Serializable
private
data class
KickDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
,
val
memberId
:
Long
,
val
msg
:
String
=
""
)
:
VerifyDTO
()
@Serializable
private
data class
GroupConfigDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
,
val
config
:
GroupDetailDTO
)
:
VerifyDTO
()
@Serializable
private
data class
GroupDetailDTO
(
val
name
:
String
?
=
null
,
val
announcement
:
String
?
=
null
,
val
confessTalk
:
Boolean
?
=
null
,
val
allowMemberInvite
:
Boolean
?
=
null
,
val
autoApprove
:
Boolean
?
=
null
,
val
anonymousChat
:
Boolean
?
=
null
)
:
DTO
{
constructor
(
group
:
Group
)
:
this
(
group
.
name
,
group
.
entranceAnnouncement
,
group
.
isConfessTalkEnabled
,
group
.
isAllowMemberInvite
,
group
.
isAutoApproveEnabled
,
group
.
isAnonymousChatEnabled
)
}
@Serializable
private
data class
MemberInfoDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
,
val
memberId
:
Long
,
val
info
:
MemberDetailDTO
)
:
VerifyDTO
()
@Serializable
private
data class
MemberDetailDTO
(
val
name
:
String
?
=
null
,
val
specialTitle
:
String
?
=
null
)
:
DTO
{
constructor
(
member
:
Member
)
:
this
(
member
.
nameCard
,
member
.
specialTitle
)
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
import
io.ktor.application.Application
import
io.ktor.application.call
import
io.ktor.routing.routing
import
net.mamoe.mirai.api.http.data.common.GroupDTO
import
net.mamoe.mirai.api.http.data.common.MemberDTO
import
net.mamoe.mirai.api.http.data.common.QQDTO
import
net.mamoe.mirai.api.http.util.toJson
import
net.mamoe.mirai.contact.toMutableList
fun
Application
.
infoModule
()
{
routing
{
miraiGet
(
"/friendList"
)
{
val
ls
=
it
.
bot
.
qqs
.
toMutableList
().
map
{
qq
->
QQDTO
(
qq
)
}
call
.
respondJson
(
ls
.
toJson
())
}
miraiGet
(
"/groupList"
)
{
val
ls
=
it
.
bot
.
groups
.
toMutableList
().
map
{
group
->
GroupDTO
(
group
)
}
call
.
respondJson
(
ls
.
toJson
())
}
miraiGet
(
"/memberList"
)
{
val
ls
=
it
.
bot
.
getGroup
(
paramOrNull
(
"target"
)).
members
.
toMutableList
().
map
{
member
->
MemberDTO
(
member
)
}
call
.
respondJson
(
ls
.
toJson
())
}
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.route
import
io.ktor.application.Application
import
io.ktor.application.call
import
io.ktor.http.HttpStatusCode
import
io.ktor.http.content.readAllParts
import
io.ktor.http.content.streamProvider
import
io.ktor.request.receiveMultipart
import
io.ktor.response.respond
import
io.ktor.response.respondText
import
io.ktor.routing.post
import
io.ktor.routing.routing
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.api.http.AuthedSession
import
net.mamoe.mirai.api.http.SessionManager
import
net.mamoe.mirai.api.http.data.*
import
net.mamoe.mirai.api.http.data.common.DTO
import
net.mamoe.mirai.api.http.data.common.MessageChainDTO
import
net.mamoe.mirai.api.http.data.common.VerifyDTO
import
net.mamoe.mirai.api.http.data.common.toMessageChain
import
net.mamoe.mirai.api.http.util.toJson
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.message.uploadImage
import
java.net.URL
fun
Application
.
messageModule
()
{
routing
{
miraiGet
(
"/fetchMessage"
)
{
val
count
:
Int
=
paramOrNull
(
"count"
)
val
fetch
=
it
.
messageQueue
.
fetch
(
count
)
call
.
respondJson
(
fetch
.
toJson
())
}
suspend
fun
<
C
:
Contact
>
sendMessage
(
quote
:
QuoteReplyToSend
?,
messageChain
:
MessageChain
,
target
:
C
):
MessageReceipt
<
out
Contact
>
{
val
send
=
if
(
quote
==
null
)
{
messageChain
}
else
{
(
quote
+
messageChain
).
toChain
()
}
return
target
.
sendMessage
(
send
)
}
miraiVerify
<
SendDTO
>(
"/sendFriendMessage"
)
{
val
quote
=
it
.
quote
?.
let
{
q
->
it
.
session
.
messageQueue
.
cache
(
q
).
run
{
this
[
MessageSource
].
quote
(
sender
)
}}
it
.
session
.
bot
.
getFriend
(
it
.
target
).
apply
{
val
receipt
=
sendMessage
(
quote
,
it
.
messageChain
.
toMessageChain
(
this
),
this
)
receipt
.
source
.
ensureSequenceIdAvailable
()
it
.
session
.
messageQueue
.
addQuoteCache
(
FriendMessage
(
bot
.
selfQQ
,
receipt
.
source
.
toChain
()))
call
.
respondDTO
(
SendRetDTO
(
messageId
=
receipt
.
source
.
id
))
}
}
miraiVerify
<
SendDTO
>(
"/sendGroupMessage"
)
{
val
quote
=
it
.
quote
?.
let
{
q
->
it
.
session
.
messageQueue
.
cache
(
q
).
run
{
this
[
MessageSource
].
quote
(
sender
)
}}
it
.
session
.
bot
.
getGroup
(
it
.
target
).
apply
{
val
receipt
=
sendMessage
(
quote
,
it
.
messageChain
.
toMessageChain
(
this
),
this
)
receipt
.
source
.
ensureSequenceIdAvailable
()
it
.
session
.
messageQueue
.
addQuoteCache
(
GroupMessage
(
""
,
botPermission
,
botAsMember
,
receipt
.
source
.
toChain
()))
call
.
respondDTO
(
SendRetDTO
(
messageId
=
receipt
.
source
.
id
))
}
}
miraiVerify
<
SendImageDTO
>(
"sendImageMessage"
)
{
val
bot
=
it
.
session
.
bot
val
contact
=
when
{
it
.
target
!=
null
->
bot
[
it
.
target
]
it
.
qq
!=
null
->
bot
.
getFriend
(
it
.
qq
)
it
.
group
!=
null
->
bot
.
getGroup
(
it
.
group
)
else
->
throw
IllegalParamException
(
"target、qq、group不可全为null"
)
}
val
ls
=
it
.
urls
.
map
{
url
->
contact
.
uploadImage
(
URL
(
url
))
}
contact
.
sendMessage
(
MessageChain
(
ls
))
call
.
respondJson
(
ls
.
map
{
image
->
image
.
imageId
}.
toJson
())
}
// TODO: 重构
post
(
"uploadImage"
)
{
val
parts
=
call
.
receiveMultipart
().
readAllParts
()
val
sessionKey
=
parts
.
value
(
"sessionKey"
)
if
(!
SessionManager
.
containSession
(
sessionKey
))
throw
IllegalSessionException
val
session
=
try
{
SessionManager
[
sessionKey
]
as
AuthedSession
}
catch
(
e
:
TypeCastException
)
{
throw
NotVerifiedSessionException
}
val
type
=
parts
.
value
(
"type"
)
parts
.
file
(
"img"
)
?.
apply
{
val
image
=
streamProvider
().
use
{
when
(
type
)
{
"group"
->
session
.
bot
.
groups
.
firstOrNull
()
?.
uploadImage
(
it
)
"friend"
->
session
.
bot
.
qqs
.
firstOrNull
()
?.
uploadImage
(
it
)
else
->
null
}
}
image
?.
apply
{
call
.
respondText
(
imageId
)
}
?:
throw
IllegalAccessException
(
"图片上传错误"
)
}
?:
throw
IllegalAccessException
(
"未知错误"
)
}
miraiVerify
<
RecallDTO
>(
"recall"
)
{
it
.
session
.
messageQueue
.
cache
(
it
.
target
).
apply
{
it
.
session
.
bot
.
recall
(
get
(
MessageSource
))
}
call
.
respondStateCode
(
StateCode
.
Success
)
}
}
}
@Serializable
private
data class
SendDTO
(
override
val
sessionKey
:
String
,
val
quote
:
Long
?
=
null
,
val
target
:
Long
,
val
messageChain
:
MessageChainDTO
)
:
VerifyDTO
()
@Serializable
private
data class
SendImageDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
?
=
null
,
val
qq
:
Long
?
=
null
,
val
group
:
Long
?
=
null
,
val
urls
:
List
<
String
>
)
:
VerifyDTO
()
@Serializable
private
class
SendRetDTO
(
val
code
:
Int
=
0
,
val
msg
:
String
=
"success"
,
val
messageId
:
Long
)
:
DTO
@Serializable
private
data class
RecallDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
)
:
VerifyDTO
()
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/MiraiJson.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.api.http.util
import
kotlinx.serialization.*
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.modules.SerializersModule
import
net.mamoe.mirai.api.http.data.common.*
// 解析失败时直接返回null,由路由判断响应400状态
@UseExperimental
(
ImplicitReflectionSerializer
::
class
)
inline
fun
<
reified
T
:
Any
>
String
.
jsonParseOrNull
(
serializer
:
DeserializationStrategy
<
T
>?
=
null
):
T
?
=
try
{
if
(
serializer
==
null
)
MiraiJson
.
json
.
parse
(
this
)
else
Json
.
parse
(
this
)
}
catch
(
e
:
Exception
)
{
null
}
@UseExperimental
(
ImplicitReflectionSerializer
::
class
,
UnstableDefault
::
class
)
inline
fun
<
reified
T
:
Any
>
T
.
toJson
(
serializer
:
SerializationStrategy
<
T
>?
=
null
):
String
=
if
(
serializer
==
null
)
MiraiJson
.
json
.
stringify
(
this
)
else
MiraiJson
.
json
.
stringify
(
serializer
,
this
)
// 序列化列表时,stringify需要使用的泛型是T,而非List<T>
// 因为使用的stringify的stringify(objs: List<T>)重载
@UseExperimental
(
ImplicitReflectionSerializer
::
class
,
UnstableDefault
::
class
)
inline
fun
<
reified
T
:
Any
>
List
<
T
>.
toJson
(
serializer
:
SerializationStrategy
<
List
<
T
>>?
=
null
):
String
=
if
(
serializer
==
null
)
MiraiJson
.
json
.
stringify
(
this
)
else
MiraiJson
.
json
.
stringify
(
serializer
,
this
)
/**
* Json解析规则,需要注册支持的多态的类
*/
object
MiraiJson
{
val
json
=
Json
(
context
=
SerializersModule
{
polymorphic
(
EventDTO
.
serializer
())
{
GroupMessagePacketDTO
::
class
with
GroupMessagePacketDTO
.
serializer
()
FriendMessagePacketDTO
::
class
with
FriendMessagePacketDTO
.
serializer
()
BotOnlineEventDTO
::
class
with
BotOnlineEventDTO
.
serializer
()
BotOfflineEventActiveDTO
::
class
with
BotOfflineEventActiveDTO
.
serializer
()
BotOfflineEventForceDTO
::
class
with
BotOfflineEventForceDTO
.
serializer
()
BotOfflineEventDroppedDTO
::
class
with
BotOfflineEventDroppedDTO
.
serializer
()
BotReloginEventDTO
::
class
with
BotReloginEventDTO
.
serializer
()
BotGroupPermissionChangeEventDTO
::
class
with
BotGroupPermissionChangeEventDTO
.
serializer
()
BotMuteEventDTO
::
class
with
BotMuteEventDTO
.
serializer
()
BotUnmuteEventDTO
::
class
with
BotUnmuteEventDTO
.
serializer
()
BotJoinGroupEventDTO
::
class
with
BotJoinGroupEventDTO
.
serializer
()
GroupNameChangeEventDTO
::
class
with
GroupNameChangeEventDTO
.
serializer
()
GroupEntranceAnnouncementChangeEventDTO
::
class
with
GroupEntranceAnnouncementChangeEventDTO
.
serializer
()
GroupMuteAllEventDTO
::
class
with
GroupMuteAllEventDTO
.
serializer
()
GroupAllowAnonymousChatEventDTO
::
class
with
GroupAllowAnonymousChatEventDTO
.
serializer
()
GroupAllowConfessTalkEventDTO
::
class
with
GroupAllowConfessTalkEventDTO
.
serializer
()
GroupAllowMemberInviteEventDTO
::
class
with
GroupAllowMemberInviteEventDTO
.
serializer
()
MemberJoinEventDTO
::
class
with
MemberJoinEventDTO
.
serializer
()
MemberLeaveEventKickDTO
::
class
with
MemberLeaveEventKickDTO
.
serializer
()
MemberLeaveEventQuitDTO
::
class
with
MemberLeaveEventQuitDTO
.
serializer
()
MemberCardChangeEventDTO
::
class
with
MemberCardChangeEventDTO
.
serializer
()
MemberSpecialTitleChangeEventDTO
::
class
with
MemberSpecialTitleChangeEventDTO
.
serializer
()
MemberPermissionChangeEventDTO
::
class
with
MemberPermissionChangeEventDTO
.
serializer
()
MemberMuteEventDTO
::
class
with
MemberMuteEventDTO
.
serializer
()
MemberUnmuteEventDTO
::
class
with
MemberUnmuteEventDTO
.
serializer
()
}
// Message Polymorphic
// polymorphic(MessageDTO.serializer()) {
// MessageSourceDTO::class with MessageSourceDTO.serializer()
// AtDTO::class with AtDTO.serializer()
// AtAllDTO::class with AtAllDTO.serializer()
// FaceDTO::class with FaceDTO.serializer()
// PlainDTO::class with PlainDTO.serializer()
// ImageDTO::class with ImageDTO.serializer()
// XmlDTO::class with XmlDTO.serializer()
// UnknownMessageDTO::class with UnknownMessageDTO.serializer()
// }
})
}
\ No newline at end of file
mirai-plugins/build.gradle
deleted
100644 → 0
View file @
69abf7a5
mirai-plugins/image-sender/artifact/mirai-plugin-image-sender.jar
deleted
100644 → 0
View file @
69abf7a5
File deleted
mirai-plugins/image-sender/build.gradle.kts
deleted
100644 → 0
View file @
69abf7a5
plugins
{
kotlin
(
"jvm"
)
java
id
(
"com.github.johnrengelman.shadow"
)
}
version
=
"1.0.0"
val
kotlinVersion
:
String
by
rootProject
.
ext
val
atomicFuVersion
:
String
by
rootProject
.
ext
val
coroutinesVersion
:
String
by
rootProject
.
ext
val
kotlinXIoVersion
:
String
by
rootProject
.
ext
val
coroutinesIoVersion
:
String
by
rootProject
.
ext
val
serializationVersion
:
String
by
rootProject
.
ext
val
klockVersion
:
String
by
rootProject
.
ext
val
ktorVersion
:
String
by
rootProject
.
ext
kotlin
{
sourceSets
{
all
{
languageSettings
.
enableLanguageFeature
(
"InlineClasses"
)
languageSettings
.
useExperimentalAnnotation
(
"kotlin.Experimental"
)
}
}
}
fun
kotlinx
(
id
:
String
,
version
:
String
)
=
"org.jetbrains.kotlinx:kotlinx-$id:$version"
fun
ktor
(
id
:
String
,
version
:
String
)
=
"io.ktor:ktor-$id:$version"
dependencies
{
api
(
project
(
":mirai-core"
))
api
(
project
(
":mirai-console"
))
runtimeOnly
(
files
(
"../mirai-core/build/classes/kotlin/jvm/main"
))
// classpath is not added correctly by IDE
api
(
kotlin
(
"stdlib"
,
kotlinVersion
))
api
(
kotlinx
(
"io-jvm"
,
kotlinXIoVersion
))
api
(
kotlinx
(
"io"
,
kotlinXIoVersion
))
api
(
kotlinx
(
"coroutines-io"
,
coroutinesIoVersion
))
api
(
kotlinx
(
"coroutines-core"
,
coroutinesVersion
))
api
(
"org.jsoup:jsoup:1.12.1"
)
api
(
group
=
"com.alibaba"
,
name
=
"fastjson"
,
version
=
"1.2.62"
)
}
tasks
.
withType
<
JavaCompile
>()
{
options
.
encoding
=
"UTF-8"
}
\ No newline at end of file
mirai-plugins/image-sender/src/main/java/net/mamoe/mirai/imageplugin/ImageSenderMain.kt
deleted
100644 → 0
View file @
69abf7a5
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.imageplugin
import
kotlinx.coroutines.*
import
net.mamoe.mirai.console.MiraiConsole
import
net.mamoe.mirai.console.command.registerCommand
import
net.mamoe.mirai.console.plugins.Config
import
net.mamoe.mirai.console.plugins.ConfigSection
import
net.mamoe.mirai.console.plugins.PluginBase
import
net.mamoe.mirai.console.plugins.withDefaultWriteSave
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.sendMessage
import
net.mamoe.mirai.event.events.BotOnlineEvent
import
net.mamoe.mirai.event.events.MemberPermissionChangeEvent
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeGroupMessages
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.sendTo
import
net.mamoe.mirai.message.upload
import
net.mamoe.mirai.message.uploadAsImage
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
org.jsoup.Jsoup
import
java.awt.RenderingHints
import
java.awt.image.BufferedImage
import
javax.imageio.ImageIO
class
ImageSenderMain
:
PluginBase
()
{
lateinit
var
images
:
Config
lateinit
var
normal
:
List
<
ConfigSection
>
lateinit
var
r18
:
List
<
ConfigSection
>
val
config
by
lazy
{
loadConfig
(
"setting.yml"
)
}
val
Normal_Image_Trigger
by
config
.
withDefaultWriteSave
{
"色图"
}
val
R18_Image_Trigger
by
config
.
withDefaultWriteSave
{
"不够色"
}
val
Image_Resize_Max_Width_Height
by
config
.
withDefaultWriteSave
{
800
}
val
groupsAllowNormal
by
lazy
{
config
.
getLongList
(
"Allow_Normal_Image_Groups"
).
toMutableList
()
}
val
groupsAllowR18
by
lazy
{
config
.
getLongList
(
"Allow_R18_Image_Groups"
).
toMutableList
()
}
override
fun
onDisable
()
{
config
[
"Allow_R18_Image_Groups"
]
=
groupsAllowR18
config
[
"Allow_Normal_Image_Groups"
]
=
groupsAllowNormal
config
.
save
()
}
override
fun
onEnable
()
{
logger
.
info
(
"Image Sender plugin enabled"
)
registerCommands
()
subscribeAlways
<
MemberPermissionChangeEvent
>
{
logger
.
info
(
"${this.bot.uin} login succeed, it will be controlled by Image Sender Plugin"
)
this
.
bot
.
subscribeGroupMessages
{
(
contains
(
Normal_Image_Trigger
))
{
sendImage
(
subject
,
normal
.
random
())
}
(
contains
(
R18_Image_Trigger
))
{
sendImage
(
subject
,
r18
.
random
())
}
}
}
}
private
fun
sendImage
(
contact
:
Contact
,
configSection
:
ConfigSection
)
{
launch
{
try
{
logger
.
info
(
"正在推送图片"
)
getImage
(
contact
,
configSection
.
getString
(
"url"
),
configSection
.
getString
(
"pid"
),
800
).
plus
(
configSection
.
getString
(
"tags"
)).
sendTo
(
contact
)
}
catch
(
e
:
Exception
)
{
contact
.
sendMessage
(
e
.
message
?:
"unknown error"
)
}
}
}
private
suspend
fun
getImage
(
contact
:
Contact
,
url
:
String
,
pid
:
String
,
maxWidthOrHeight
:
Int
):
Image
{
val
bodyStream
=
withTimeoutOrNull
(
20
*
1000
)
{
withContext
(
Dispatchers
.
IO
)
{
Jsoup
.
connect
(
url
)
.
followRedirects
(
true
)
.
timeout
(
180
_000
)
.
ignoreContentType
(
true
)
.
userAgent
(
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; ja-jp) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27"
)
.
referrer
(
"https://www.pixiv.net/member_illust.php?mode=medium&illust_id=$pid"
)
.
ignoreHttpErrors
(
true
)
.
maxBodySize
(
100000000
)
.
execute
().
also
{
check
(
it
.
statusCode
()
==
200
)
{
"Failed to download image"
}
}
}
}
?.
bodyStream
()
?:
error
(
"Failed to download image"
)
if
(
maxWidthOrHeight
<
1
)
{
return
bodyStream
.
uploadAsImage
(
contact
)
}
val
image
=
withContext
(
Dispatchers
.
IO
)
{
ImageIO
.
read
(
bodyStream
)
}
if
(
image
.
width
.
coerceAtLeast
(
image
.
height
)
<=
maxWidthOrHeight
)
{
return
image
.
upload
(
contact
)
}
val
rate
=
(
maxWidthOrHeight
.
toFloat
()
/
image
.
width
.
coerceAtLeast
(
image
.
height
))
val
newWidth
=
(
image
.
width
*
rate
).
toInt
()
val
newHeight
=
(
image
.
height
*
rate
).
toInt
()
return
withContext
(
Dispatchers
.
IO
)
{
val
dimg
=
BufferedImage
(
newWidth
,
newHeight
,
image
.
type
)
val
g
=
dimg
.
createGraphics
()
g
.
setRenderingHint
(
RenderingHints
.
KEY_INTERPOLATION
,
RenderingHints
.
VALUE_INTERPOLATION_BILINEAR
)
g
.
drawImage
(
image
,
0
,
0
,
newWidth
,
newHeight
,
0
,
0
,
image
.
width
,
image
.
height
,
null
)
g
.
dispose
()
dimg
}.
upload
(
contact
)
}
override
fun
onLoad
()
{
logger
.
info
(
"loading local image data"
)
try
{
images
=
getResourcesConfig
(
"data.yml"
)
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
logger
.
info
(
"无法加载本地图片"
)
}
logger
.
info
(
"本地图片版本"
+
images
.
getString
(
"version"
))
r18
=
images
.
getConfigSectionList
(
"R18"
)
normal
=
images
.
getConfigSectionList
(
"normal"
)
logger
.
info
(
"Normal * "
+
normal
.
size
)
logger
.
info
(
"R18 * "
+
r18
.
size
)
}
fun
registerCommands
()
{
registerCommand
{
}
}
}
\ No newline at end of file
mirai-plugins/image-sender/src/main/resources/Test.kt
deleted
100644 → 0
View file @
69abf7a5
import
com.alibaba.fastjson.JSONObject
import
com.google.gson.JsonObject
import
net.mamoe.mirai.console.plugins.*
import
net.mamoe.mirai.utils.cryptor.contentToString
import
org.jsoup.Connection
import
org.jsoup.Jsoup
import
java.io.File
import
kotlin.concurrent.thread
object
Data
{
val
section
=
(
File
(
System
.
getProperty
(
"user.dir"
)
+
"/setu.yml"
)).
loadAsConfig
()
val
abstract
=
section
.
getStringList
(
"abstract"
).
toMutableList
()
val
R18
=
section
.
getConfigSectionList
(
"R18"
).
toMutableList
()
val
normal
=
section
.
getConfigSectionList
(
"normal"
).
toMutableList
()
fun
init
()
{
section
.
setIfAbsent
(
"abstract"
,
mutableListOf
<
String
>())
section
.
setIfAbsent
(
"R18"
,
mutableListOf
<
ConfigSection
>())
section
.
setIfAbsent
(
"Normal"
,
mutableListOf
<
ConfigSection
>())
}
fun
save
()
{
section
[
"abstract"
]
=
abstract
section
[
"R18"
]
=
R18
section
[
"normal"
]
=
normal
section
.
save
()
}
}
fun
main
()
{
val
abstract_file
=
(
File
(
System
.
getProperty
(
"user.dir"
)
+
"/abstractSetu.yml"
)).
loadAsConfig
()
abstract_file
.
setIfAbsent
(
"R18"
,
mutableListOf
<
ConfigSection
>())
abstract_file
.
setIfAbsent
(
"normal"
,
mutableListOf
<
ConfigSection
>())
val
r18
=
abstract_file
.
getConfigSectionList
(
"R18"
).
toMutableList
()
val
normal
=
abstract_file
.
getConfigSectionList
(
"normal"
).
toMutableList
()
Data
.
R18
.
forEach
{
val
forbid
=
with
(
it
.
getString
(
"tags"
))
{
this
.
contains
(
"初音ミク"
)
||
this
.
contains
(
"VOCALOID"
)
||
this
.
contains
(
"Miku"
)
||
this
.
contains
(
"东方"
)
||
this
.
contains
(
"東方"
)
}
if
(
forbid
)
{
println
(
"过滤掉了一张图"
)
}
else
{
r18
.
add
(
ConfigSectionImpl
().
apply
{
this
[
"pid"
]
=
it
[
"pid"
]
!!
this
[
"author"
]
=
it
[
"author"
]
!!
this
[
"uid"
]
=
it
[
"uid"
]
!!
this
[
"tags"
]
=
it
[
"tags"
]
!!
this
[
"url"
]
=
it
[
"url"
]
!!
}
)
}
}
Data
.
normal
.
forEach
{
val
forbid
=
with
(
it
.
getString
(
"tags"
))
{
this
.
contains
(
"初音ミク"
)
||
this
.
contains
(
"VOCALOID"
)
||
this
.
contains
(
"Miku"
)
||
this
.
contains
(
"东方"
)
||
this
.
contains
(
"東方"
)
}
if
(
forbid
)
{
println
(
"过滤掉了一张图"
)
}
else
{
normal
.
add
(
ConfigSectionImpl
().
apply
{
this
[
"pid"
]
=
it
[
"pid"
]
!!
this
[
"author"
]
=
it
[
"author"
]
!!
this
[
"uid"
]
=
it
[
"uid"
]
!!
this
[
"tags"
]
=
it
[
"tags"
]
!!
this
[
"url"
]
=
it
[
"url"
]
!!
}
)
}
}
abstract_file
.
set
(
"R18"
,
r18
)
abstract_file
.
set
(
"normal"
,
normal
)
abstract_file
.
save
()
/**
Data.init()
Runtime.getRuntime().addShutdownHook(thread(start = false) {
Data.save()
})
while (true){
try {
val val0 = JSONObject.parseObject(Jsoup
.connect("https://api.lolicon.app/setu/")
.ignoreContentType(true)
.method(Connection.Method.GET)
.data("r18","1")
.data("num","10")
.execute().body())
val val1 = val0.getJSONArray("data")
for(index in 0 until val1.size - 1){
val content = val1.getJSONObject(index)
val pid = content.getString("pid")
if(Data.abstract.contains(pid)){
println("获取到了一张重复图$pid")
continue
}
val configSection = ConfigSectionImpl()
val isR18 = content.getBoolean("r18")
configSection["author"] = content.getString("author")
configSection["pid"] = pid
configSection["uid"] = content.getInteger("uid")
configSection["width"] = content.getInteger("width")
configSection["height"] = content.getInteger("height")
configSection["tags"] = content.getJSONArray("tags").map {
it.toString()
}.joinToString(",")
configSection["url"] = content.getString("url")
if(isR18){
Data.R18.add(configSection)
print("获取到了一张R18")
}else{
Data.normal.add(configSection)
print("获取到了一张Normal")
}
Data.abstract.add(pid)
println(configSection.contentToString())
}
}catch (e:Exception){
println(e.message)
}
Data.save()
println("SAVED")
Thread.sleep(1000)
}
*/
}
\ No newline at end of file
mirai-plugins/image-sender/src/main/resources/data.yml
deleted
100644 → 0
View file @
69abf7a5
This source diff could not be displayed because it is too large. You can
view the blob
instead.
mirai-plugins/image-sender/src/main/resources/plugin.yml
deleted
100644 → 0
View file @
69abf7a5
name
:
ImageSender
main
:
net.mamoe.mirai.imageplugin.ImageSenderMain
version
:
1.0.0
author
:
不想写代码
info
:
a demo[hso] plugin of mirai
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment