mirror of https://github.com/hykilpikonna/AquaDX
[O] Make handlers abstract
parent
fa45891af4
commit
ae6ff97b62
|
@ -1,123 +1,17 @@
|
||||||
package icu.samnyan.aqua.sega.chusan
|
package icu.samnyan.aqua.sega.chusan
|
||||||
|
|
||||||
import ext.*
|
import ext.*
|
||||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
|
||||||
import icu.samnyan.aqua.net.utils.simpleDescribe
|
|
||||||
import icu.samnyan.aqua.sega.chusan.handler.*
|
|
||||||
import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
|
|
||||||
import icu.samnyan.aqua.sega.chusan.model.request.UserCMissionResp
|
import icu.samnyan.aqua.sega.chusan.model.request.UserCMissionResp
|
||||||
import icu.samnyan.aqua.sega.chusan.model.response.data.MatchingMemberInfo
|
import icu.samnyan.aqua.sega.chusan.model.response.data.MatchingMemberInfo
|
||||||
import icu.samnyan.aqua.sega.chusan.model.response.data.MatchingWaitState
|
import icu.samnyan.aqua.sega.chusan.model.response.data.MatchingWaitState
|
||||||
import icu.samnyan.aqua.sega.chusan.model.response.data.UserEmoney
|
import icu.samnyan.aqua.sega.chusan.model.response.data.UserEmoney
|
||||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge
|
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge
|
||||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail
|
import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail
|
||||||
import icu.samnyan.aqua.sega.general.BaseHandler
|
|
||||||
import icu.samnyan.aqua.sega.general.RequestContext
|
|
||||||
import icu.samnyan.aqua.sega.general.SpecialHandler
|
|
||||||
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
|
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
|
||||||
import icu.samnyan.aqua.sega.general.toSpecial
|
|
||||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper
|
|
||||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper
|
|
||||||
import icu.samnyan.aqua.spring.Metrics
|
|
||||||
import jakarta.servlet.http.HttpServletRequest
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import kotlin.collections.set
|
|
||||||
import kotlin.reflect.full.declaredMemberProperties
|
|
||||||
|
|
||||||
/**
|
val chusanInit: ChusanController.() -> Unit = {
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
@RestController
|
|
||||||
@API(value = ["/g/chu3/{version}/ChuniServlet", "/g/chu3/{version}"])
|
|
||||||
class ChusanServletController(
|
|
||||||
val gameLogin: GameLoginHandler,
|
|
||||||
val upsertUserAll: UpsertUserAllHandler,
|
|
||||||
val cmUpsertUserGacha: CMUpsertUserGachaHandler,
|
|
||||||
val cmUpsertUserPrintSubtract: CMUpsertUserPrintSubtractHandler,
|
|
||||||
val cmUpsertUserPrintCancel: CMUpsertUserPrintCancelHandler,
|
|
||||||
|
|
||||||
val mapper: StringMapper,
|
|
||||||
val cmMapper: BasicMapper,
|
|
||||||
val db: Chu3Repos,
|
|
||||||
val us: AquaUserServices,
|
|
||||||
val versionHelper: ChusanVersionHelper,
|
|
||||||
val props: ChusanProps
|
|
||||||
) {
|
|
||||||
val log = LoggerFactory.getLogger(ChusanServletController::class.java)
|
|
||||||
|
|
||||||
// Below are code related to handling the handlers
|
|
||||||
val externalHandlers = mutableListOf("GameLoginApi", "UpsertUserAllApi",
|
|
||||||
"CMUpsertUserGachaApi", "CMUpsertUserPrintCancelApi", "CMUpsertUserPrintSubtractApi")
|
|
||||||
|
|
||||||
val noopEndpoint = setOf("UpsertClientBookkeepingApi", "UpsertClientDevelopApi", "UpsertClientErrorApi",
|
|
||||||
"UpsertClientSettingApi", "UpsertClientTestmodeApi", "CreateTokenApi", "RemoveTokenApi", "UpsertClientUploadApi",
|
|
||||||
"PrinterLoginApi", "PrinterLogoutApi", "Ping", "GameLogoutApi", "RemoveMatchingMemberApi")
|
|
||||||
|
|
||||||
// Fun!
|
|
||||||
val initH = mutableMapOf<String, SpecialHandler>()
|
|
||||||
infix operator fun String.invoke(fn: SpecialHandler) = initH.set("${this}Api", fn)
|
|
||||||
infix fun List<String>.all(fn: SpecialHandler) = forEach { it(fn) }
|
|
||||||
infix fun String.static(fn: () -> Any) = mapper.write(fn()).let { resp -> this { resp } }
|
|
||||||
val meow = init()
|
|
||||||
|
|
||||||
val members = this::class.declaredMemberProperties
|
|
||||||
val handlers: Map<String, SpecialHandler> = initH + externalHandlers.associateWith { api ->
|
|
||||||
val name = api.replace("Api", "").lowercase()
|
|
||||||
(members.find { it.name.lowercase() == name } ?: members.find { it.name.lowercase() == name.replace("cm", "") })
|
|
||||||
?.let { (it.call(this) as BaseHandler).toSpecial() }
|
|
||||||
?: throw IllegalArgumentException("Chu3: No handler found for $api")
|
|
||||||
}
|
|
||||||
|
|
||||||
@API("/{endpoint}", "/MatchingServer/{endpoint}")
|
|
||||||
fun handle(@PV endpoint: Str, @RB data: MutableMap<Str, Any>, @PV version: Str, req: HttpServletRequest): Any {
|
|
||||||
val ctx = RequestContext(req, data)
|
|
||||||
var api = endpoint
|
|
||||||
data["version"] = version
|
|
||||||
|
|
||||||
// Export version
|
|
||||||
if (api.endsWith("C3Exp")) {
|
|
||||||
api = api.removeSuffix("C3Exp")
|
|
||||||
data["c3exp"] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (api !in noopEndpoint && !handlers.containsKey(api)) {
|
|
||||||
log.warn("Chu3 > $api not found")
|
|
||||||
return """{"returnCode":"1","apiName":"$api"}"""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only record the counter metrics if the API is known.
|
|
||||||
Metrics.counter("aquadx_chusan_api_call", "api" to api).increment()
|
|
||||||
if (api in noopEndpoint) {
|
|
||||||
log.info("Chu3 > $api no-op")
|
|
||||||
return """{"returnCode":"1"}"""
|
|
||||||
}
|
|
||||||
log.info("Chu3 < $api : ${data.toJson()}")
|
|
||||||
val map = if ("CM" in api) cmMapper else mapper
|
|
||||||
|
|
||||||
return try {
|
|
||||||
Metrics.timer("aquadx_chusan_api_latency", "api" to api).recordCallable {
|
|
||||||
handlers[api]!!(ctx).let { if (it is String) it else map.write(it) }.also {
|
|
||||||
if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
|
|
||||||
log.info("Chu3 > $api : $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Metrics.counter(
|
|
||||||
"aquadx_chusan_api_error",
|
|
||||||
"api" to api, "error" to e.simpleDescribe()
|
|
||||||
).increment()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun ChusanServletController.init() {
|
|
||||||
// Stub handlers
|
// Stub handlers
|
||||||
"GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" }
|
"GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" }
|
||||||
"GetGameIdlist" { """{"type":"${data["type"]}","length":"0","gameIdlistList":[]}""" }
|
"GetGameIdlist" { """{"type":"${data["type"]}","length":"0","gameIdlistList":[]}""" }
|
||||||
|
@ -183,7 +77,8 @@ fun ChusanServletController.init() {
|
||||||
|
|
||||||
"GetGameGachaCardById" { db.gameGachaCard.findAllByGachaId(parsing { data["gachaId"]!!.int }).let {
|
"GetGameGachaCardById" { db.gameGachaCard.findAllByGachaId(parsing { data["gachaId"]!!.int }).let {
|
||||||
mapOf("gachaId" to it.size, "length" to it.size, "isPickup" to false, "gameGachaCardList" to it,
|
mapOf("gachaId" to it.size, "length" to it.size, "isPickup" to false, "gameGachaCardList" to it,
|
||||||
"emissionList" to empty, "afterCalcList" to empty)
|
"emissionList" to empty, "afterCalcList" to empty
|
||||||
|
)
|
||||||
} }
|
} }
|
||||||
|
|
||||||
"GetUserCMission" {
|
"GetUserCMission" {
|
||||||
|
@ -333,8 +228,8 @@ fun ChusanServletController.init() {
|
||||||
"maxCountCharacter" to 300,
|
"maxCountCharacter" to 300,
|
||||||
"maxCountItem" to 300,
|
"maxCountItem" to 300,
|
||||||
"maxCountMusic" to 300,
|
"maxCountMusic" to 300,
|
||||||
"matchStartTime" to LocalDateTime.now().minusHours(1).format(fmt),
|
"matchStartTime" to LocalDateTime.now().minusHours(5).format(fmt),
|
||||||
"matchEndTime" to LocalDateTime.now().plusHours(1).format(fmt),
|
"matchEndTime" to LocalDateTime.now().plusHours(5).format(fmt),
|
||||||
"matchTimeLimit" to 10,
|
"matchTimeLimit" to 10,
|
||||||
"matchErrorLimit" to 10,
|
"matchErrorLimit" to 10,
|
||||||
"matchingUri" to addr,
|
"matchingUri" to addr,
|
||||||
|
@ -372,4 +267,4 @@ fun ChusanServletController.init() {
|
||||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||||
mapOf("userName" to user.userName, "level" to user.level, "medal" to user.medal, "lastDataVersion" to user.lastDataVersion, "isLogin" to false)
|
mapOf("userName" to user.userName, "level" to user.level, "medal" to user.medal, "lastDataVersion" to user.lastDataVersion, "isLogin" to false)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package icu.samnyan.aqua.sega.chusan
|
||||||
|
|
||||||
|
import ext.*
|
||||||
|
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||||
|
import icu.samnyan.aqua.net.utils.simpleDescribe
|
||||||
|
import icu.samnyan.aqua.sega.chusan.handler.*
|
||||||
|
import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
|
||||||
|
import icu.samnyan.aqua.sega.general.*
|
||||||
|
import icu.samnyan.aqua.sega.util.jackson.BasicMapper
|
||||||
|
import icu.samnyan.aqua.sega.util.jackson.StringMapper
|
||||||
|
import icu.samnyan.aqua.spring.Metrics
|
||||||
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import kotlin.collections.set
|
||||||
|
import kotlin.reflect.full.declaredMemberProperties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author samnyan (privateamusement@protonmail.com)
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@RestController
|
||||||
|
@API(value = ["/g/chu3/{version}/ChuniServlet", "/g/chu3/{version}"])
|
||||||
|
class ChusanController(
|
||||||
|
val gameLogin: GameLoginHandler,
|
||||||
|
val upsertUserAll: UpsertUserAllHandler,
|
||||||
|
val cmUpsertUserGacha: CMUpsertUserGachaHandler,
|
||||||
|
val cmUpsertUserPrintSubtract: CMUpsertUserPrintSubtractHandler,
|
||||||
|
val cmUpsertUserPrintCancel: CMUpsertUserPrintCancelHandler,
|
||||||
|
|
||||||
|
val mapper: StringMapper,
|
||||||
|
val cmMapper: BasicMapper,
|
||||||
|
val db: Chu3Repos,
|
||||||
|
val us: AquaUserServices,
|
||||||
|
val versionHelper: ChusanVersionHelper,
|
||||||
|
val props: ChusanProps
|
||||||
|
): MeowApi({ api, resp ->
|
||||||
|
if (resp is String) resp
|
||||||
|
else (if ("CM" in api) cmMapper else mapper).write(resp)
|
||||||
|
}) {
|
||||||
|
val log = LoggerFactory.getLogger(ChusanController::class.java)
|
||||||
|
|
||||||
|
// Below are code related to handling the handlers
|
||||||
|
val externalHandlers = mutableListOf("GameLoginApi", "UpsertUserAllApi",
|
||||||
|
"CMUpsertUserGachaApi", "CMUpsertUserPrintCancelApi", "CMUpsertUserPrintSubtractApi")
|
||||||
|
|
||||||
|
val noopEndpoint = setOf("UpsertClientBookkeepingApi", "UpsertClientDevelopApi", "UpsertClientErrorApi",
|
||||||
|
"UpsertClientSettingApi", "UpsertClientTestmodeApi", "CreateTokenApi", "RemoveTokenApi", "UpsertClientUploadApi",
|
||||||
|
"PrinterLoginApi", "PrinterLogoutApi", "Ping", "GameLogoutApi", "RemoveMatchingMemberApi")
|
||||||
|
|
||||||
|
init { chusanInit() }
|
||||||
|
|
||||||
|
val members = this::class.declaredMemberProperties
|
||||||
|
val handlers: Map<String, SpecialHandler> = initH + externalHandlers.associateWith { api ->
|
||||||
|
val name = api.replace("Api", "").lowercase()
|
||||||
|
(members.find { it.name.lowercase() == name } ?: members.find { it.name.lowercase() == name.replace("cm", "") })
|
||||||
|
?.let { (it.call(this) as BaseHandler).toSpecial() }
|
||||||
|
?: throw IllegalArgumentException("Chu3: No handler found for $api")
|
||||||
|
}
|
||||||
|
|
||||||
|
@API("/{endpoint}", "/MatchingServer/{endpoint}")
|
||||||
|
fun handle(@PV endpoint: Str, @RB data: MutableMap<Str, Any>, @PV version: Str, req: HttpServletRequest): Any {
|
||||||
|
val ctx = RequestContext(req, data)
|
||||||
|
var api = endpoint
|
||||||
|
data["version"] = version
|
||||||
|
|
||||||
|
// Export version
|
||||||
|
if (api.endsWith("C3Exp")) {
|
||||||
|
api = api.removeSuffix("C3Exp")
|
||||||
|
data["c3exp"] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (api !in noopEndpoint && !handlers.containsKey(api)) {
|
||||||
|
log.warn("Chu3 > $api not found")
|
||||||
|
return """{"returnCode":"1","apiName":"$api"}"""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only record the counter metrics if the API is known.
|
||||||
|
Metrics.counter("aquadx_chusan_api_call", "api" to api).increment()
|
||||||
|
if (api in noopEndpoint) {
|
||||||
|
log.info("Chu3 > $api no-op")
|
||||||
|
return """{"returnCode":"1"}"""
|
||||||
|
}
|
||||||
|
log.info("Chu3 < $api : ${data.toJson()}")
|
||||||
|
|
||||||
|
return try {
|
||||||
|
Metrics.timer("aquadx_chusan_api_latency", "api" to api).recordCallable {
|
||||||
|
serialize(api, handlers[api]!!(ctx)).also {
|
||||||
|
if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
|
||||||
|
log.info("Chu3 > $api : $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Metrics.counter(
|
||||||
|
"aquadx_chusan_api_error",
|
||||||
|
"api" to api, "error" to e.simpleDescribe()
|
||||||
|
).increment()
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,7 @@ import ext.long
|
||||||
import ext.parsing
|
import ext.parsing
|
||||||
import jakarta.servlet.http.HttpServletRequest
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
fun interface BaseHandler {
|
fun interface BaseHandler {
|
||||||
@Throws(JsonProcessingException::class)
|
@Throws(JsonProcessingException::class)
|
||||||
fun handle(request: Map<String, Any>): Any?
|
fun handle(request: Map<String, Any>): Any?
|
||||||
|
@ -22,3 +20,11 @@ data class RequestContext(
|
||||||
|
|
||||||
typealias SpecialHandler = RequestContext.() -> Any?
|
typealias SpecialHandler = RequestContext.() -> Any?
|
||||||
fun BaseHandler.toSpecial() = { ctx: RequestContext -> handle(ctx.data) }
|
fun BaseHandler.toSpecial() = { ctx: RequestContext -> handle(ctx.data) }
|
||||||
|
|
||||||
|
// A very :3 way of declaring APIs
|
||||||
|
abstract class MeowApi(val serialize: (String, Any?) -> String) {
|
||||||
|
val initH = mutableMapOf<String, SpecialHandler>()
|
||||||
|
infix operator fun String.invoke(fn: SpecialHandler) = initH.set("${this}Api", fn)
|
||||||
|
infix fun List<String>.all(fn: SpecialHandler) = forEach { it(fn) }
|
||||||
|
infix fun String.static(fn: () -> Any) = serialize(this, fn()).let { resp -> this { resp } }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue