diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/Exception.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/Exception.kt new file mode 100644 index 000000000..2f6113472 --- /dev/null +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/Exception.kt @@ -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) \ No newline at end of file diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt new file mode 100644 index 000000000..51766c1cb --- /dev/null +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/StateCode.kt @@ -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 + } + } +} \ No newline at end of file diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt similarity index 88% rename from mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt rename to mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt index 2410a8ef9..3540e0cc6 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/ContactDTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt @@ -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) ) } diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt new file mode 100644 index 000000000..157f739bc --- /dev/null +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/DTO.kt @@ -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 // 反序列化验证成功后传入 +} diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt similarity index 98% rename from mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt rename to mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt index e670b3f33..dea0705e5 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/MessageDTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt @@ -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 diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt deleted file mode 100644 index ac8ccb5a0..000000000 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/AuthDTO.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.mamoe.mirai.api.http.dto - -import kotlinx.serialization.Serializable - -@Serializable -data class AuthDTO(val authKey: String) : DTO diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt deleted file mode 100644 index e652c5167..000000000 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/VerifyDTO.kt +++ /dev/null @@ -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 - } - } -} - diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt index 718d8b7a3..8191447fd 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt @@ -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) { diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt index fab85148b..d6d1148ec 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/BaseRoute.kt @@ -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 ApplicationCall.receiveDTO(): T? = receive().jsonParseOrNull() - - fun PipelineContext.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 PipelineContext.paramOrNull(name: String): R = @@ -171,42 +173,3 @@ internal inline fun PipelineContext.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) - diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt similarity index 57% rename from mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt rename to mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt index 69299ae06..96bd31f68 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/GroupManageRouteModule.kt @@ -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("/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("/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("/groupConfig") { dto -> @@ -62,13 +67,13 @@ fun Application.groupManageModule() { * 群员信息管理(需要相关权限) */ miraiGet("/memberInfo") { - val member = it.bot.getGroup(paramOrNull("target"))[paramOrNull("memberID")] - call.respondDTO(MemberInfoDTO(member)) + val member = it.bot.getGroup(paramOrNull("target"))[paramOrNull("memberId")] + call.respondDTO(MemberDetailDTO(member)) } - miraiVerify("/memberInfo") { dto -> + miraiVerify("/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) } \ No newline at end of file diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt index 847f88d79..8fc741a5b 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/InfoRouteModule.kt @@ -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() { diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt similarity index 73% rename from mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt rename to mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt index 6d3be41b0..b287c4a41 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/SendMessageRouteModule.kt @@ -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("/event/message") { - - } - - miraiVerify("/addFriend") { - - } } -} \ No newline at end of file +} + +@Serializable +private data class SendDTO( + override val sessionKey: String, + val target: Long, + val messageChain: MessageChainDTO +) : VerifyDTO() \ No newline at end of file diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt similarity index 93% rename from mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt rename to mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt index d7acf6c22..a0fd5b45f 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/dto/DTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/util/Json.kt @@ -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 String.jsonParseOrNull( inline fun T.toJson( serializer: SerializationStrategy? = null ): String = if (serializer == null) MiraiJson.json.stringify(this) - else MiraiJson.json.stringify(serializer, this) +else MiraiJson.json.stringify(serializer, this) // 序列化列表时,stringify需要使用的泛型是T,而非List