Merge branch 'v1-dev' and resolve all conflicts

This commit is contained in:
Azalea
2026-03-29 21:21:28 +00:00
9 changed files with 46 additions and 126 deletions
+9 -9
View File
@@ -32,15 +32,15 @@ Multipurpose game server for ALL.Net games.
> [!WARNING]
> CHUNITHM pre-NEW!! and maimai pre-DX are no longer supported after February 6th, 2026 and all associated data will be removed.
| Game | Latest Ver. | Initial Ver. | Notes |
|------------------------|---------------------|---------------------|-------------------------------------------------------------|
| SDHD: CHUNITHM | 2.45 (X-VERSE-X) | 2.00 (NEW) | |
| SDEZ: maimai DX | 1.65 (CiRCLE PLUS) | 1.00 (DX) | Missing circle (teams) support |
| SDGA: maimai DX (Intl) | 1.60 (CiRCLE) | 1.00 (DX) | Thanks [@Clansty](https://github.com/clansty) |
| SDED: Card Maker | 1.39 | N/A | Thanks [@Becods](https://github.com/Becods) |
| SDDT: O.N.G.E.K.I. | 1.50 (Re:Fresh) | N/A | Thanks [@PenguinCaptain](https://github.com/PenguinCaptain) |
| SBZV: Project DIVA | 7.10 | N/A | No web interface provided |
| SDFE: Wacca | 3.07 (Reverse) | N/A | Later versions are EOS patches, network will not work |
| Game | Latest Ver. | Initial Ver. | Notes | Web UI | Data Import |
|------------------------|---------------------|---------------------|-------------------------------------------------------------|--------|-------------|
| SDHD: CHUNITHM | 2.45 (X-VERSE-X) | 2.00 (NEW) | | ✅ | ❗ |
| SDEZ: maimai DX | 1.65 (CiRCLE PLUS) | 1.00 (DX) | Missing circle (teams) support | ✅ | ✅ |
| SDGA: maimai DX (Intl) | 1.60 (CiRCLE) | 1.00 (DX) | Thanks [@Clansty](https://github.com/clansty) | ✅ | ✅ |
| SDED: Card Maker | 1.39 | N/A | Thanks [@Becods](https://github.com/Becods) | ❌ | ❌ |
| SDDT: O.N.G.E.K.I. | 1.50 (Re:Fresh) | N/A | Thanks [@PenguinCaptain](https://github.com/PenguinCaptain) | ✅ | ❌ |
| SBZV: Project DIVA | 7.10 | N/A | Minimal support | ❌ | ❌ |
| SDFE: Wacca | 3.07 (Reverse) | N/A | Later versions are EOS patches, network will not work | ✅ | ❌ |
<!-- A majority of them have been left as N/A for initial version as they do not appear to have restrictions -->
+1 -1
View File
@@ -1,7 +1,7 @@
FROM archlinux:latest
RUN pacman -Syu --noconfirm \
&& pacman -S --noconfirm openssh sudo jdk21-openjdk wget which procps-ng zsh git curlie micro ripgrep python3 exa \
&& pacman -S --noconfirm openssh sudo jdk21-openjdk wget which procps-ng zsh git curlie micro ripgrep python3 exa diffutils \
&& rm -rf /var/cache/pacman/pkg/* \
&& mkdir -p /var/run/sshd \
&& chsh -s /bin/zsh root \
+5
View File
@@ -0,0 +1,5 @@
```
gradle test -PrunTests --tests Mai2Test
```
@@ -377,7 +377,7 @@ fun ChusanController.chusanInit() {
}
// Static
"GetGameEvent" static { db.gameEvent.findByEnable(true).let { mapOf("type" to 1, "length" to it.size, "gameEventList" to it) } }
"GetGameEvent" static { db.gameEvent.findAll().let { mapOf("type" to 1, "length" to it.size, "gameEventList" to it) } }
"GetGameCharge" static { db.gameCharge.findAll().let { mapOf("length" to it.size, "gameChargeList" to it) } }
"GetGameGacha" static { db.gameGacha.findAll().let { mapOf("length" to it.size, "gameGachaList" to it, "registIdList" to empty) } }
"GetGameMapAreaCondition" static { ChusanData.mapAreaCondition }
@@ -53,7 +53,7 @@ fun Maimai2ServletController.initApis() {
}
// Maimai only request for event type 1
"GetGameEvent" static { mapOf("type" to 1, "gameEventList" to db.gameEvent.findByEnable(true)) }
"GetGameEvent" static { mapOf("type" to 1, "gameEventList" to db.gameEvent.findAll()) }
"GetGameCharge" static { db.gameCharge.findAll().let { mapOf("length" to it.size, "gameChargeList" to it) } }
"GetUserOption" { mapOf(
@@ -45,6 +45,7 @@ import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.NoRepositoryBean
import org.springframework.stereotype.Component
import java.util.*
+27 -21
View File
@@ -13,7 +13,7 @@ class Mai2Test : StringSpec({
var userId = 0L
suspend fun post(url: String, body: String): Pair<HttpResponse, Map<String, Any?>> {
val resp = HTTP.post("$HOST/gs/$CLIENT_ID/mai2/$url") {
val resp = HTTP.post("$HOST/g/mai2/$url") {
contentType(ContentType.Application.Json)
setBody(body)
}
@@ -31,20 +31,23 @@ class Mai2Test : StringSpec({
"GetGameSettingApi" {
println("UserID: $userId")
post("GetGameSettingApi", """{"placeId":291,"clientId":"$CLIENT_ID"}""").let { (_, result) ->
result shouldBe """{"gameSetting":{"requestInterval":10,"rebootStartTime":"2099-01-01 23:59:00.0","rebootEndTime":"2099-01-01 23:59:00.0","movieUploadLimit":10000,"movieStatus":0,"movieServerUri":"","deliverServerUri":"","oldServerUri":"","usbDlServerUri":"","rebootInterval":0,"isMaintenance":false},"isAouAccession":true}""".jsonMap()
val gs = result["gameSetting"] as Map<*, *>
gs["requestInterval"] shouldBe 10
result["isAouAccession"] shouldBe true
}
}
"GetGameRankingApi" {
post("GetGameRankingApi", """{"type":1}""").let { (_, result) ->
result shouldBe """{"type":"1","gameRankingList":[]}""".jsonMap()
result["type"] shouldBe 1
assert(result["gameRankingList"] is List<*>)
}
}
"GetGameEventApi" {
post("GetGameEventApi", """{"type":1,"isAllEvent":true}""").let { (_, result) ->
result.keys shouldBe setOf("type", "gameEventList")
((result["gameEventList"] as List<*>).first() as Map<*, *>).keys shouldBe setOf("id", "type", "startDate", "endDate")
((result["gameEventList"] as List<*>).first() as Map<*, *>).keys shouldBe setOf("id", "type", "startDate", "endDate", "enable", "disableArea")
}
}
@@ -56,13 +59,13 @@ class Mai2Test : StringSpec({
"GetGameChargeApi" {
post("GetGameChargeApi", """{"isAll":false}""").let { (_, result) ->
result shouldBe """{"length":5,"gameChargeList":[{"orderId":1,"chargeId":2,"price":1,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"orderId":2,"chargeId":3,"price":2,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"orderId":3,"chargeId":4,"price":3,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"orderId":4,"chargeId":5,"price":4,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"orderId":5,"chargeId":6,"price":5,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"}]}""".jsonMap()
result shouldBe """{"length":5,"gameChargeList":[{"chargeId":0,"orderId":0,"price":1,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"chargeId":0,"orderId":0,"price":2,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"chargeId":0,"orderId":0,"price":3,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"chargeId":0,"orderId":0,"price":4,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"},{"chargeId":0,"orderId":0,"price":5,"startDate":"2019-01-01 00:00:00.000000","endDate":"2099-01-01 00:00:00.000000"}]}""".jsonMap()
}
}
"GetGameNgMusicIdApi" {
post("GetGameNgMusicIdApi", """{}""").let { (_, result) ->
result shouldBe """{"length":0,"musicIdList":[]}""".jsonMap()
result shouldBe """{"length":0,"musicIdList":[],"ngMusicDataList":[]}""".jsonMap()
}
}
@@ -115,13 +118,16 @@ class Mai2Test : StringSpec({
"GetUserDataApi" {
post("GetUserDataApi", """{"userId":$userId}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userData":{"userName":"AZA☆","friendCode":"","isNetMember":1,"nameplateId":0,"iconId":11,"trophyId":0,"plateId":1,"titleId":11,"partnerId":1,"frameId":1,"selectMapId":400001,"totalAwake":0,"gradeRating":0,"musicRating":271,"playerRating":271,"highestRating":271,"gradeRank":0,"classRank":0,"courseRank":0,"charaSlot":[101,400101,105,104,103],"charaLockSlot":[0,0,0,0,0],"contentBit":2169888,"playCount":1,"eventWatchedDate":"2024-03-27 05:45:15.0","lastGameId":"SDEZ","lastRomVersion":"1.41.00","lastDataVersion":"1.40.08","lastLoginDate":"2024-03-27 05:45:15.0","lastPlayDate":"2024-03-27 05:56:54.0","lastPlayCredit":1,"lastPlayMode":0,"lastPlaceId":291,"lastPlaceName":"","lastAllNetId":0,"lastRegionId":1,"lastRegionName":"W","lastClientId":"$CLIENT_ID","lastCountryCode":"JPN","lastSelectEMoney":0,"lastSelectTicket":0,"lastSelectCourse":0,"lastCountCourse":0,"firstGameId":"SDEZ","firstRomVersion":"1.41.00","firstDataVersion":"1.40.08","firstPlayDate":"2024-03-27 05:45:15.0","compatibleCmVersion":"1.40.00","dailyBonusDate":"1970-01-01 09:00:00.0","dailyCourseBonusDate":"1970-01-01 09:00:00.0","lastPairLoginDate":"1970-01-01 09:00:00.0","lastTrialPlayDate":"1970-01-01 09:00:00.0","playVsCount":0,"playSyncCount":0,"winCount":0,"helpCount":0,"comboCount":0,"totalDeluxscore":1725,"totalBasicDeluxscore":0,"totalAdvancedDeluxscore":0,"totalExpertDeluxscore":1725,"totalMasterDeluxscore":0,"totalReMasterDeluxscore":0,"totalHiscore":0,"totalBasicHighscore":0,"totalAdvancedHighscore":0,"totalExpertHighscore":0,"totalMasterHighscore":0,"totalReMasterHighscore":0,"totalSync":0,"totalBasicSync":0,"totalAdvancedSync":0,"totalExpertSync":0,"totalMasterSync":0,"totalReMasterSync":0,"totalAchievement":997456,"totalBasicAchievement":0,"totalAdvancedAchievement":0,"totalExpertAchievement":997456,"totalMasterAchievement":0,"totalReMasterAchievement":0,"playerOldRating":271,"playerNewRating":0,"banState":0,"dateTime":1711485182,"cmLastEmoneyBrand":2,"cmLastEmoneyCredit":69,"mapStock":0,"currentPlayCount":1,"renameCredit":0,"accessCode":"$ACCESS_CODE"},"banState":0}""".jsonMap()
val userData = result["userData"] as Map<*, *>
userData["userName"] shouldBe "AZA☆"
userData["playerRating"] shouldBe 271
result["banState"] shouldBe 0
}
}
"GetUserCardApi" {
post("GetUserCardApi", """{"userId":$userId,"nextIndex":0,"maxCount":20}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userCardList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":0,"userCardList":[]}""".jsonMap()
}
}
@@ -191,63 +197,63 @@ class Mai2Test : StringSpec({
"GetUserCourseApi" {
post("GetUserCourseApi", """{"userId":$userId,"nextIndex":0}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userCourseList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":0,"userCourseList":[]}""".jsonMap()
}
}
"GetUserChargeApi" {
post("GetUserChargeApi", """{"userId":$userId}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"length":0,"userChargeList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":0,"userChargeList":[]}""".jsonMap()
}
}
"GetUserFavoriteApi" {
post("GetUserFavoriteApi", """{"userId":$userId,"itemKind":1}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userFavoriteData":[]}""".jsonMap()
result shouldBe """{"userId":$userId}""".jsonMap()
}
post("GetUserFavoriteApi", """{"userId":$userId,"itemKind":2}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userFavoriteData":[]}""".jsonMap()
result shouldBe """{"userId":$userId}""".jsonMap()
}
post("GetUserFavoriteApi", """{"userId":$userId,"itemKind":3}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userFavoriteData":[]}""".jsonMap()
result shouldBe """{"userId":$userId}""".jsonMap()
}
post("GetUserFavoriteApi", """{"userId":$userId,"itemKind":4}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userFavoriteData":[]}""".jsonMap()
result shouldBe """{"userId":$userId}""".jsonMap()
}
post("GetUserFavoriteApi", """{"userId":$userId,"itemKind":5}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userFavoriteData":[]}""".jsonMap()
result shouldBe """{"userId":$userId}""".jsonMap()
}
}
"GetUserGhostApi" {
post("GetUserGhostApi", """{"userId":$userId}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"userGhostList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":0,"userGhostList":[]}""".jsonMap()
}
}
"GetUserMapApi" {
post("GetUserMapApi", """{"userId":$userId,"nextIndex":0,"maxCount":20}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userMapList":[{"mapId":1,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":2,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":3,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":4,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":5,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":6,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150001,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150002,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150005,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350001,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350006,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350007,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400001,"distance":14000,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400002,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400005,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400006,"distance":0,"isLock":false,"isClear":false,"isComplete":false}]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":22,"userMapList":[{"mapId":1,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":2,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":3,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":4,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":5,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":6,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150001,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150002,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":150005,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350001,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350006,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":350007,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400001,"distance":14000,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400002,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400003,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400004,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400005,"distance":0,"isLock":false,"isClear":false,"isComplete":false},{"mapId":400006,"distance":0,"isLock":false,"isClear":false,"isComplete":false}]}""".jsonMap()
}
}
"GetUserLoginBonusApi" {
post("GetUserLoginBonusApi", """{"userId":$userId,"nextIndex":0,"maxCount":20}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userLoginBonusList":[{"bonusId":38,"point":1,"isCurrent":true,"isComplete":false}]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":1,"userLoginBonusList":[{"bonusId":38,"point":1,"isCurrent":false,"isComplete":false}]}""".jsonMap()
}
}
"GetUserRegionApi" {
post("GetUserRegionApi", """{"userId":$userId}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"length":0,"userRegionList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"length":1,"userRegionList":[{"regionId":1,"playCount":1}]}""".jsonMap()
}
}
@@ -283,7 +289,7 @@ class Mai2Test : StringSpec({
"GetUserMusicApi" {
post("GetUserMusicApi", """{"userId":$userId,"nextIndex":0,"maxCount":50}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userMusicList":[{"userMusicDetailList":[{"musicId":11479,"level":2,"playCount":1,"achievement":997456,"comboStatus":1,"syncStatus":0,"deluxscoreMax":1725,"scoreRank":11,"extNum1":0}]}]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":1,"userMusicList":[{"userMusicDetailList":[{"musicId":11479,"level":2,"playCount":1,"achievement":997456,"comboStatus":1,"syncStatus":0,"deluxscoreMax":1725,"scoreRank":11,"extNum1":0}]}]}""".jsonMap()
}
}
@@ -310,7 +316,7 @@ class Mai2Test : StringSpec({
"GetUserFriendSeasonRankingApi" {
post("GetUserFriendSeasonRankingApi", """{"userId":$userId,"nextIndex":0,"maxCount":20}""").let { (_, result) ->
result shouldBe """{"userId":$userId,"nextIndex":0,"userFriendSeasonRankingList":[]}""".jsonMap()
result shouldBe """{"userId":$userId,"nextIndex":0,"length":0,"userFriendSeasonRankingList":[]}""".jsonMap()
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ class WaccaTest : StringSpec({
data class PostResp(val resp: HttpResponse, val res: List<Any>)
suspend fun post(url: String, par: String): PostResp {
requestNo++
val resp = HTTP.post("$HOST/gs/$CLIENT_ID/wacca/api/$url") {
val resp = HTTP.post("$HOST/g/wacca/api/$url") {
contentType(ContentType.Application.Json)
setBody("""{"requestNo": ${requestNo++},"appVersion": "$version","boardId": "$BOARD_ID","chipId": "$FULL_CLIENT_ID","params": $par}""")
}
@@ -1,92 +0,0 @@
package aquadx.sega.chusan
import ext.*
import aquadx.net.db.AquaUserServices
import aquadx.net.games.chu3.Chusan
import aquadx.net.utils.simpleDescribe
import aquadx.sega.allnet.TokenChecker
import aquadx.sega.chusan.handler.chusanInit
import aquadx.sega.chusan.model.Chu3Repos
import aquadx.sega.general.GameMusicPopularity
import aquadx.sega.general.MeowApi
import aquadx.sega.general.RequestContext
import aquadx.sega.general.service.CardService
import aquadx.sega.util.BasicMapper
import aquadx.sega.util.StringMapper
import aquadx.spring.Metrics
import jakarta.servlet.http.HttpServletRequest
import org.slf4j.LoggerFactory
import org.springframework.web.bind.annotation.RestController
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Suppress("unused")
@RestController
@API(value = ["/g/chu3/{version}/ChuniServlet", "/g/chu3/{version}"])
class ChusanController(
val mapper: StringMapper,
val cmMapper: BasicMapper,
val db: Chu3Repos,
val us: AquaUserServices,
val cardService: CardService,
val versionHelper: ChusanVersionHelper,
val props: ChusanProps,
val pop: GameMusicPopularity,
val chusan: Chusan
): MeowApi({ api, resp ->
if (resp is String) resp
else (if ("CM" in api || api == "GetUserItemApi" ) cmMapper else mapper).write(resp)
}) {
val log = LoggerFactory.getLogger(ChusanController::class.java)
val noopEndpoint = setOf("UpsertClientBookkeepingApi", "UpsertClientDevelopApi", "UpsertClientErrorApi",
"UpsertClientSettingApi", "UpsertClientTestmodeApi", "CreateTokenApi", "RemoveTokenApi", "UpsertClientUploadApi",
"PrinterLoginApi", "PrinterLogoutApi", "Ping", "GameLogoutApi", "RemoveMatchingMemberApi",
"UpsertClientPlayTimeApi", "UpsertClientGameStartApi", "UpsertClientGameEndApi")
init { chusanInit() }
val handlers = initH
@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.startsWith("CM") && api !in handlers) api = api.removePrefix("CM")
val token = TokenChecker.tokenShort()
log.info("$token : $api < ${data.toJson()}")
val noop = """{"returnCode":"1","apiName":"$api"}"""
if (api !in noopEndpoint && !handlers.containsKey(api)) {
log.warn("$token : $api > not found")
return noop
}
// 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("$token : $api > no-op")
return noop
}
return try {
Metrics.timer("aquadx_chusan_api_latency", "api" to api).recordCallable {
serialize(api, handlers[api]!!(ctx) ?: noop).also {
if (api !in setOf("GetUserItemApi", "GetGameEventApi"))
log.info("$token : $api > ${it.truncate(500)}")
}
}
} catch (e: Exception) {
Metrics.counter("aquadx_chusan_api_error", "api" to api, "error" to e.simpleDescribe()).increment()
throw e
}
}
}