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
Expand all
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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 diff is collapsed.
Click to expand it.
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