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
4b9900e0
Commit
4b9900e0
authored
Feb 03, 2020
by
ryoii
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
base framework
parent
30d41f6e
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
590 additions
and
33 deletions
+590
-33
mirai-api-http/README_CH.md
mirai-api-http/README_CH.md
+22
-25
mirai-api-http/build.gradle.kts
mirai-api-http/build.gradle.kts
+1
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
...ain/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
+42
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/Session.kt
...-http/src/main/kotlin/net/mamoe/mirai/api/http/Session.kt
+23
-8
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt
...p/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt
+9
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
...rc/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
+39
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt
...-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt
+42
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
...rc/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
+86
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
...src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
+35
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
...ain/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
+17
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
.../kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
+42
-0
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
+191
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
...kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
+2
-0
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
...tlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
+39
-0
No files found.
mirai-api-http/README_CH.md
View file @
4b9900e0
...
...
@@ -6,9 +6,8 @@ Mirai-API-http 提供HTTP API供所有语言使用mirai<br>
### 开始会话-认证(Authorize)
```
php
路径
:
/
auth
方法
:
POST
```
[POST] /auth
```
使用此方法验证你的会话连接, 并将这个会话绑定一个BOT
<br>
注意: 每个会话只能绑定一个BOT.
...
...
@@ -25,31 +24,29 @@ Mirai-API-http 提供HTTP API供所有语言使用mirai<br>
| 名字 | 类型 | 举例 | 说明|
| --- | --- | --- | --- |
|
success |Boolean |true|是否验证成功
|
|
code |Int |0|返回状态
|
| session |String |UANSHDKSLAOISN|你的session key|
#### 返回(失败):<br>
| name | type | example|note|
| --- | --- | --- | --- |
| success |Boolean |false|是否验证成功|
| session |String |null|你的session key|
| error |int |0|错误码|
#### 错误码:<br>
#### 状态码:<br>
| 代码 | 原因|
| --- | --- |
| 0 |
错误的MIRAI API HTTP key
|
| 1 |
试图绑定不存在的bot
|
| 0 |
正常
|
| 1 |
错误的MIRAI API HTTP key
|
| 2 | 试图绑定不存在的bot|
session key 是使用以下方法必须携带的
</br>
session key 需要被以cookie的形式上报
<b>
cookies
</b>
:
| name | value
|
| --- | --- |
| session |your session key here |
| 名字 | 值
|
| --- | --- |
| session |your session key here |
如果出现HTTP 403错误码,代表session key已过期, 需要重新获取
### 发送好友消息
```
[POST] /sendFriendMessage
```
mirai-api-http/build.gradle.kts
View file @
4b9900e0
...
...
@@ -42,6 +42,7 @@ kotlin {
implementation
(
ktor
(
"server-cio"
))
implementation
(
kotlinx
(
"io-jvm"
,
kotlinXIoVersion
))
implementation
(
ktor
(
"http-jvm"
))
implementation
(
"org.slf4j:slf4j-simple:1.7.26"
)
}
}
...
...
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/MiraiHttpAPIServer.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http
import
io.ktor.application.Application
import
io.ktor.server.cio.CIO
import
io.ktor.server.engine.embeddedServer
import
io.ktor.util.KtorExperimentalAPI
import
net.mamoe.mirai.api.http.route.mirai
import
net.mamoe.mirai.utils.DefaultLogger
object
MiraiHttpAPIServer
{
private
val
logger
=
DefaultLogger
(
"Mirai HTTP API"
)
init
{
SessionManager
.
authKey
=
generateSessionKey
()
//用于验证的key, 使用和SessionKey相同的方法生成, 但意义不同
}
@UseExperimental
(
KtorExperimentalAPI
::
class
)
fun
start
(
port
:
Int
=
8080
,
authKey
:
String
?
=
null
,
callback
:
(()
->
Unit
)?
=
null
)
{
authKey
?.
apply
{
if
(
authKey
.
length
in
8
..
128
)
{
SessionManager
.
authKey
=
authKey
}
else
{
logger
.
error
(
"Expected authKey length is between 8 to 128"
)
}
}
// TODO: start是无阻塞的,理应获取启动状态后再执行后续代码
try
{
embeddedServer
(
CIO
,
port
,
module
=
Application
::
mirai
).
start
()
logger
.
info
(
"Http api server is running with authKey: ${SessionManager.authKey}"
)
callback
?.
invoke
()
}
catch
(
e
:
Exception
)
{
logger
.
error
(
"Http api server launch error"
)
}
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net
.mamoe.mirai.api.
http/Session.kt
→
mirai-api-http/src/main/kotlin/net
/mamoe/mirai/api/
http/Session.kt
View file @
4b9900e0
package
net.mamoe.mirai.api.http
import
kotlinx.coroutines.*
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.json.JsonConfiguration
import
java.lang.StringBuilder
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.api.http.queue.MessageQueue
import
net.mamoe.mirai.event.Listener
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.message.MessagePacket
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.EmptyCoroutineContext
...
...
@@ -44,6 +46,10 @@ object SessionManager {
}
}
operator
fun
get
(
sessionKey
:
String
)
=
allSession
[
sessionKey
]
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
)
...
...
@@ -69,7 +75,7 @@ abstract class Session internal constructor(
val
key
:
String
=
generateSessionKey
()
internal
fun
close
(){
internal
open
fun
close
(){
supervisorJob
.
complete
()
}
}
...
...
@@ -89,11 +95,20 @@ class TempSession internal constructor(coroutineContext: CoroutineContext) : Ses
* 任何[TempSession]认证后转化为一个[AuthedSession]
* 在这一步[AuthedSession]应该已经有assigned的bot
*/
class
AuthedSession
internal
constructor
(
val
botNumber
:
Int
,
coroutineContext
:
CoroutineContext
):
Session
(
coroutineContext
){
}
class
AuthedSession
internal
constructor
(
val
bot
:
Bot
,
coroutineContext
:
CoroutineContext
):
Session
(
coroutineContext
){
val
messageQueue
=
MessageQueue
()
private
val
_listener
:
Listener
<
MessagePacket
<
*
,
*
>>
init
{
bot
.
subscribeMessages
{
_listener
=
always
{
this
.
run
(
messageQueue
::
add
)
}
}
}
override
fun
close
()
{
_listener
.
complete
()
super
.
close
()
}
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.dto
import
kotlinx.serialization.Serializable
@Serializable
data class
AuthDTO
(
val
authKey
:
String
)
:
DTO
@Serializable
data class
AuthResDTO
(
val
code
:
Int
,
val
session
:
String
)
:
DTO
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.dto
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.contact.QQ
@Serializable
abstract
class
ContactDTO
:
DTO
{
abstract
val
id
:
Long
}
@Serializable
data class
QQDTO
(
override
val
id
:
Long
,
val
nickName
:
String
,
val
remark
:
String
)
:
ContactDTO
()
suspend
fun
QQDTO
(
qq
:
QQ
):
QQDTO
=
QQDTO
(
qq
.
id
,
qq
.
queryProfile
().
nickname
,
qq
.
queryRemark
().
value
)
@Serializable
data class
MemberDTO
(
override
val
id
:
Long
,
val
memberName
:
String
=
""
,
val
group
:
GroupDTO
,
val
permission
:
MemberPermission
)
:
ContactDTO
()
fun
MemberDTO
(
member
:
Member
,
name
:
String
=
""
):
MemberDTO
=
MemberDTO
(
member
.
id
,
name
,
GroupDTO
(
member
.
group
),
member
.
permission
)
@Serializable
data class
GroupDTO
(
override
val
id
:
Long
,
val
name
:
String
)
:
ContactDTO
()
fun
GroupDTO
(
group
:
Group
):
GroupDTO
=
GroupDTO
(
group
.
id
,
group
.
name
)
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.dto
import
kotlinx.serialization.*
import
kotlinx.serialization.json.Json
import
kotlinx.serialization.modules.SerializersModule
interface
DTO
object
MiraiJson
{
val
json
=
Json
(
context
=
SerializersModule
{
polymorphic
(
MessagePacketDTO
.
serializer
())
{
GroupMessagePacketDTO
::
class
with
GroupMessagePacketDTO
.
serializer
()
FriendMessagePacketDTO
::
class
with
FriendMessagePacketDTO
.
serializer
()
}
})
}
// 解析失败时直接返回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
MiraiJson
.
json
.
parse
(
serializer
,
this
)
}
catch
(
e
:
Exception
)
{
throw
e
}
@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
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
Json
.
stringify
(
serializer
,
this
)
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.dto
import
kotlinx.serialization.SerialName
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.GroupMessage
import
net.mamoe.mirai.message.MessagePacket
import
net.mamoe.mirai.message.data.*
/*
DTO data class
*/
@Serializable
@SerialName
(
"FriendMessage"
)
data class
FriendMessagePacketDTO
(
val
sender
:
QQDTO
)
:
MessagePacketDTO
()
@Serializable
@SerialName
(
"GroupMessage"
)
data class
GroupMessagePacketDTO
(
val
sender
:
MemberDTO
)
:
MessagePacketDTO
()
@Serializable
data class
MessageDTO
(
val
type
:
MessageType
,
val
data
:
String
)
:
DTO
typealias
MessageChainDTO
=
Array
<
MessageDTO
>
@Serializable
abstract
class
MessagePacketDTO
:
DTO
{
lateinit
var
messageChain
:
MessageChainDTO
companion
object
{
val
EMPTY
=
@SerialName
(
"UnknownMessage"
)
object
:
MessagePacketDTO
()
{}
}
}
/*
Extend function
*/
suspend
fun
MessagePacket
<*,
*>.
toDTO
():
MessagePacketDTO
=
when
(
this
)
{
is
FriendMessage
->
FriendMessagePacketDTO
(
QQDTO
(
sender
))
is
GroupMessage
->
GroupMessagePacketDTO
(
MemberDTO
(
sender
,
senderName
))
else
->
MessagePacketDTO
.
EMPTY
}.
apply
{
messageChain
=
Array
(
message
.
size
){
message
[
it
].
toDTO
()
}}
fun
MessageChainDTO
.
toMessageChain
()
=
MessageChain
().
apply
{
this
@
toMessageChain
.
forEach
{
add
(
it
.
toMessage
())
}
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
fun
Message
.
toDTO
()
=
when
(
this
)
{
is
At
->
MessageDTO
(
MessageType
.
AT
,
target
.
toString
())
is
Face
->
MessageDTO
(
MessageType
.
FACE
,
id
.
value
.
toString
())
is
PlainText
->
MessageDTO
(
MessageType
.
PLAIN
,
stringValue
)
// is Image -> MessageDTO(MessageType.IMAGE, ???)
is
Image
->
MessageDTO
(
MessageType
.
IMAGE
,
"NOT SUPPORT IMAGE NOW"
)
is
XMLMessage
->
MessageDTO
(
MessageType
.
XML
,
stringValue
)
else
->
MessageDTO
(
MessageType
.
UNKNOWN
,
"not support type"
)
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
fun
MessageDTO
.
toMessage
()
=
when
(
type
)
{
MessageType
.
AT
->
At
(
data
.
toLong
())
MessageType
.
FACE
->
Face
(
FaceId
(
data
.
toUByte
()))
MessageType
.
PLAIN
->
PlainText
(
data
)
// MessageType.IMAGE -> Image(???)
MessageType
.
IMAGE
->
PlainText
(
data
)
MessageType
.
XML
->
XMLMessage
(
data
)
MessageType
.
UNKNOWN
->
PlainText
(
data
)
}
/*
Enum
*/
// TODO: will be replace by [net.mamoe.mirai.message.MessageType]
enum
class
MessageType
{
AT
,
FACE
,
PLAIN
,
IMAGE
,
XML
,
UNKNOWN
,
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.dto
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Transient
import
net.mamoe.mirai.api.http.AuthedSession
@Serializable
abstract
class
VerifyDTO
:
DTO
{
abstract
val
sessionKey
:
String
@Transient
lateinit
var
session
:
AuthedSession
// 反序列化验证后传入
}
@Serializable
data class
BindDTO
(
override
val
sessionKey
:
String
,
val
qq
:
Long
)
:
VerifyDTO
()
// 写成data class并继承DTO接口是为了返回时的形式统一
@Serializable
open
class
StateCodeDTO
(
val
code
:
Int
,
val
msg
:
String
)
:
DTO
{
companion
object
{
val
SUCCESS
=
StateCodeDTO
(
0
,
"success"
)
// 成功
// val AUTH_WRONG = CodeDTO(1) // AuthKey错误, @see AuthResDTO
val
NO_BOT
=
StateCodeDTO
(
2
,
"指定Bot不存在"
)
val
ILLEGAL_SESSION
=
StateCodeDTO
(
3
,
"Session失效或不存在"
)
val
NOT_VERIFIED_SESSION
=
StateCodeDTO
(
3
,
"Session未认证"
)
}
class
ILLEGAL_ACCESS
(
msg
:
String
)
:
StateCodeDTO
(
400
,
msg
)
// 非法访问
}
@Serializable
data class
SendDTO
(
override
val
sessionKey
:
String
,
val
target
:
Long
,
val
messageChain
:
MessageChainDTO
)
:
VerifyDTO
()
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.queue
import
net.mamoe.mirai.message.MessagePacket
import
java.util.concurrent.ConcurrentLinkedDeque
import
kotlin.collections.ArrayList
class
MessageQueue
:
ConcurrentLinkedDeque
<
MessagePacket
<
*
,
*
>>()
{
fun
fetch
(
size
:
Int
):
List
<
MessagePacket
<
*
,
*
>>
{
var
count
=
size
val
ret
=
ArrayList
<
MessagePacket
<
*
,
*
>>(
count
)
while
(!
this
.
isEmpty
()
&&
count--
>
0
)
{
ret
.
add
(
this
.
pop
())
}
return
ret
}
}
\ No newline at end of file
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt
0 → 100644
View file @
4b9900e0
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.Bot
import
net.mamoe.mirai.api.http.AuthedSession
import
net.mamoe.mirai.api.http.SessionManager
import
net.mamoe.mirai.api.http.dto.*
import
kotlin.coroutines.EmptyCoroutineContext
fun
Application
.
authModule
()
{
routing
{
miraiAuth
(
"/auth"
)
{
if
(
it
.
authKey
!=
SessionManager
.
authKey
)
{
call
.
respondDTO
(
AuthResDTO
(
1
,
""
))
}
else
{
call
.
respondDTO
(
AuthResDTO
(
0
,
SessionManager
.
createTempSession
().
key
))
}
}
miraiVerify
<
BindDTO
>(
"/verify"
,
verifiedSessionKey
=
false
)
{
try
{
val
bot
=
Bot
.
instanceWhose
(
it
.
qq
)
with
(
SessionManager
)
{
closeSession
(
it
.
sessionKey
)
allSession
[
it
.
sessionKey
]
=
AuthedSession
(
bot
,
EmptyCoroutineContext
)
}
call
.
respondDTO
(
StateCodeDTO
.
SUCCESS
)
}
catch
(
e
:
NoSuchElementException
)
{
call
.
respondDTO
(
StateCodeDTO
.
NO_BOT
)
}
}
miraiVerify
<
BindDTO
>(
"/release"
)
{
SessionManager
.
closeSession
(
it
.
sessionKey
)
call
.
respondDTO
(
StateCodeDTO
.
SUCCESS
)
}
}
}
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt
0 → 100644
View file @
4b9900e0
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.request.receive
import
io.ktor.response.defaultTextContentType
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.dto.*
fun
Application
.
mirai
()
{
install
(
DefaultHeaders
)
install
(
CallLogging
)
authModule
()
messageModule
()
}
/**
* 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
:
IllegalSessionException
)
{
call
.
respondDTO
(
StateCodeDTO
.
ILLEGAL_SESSION
)
}
catch
(
e
:
NotVerifiedSessionException
)
{
call
.
respondDTO
(
StateCodeDTO
.
NOT_VERIFIED_SESSION
)
}
catch
(
e
:
IllegalAccessException
)
{
call
.
respondDTO
(
StateCodeDTO
.
ILLEGAL_ACCESS
(
e
.
message
),
HttpStatusCode
.
BadRequest
)
}
}
/*
extend function
*/
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
>().
apply
(
::
println
).
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
)
/**
* 错误请求. 抛出这个异常后将会返回错误给一个请求
*/
@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未激活"
)
/**
* 错误参数
*/
class
IllegalParamException
(
message
:
String
)
:
IllegalAccessException
(
message
)
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/EventRouteModule.kt
0 → 100644
View file @
4b9900e0
package
net.mamoe.mirai.api.http.route
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt
0 → 100644
View file @
4b9900e0
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.AuthedSession
import
net.mamoe.mirai.api.http.SessionManager
import
net.mamoe.mirai.api.http.dto.*
fun
Application
.
messageModule
()
{
routing
{
miraiGet
(
"/fetchMessage"
)
{
val
count
:
Int
=
paramOrNull
(
"count"
)
val
fetch
=
it
.
messageQueue
.
fetch
(
count
)
val
ls
=
Array
(
fetch
.
size
)
{
index
->
fetch
[
index
].
toDTO
()
}
call
.
respondJson
(
ls
.
toList
().
toJson
())
}
miraiVerify
<
SendDTO
>(
"/sendFriendMessage"
)
{
it
.
session
.
bot
.
getQQ
(
it
.
target
).
sendMessage
(
it
.
messageChain
.
toMessageChain
())
call
.
respondDTO
(
StateCodeDTO
.
SUCCESS
)
}
miraiVerify
<
SendDTO
>(
"/sendGroupMessage"
)
{
it
.
session
.
bot
.
getGroup
(
it
.
target
).
sendMessage
(
it
.
messageChain
.
toMessageChain
())
call
.
respondDTO
(
StateCodeDTO
.
SUCCESS
)
}
miraiVerify
<
VerifyDTO
>(
"/event/message"
)
{
}
miraiVerify
<
VerifyDTO
>(
"/addFriend"
)
{
}
}
}
\ No newline at end of file
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