http-api refactor dto

This commit is contained in:
ryoii 2020-02-08 17:27:00 +08:00
parent 02b4f10e0a
commit e2f50210bc
13 changed files with 170 additions and 173 deletions

View File

@ -0,0 +1,38 @@
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不存在")
/**
* 指定Bot不存在
*/
object PermissionDeniedException: IllegalAccessException("无操作限权")
/**
* 错误参数
*/
class IllegalParamException(message: String) : IllegalAccessException(message)

View File

@ -0,0 +1,21 @@
package net.mamoe.mirai.api.http.data
import kotlinx.serialization.Serializable
@Serializable
open class StateCode(val code: Int, var msg: String) {
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, "无操作权限")
// KS bug: 主构造器中不能有非字段参数 https://github.com/Kotlin/kotlinx.serialization/issues/575
@Serializable
class IllegalAccess() : StateCode(400, "") { // 非法访问
constructor(msg: String) : this() {
this.msg = msg
}
}
}

View File

@ -1,4 +1,4 @@
package net.mamoe.mirai.api.http.dto
package net.mamoe.mirai.api.http.data.common
import kotlinx.serialization.Serializable
import net.mamoe.mirai.contact.Group
@ -30,7 +30,8 @@ data class MemberDTO(
val group: GroupDTO
) : ContactDTO() {
constructor(member: Member) : this (
member.id, member.groupCard, member.permission, GroupDTO(member.group)
member.id, member.groupCard, member.permission,
GroupDTO(member.group)
)
}

View File

@ -0,0 +1,18 @@
package net.mamoe.mirai.api.http.data.common
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
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
lateinit var session: AuthedSession // 反序列化验证成功后传入
}

View File

@ -1,4 +1,4 @@
package net.mamoe.mirai.api.http.dto
package net.mamoe.mirai.api.http.data.common
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

View File

@ -1,6 +0,0 @@
package net.mamoe.mirai.api.http.dto
import kotlinx.serialization.Serializable
@Serializable
data class AuthDTO(val authKey: String) : DTO

View File

@ -1,97 +0,0 @@
package net.mamoe.mirai.api.http.dto
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import net.mamoe.mirai.api.http.AuthedSession
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
@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()
@Serializable
data class SendDTO(
override val sessionKey: String,
val target: Long,
val messageChain: MessageChainDTO
) : VerifyDTO()
typealias GroupTargetDTO = FriendTargetDTO
@Serializable
data class FriendTargetDTO(
override val sessionKey: String,
val target: Long
) : VerifyDTO()
@Serializable
data class MuteDTO(
override val sessionKey: String,
val target: Long,
val member: Long = 0,
val time: Int = 0
) : VerifyDTO()
@Serializable
data class GroupConfigDTO(
override val sessionKey: String,
val target: Long,
val config: GroupInfoDTO
) : VerifyDTO()
@Serializable
data class GroupInfoDTO(
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.announcement, group.confessTalk, group.allowMemberInvite,
group.autoApprove, group.anonymousChat
)
}
@Serializable
data class MemberConfigDTO(
override val sessionKey: String,
val target: Long,
val memberId: Long,
val config: MemberInfoDTO
) : VerifyDTO()
@Serializable
data class MemberInfoDTO(
val name: String? = null,
val specialTitle: String? = null
) : DTO {
constructor(member: Member) : this(member.groupCard, member.specialTitle)
}
@Serializable
open class StateCode(val code: Int, var msg: String) {
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, "无操作权限")
// KS bug: 主构造器中不能有非字段参数 https://github.com/Kotlin/kotlinx.serialization/issues/575
@Serializable
class IllegalAccess() : StateCode(400, "") { // 非法访问
constructor(msg: String) : this() {
this.msg = msg
}
}
}

View File

@ -3,10 +3,12 @@ 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.dto.*
import net.mamoe.mirai.api.http.data.*
import net.mamoe.mirai.api.http.data.common.VerifyDTO
import kotlin.coroutines.EmptyCoroutineContext
@ -43,6 +45,9 @@ fun Application.authModule() {
}
}
@Serializable
private data class BindDTO(override val sessionKey: String, val qq: Long) : VerifyDTO()
private fun getBotOrThrow(qq: Long) = try {
Bot.instanceWhose(qq)
} catch (e: NoSuchElementException) {

View File

@ -19,7 +19,10 @@ 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.*
import net.mamoe.mirai.api.http.data.*
import net.mamoe.mirai.api.http.data.common.*
import net.mamoe.mirai.api.http.util.jsonParseOrNull
import net.mamoe.mirai.api.http.util.toJson
fun Application.mirai() {
install(DefaultHeaders)
@ -136,14 +139,13 @@ internal suspend fun ApplicationCall.respondJson(json: String, status: HttpStatu
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 =
@ -171,42 +173,3 @@ internal inline fun <reified R> PipelineContext<Unit, ApplicationCall>.paramOrNu
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未激活")
/**
* 指定Bot不存在
*/
object NoSuchBotException: IllegalAccessException("指定Bot不存在")
/**
* 指定Bot不存在
*/
object PermissionDeniedException: IllegalAccessException("无操作限权")
/**
* 错误参数
*/
class IllegalParamException(message: String) : IllegalAccessException(message)

View File

@ -3,7 +3,12 @@ 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.dto.*
import kotlinx.serialization.Serializable
import net.mamoe.mirai.api.http.data.*
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() {
@ -23,14 +28,14 @@ fun Application.groupManageModule() {
}
miraiVerify<MuteDTO>("/mute") {
when(it.session.bot.getGroup(it.target)[it.member].mute(it.time)) {
when(it.session.bot.getGroup(it.target)[it.memberId].mute(it.time)) {
true -> call.respondStateCode(StateCode.Success)
else -> throw PermissionDeniedException
}
}
miraiVerify<MuteDTO>("/unmute") {
when(it.session.bot.getGroup(it.target).members[it.member].unmute()) {
when(it.session.bot.getGroup(it.target).members[it.memberId].unmute()) {
true -> call.respondStateCode(StateCode.Success)
else -> throw PermissionDeniedException
}
@ -41,7 +46,7 @@ fun Application.groupManageModule() {
*/
miraiGet("/groupConfig") {
val group = it.bot.getGroup(paramOrNull("target"))
call.respondDTO(GroupInfoDTO(group))
call.respondDTO(GroupDetailDTO(group))
}
miraiVerify<GroupConfigDTO>("/groupConfig") { dto ->
@ -63,12 +68,12 @@ fun Application.groupManageModule() {
*/
miraiGet("/memberInfo") {
val member = it.bot.getGroup(paramOrNull("target"))[paramOrNull("memberID")]
call.respondDTO(MemberInfoDTO(member))
call.respondDTO(MemberDetailDTO(member))
}
miraiVerify<MemberConfigDTO>("/memberInfo") { dto ->
miraiVerify<MemberInfoDTO>("/memberInfo") { dto ->
val member = dto.session.bot.getGroup(dto.target)[dto.memberId]
with(dto.config) {
with(dto.info) {
name?.let { member.groupCard = it }
specialTitle?.let { member.specialTitle = it }
}
@ -76,4 +81,51 @@ fun Application.groupManageModule() {
}
}
}
@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 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.announcement, group.confessTalk, group.allowMemberInvite,
group.autoApprove, group.anonymousChat
)
}
@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.groupCard, member.specialTitle)
}

View File

@ -3,10 +3,10 @@ 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.dto.GroupDTO
import net.mamoe.mirai.api.http.dto.MemberDTO
import net.mamoe.mirai.api.http.dto.QQDTO
import net.mamoe.mirai.api.http.dto.toJson
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() {

View File

@ -3,7 +3,10 @@ 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.dto.*
import kotlinx.serialization.Serializable
import net.mamoe.mirai.api.http.data.*
import net.mamoe.mirai.api.http.data.common.*
import net.mamoe.mirai.api.http.util.toJson
fun Application.messageModule() {
routing {
@ -26,12 +29,12 @@ fun Application.messageModule() {
call.respondStateCode(StateCode.Success)
}
miraiVerify<VerifyDTO>("/event/message") {
}
miraiVerify<VerifyDTO>("/addFriend") {
}
}
}
}
@Serializable
private data class SendDTO(
override val sessionKey: String,
val target: Long,
val messageChain: MessageChainDTO
) : VerifyDTO()

View File

@ -1,10 +1,9 @@
package net.mamoe.mirai.api.http.dto
package net.mamoe.mirai.api.http.util
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
interface DTO
import net.mamoe.mirai.api.http.data.common.*
// 解析失败时直接返回null由路由判断响应400状态
@UseExperimental(ImplicitReflectionSerializer::class)
@ -20,7 +19,7 @@ inline fun <reified T : Any> String.jsonParseOrNull(
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)
else MiraiJson.json.stringify(serializer, this)
// 序列化列表时stringify需要使用的泛型是T而非List<T>