forked from Cookies_Github_mirror/AquaDX
[O] Make handlers abstract
This commit is contained in:
270
src/main/java/icu/samnyan/aqua/sega/chusan/ChusanApis.kt
Normal file
270
src/main/java/icu/samnyan/aqua/sega/chusan/ChusanApis.kt
Normal file
@@ -0,0 +1,270 @@
|
||||
package icu.samnyan.aqua.sega.chusan
|
||||
|
||||
import ext.*
|
||||
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.MatchingWaitState
|
||||
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.UserMusicDetail
|
||||
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
val chusanInit: ChusanController.() -> Unit = {
|
||||
// Stub handlers
|
||||
"GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" }
|
||||
"GetGameIdlist" { """{"type":"${data["type"]}","length":"0","gameIdlistList":[]}""" }
|
||||
|
||||
"GetTeamCourseSetting" { """{"userId":"${data["userId"]}","length":"0","nextIndex":"0","teamCourseSettingList":[]}""" }
|
||||
"GetTeamCourseRule" { """{"userId":"${data["userId"]}","length":"0","nextIndex":"0","teamCourseRuleList":[]}""" }
|
||||
"GetUserCtoCPlay" { """{"userId":"${data["userId"]}","orderBy":"0","count":"0","userCtoCPlayList":[]}""" }
|
||||
"GetUserRivalMusic" { """{"userId":"${data["userId"]}","rivalId":"0","length":"0","nextIndex":"0","userRivalMusicList":[]}""" }
|
||||
"GetUserRivalData" { """{"userId":"${data["userId"]}","length":"0","userRivalData":[]}""" }
|
||||
"GetUserRegion" { """{"userId":"${data["userId"]}","length":"0","userRegionList":[]}""" }
|
||||
"GetUserPrintedCard" { """{"userId":"${data["userId"]}","length":0,"nextIndex":-1,"userPrintedCardList":[]}""" }
|
||||
"GetUserSymbolChatSetting" { """{"userId":"${data["userId"]}","length":"0","symbolChatInfoList":[]}""" }
|
||||
"GetUserNetBattleData" { """{"userId":"${data["userId"]}","userNetBattleData":{"recentNBSelectMusicList":[],"recentNBMusicList":[]}}""" }
|
||||
"GetUserNetBattleRankingInfo" { """{"userId":"${data["userId"]}","length":"0","userNetBattleRankingInfoList":{}}""" }
|
||||
|
||||
"CMUpsertUserPrint" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintApi"}""" }
|
||||
"CMUpsertUserPrintlog" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintlogApi"}""" }
|
||||
|
||||
// Matching TODO: Actually implement this
|
||||
"EndMatching" { """{"matchingResult":{"matchingMemberInfoList":[],"matchingMemberRoleList":[],"reflectorUri":""}}""" }
|
||||
"GetMatchingState" { """{"matchingWaitState":{"restMSec":"30000","pollingInterval":"10","matchingMemberInfoList":[],"isFinish":"true"}}""" }
|
||||
|
||||
"BeginMatching" {
|
||||
val memberInfo = parsing { mapper.convert<MatchingMemberInfo>(data["matchingMemberInfo"] as JDict) }
|
||||
mapOf("roomId" to 1, "matchingWaitState" to MatchingWaitState(listOf(memberInfo)))
|
||||
}
|
||||
|
||||
// User handlers
|
||||
"GetUserData" {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
mapOf("userId" to uid, "userData" to user)
|
||||
}
|
||||
"GetUserOption" {
|
||||
val userGameOption = db.userGameOption.findSingleByUser_Card_ExtId(uid)() ?: (400 - "User not found")
|
||||
mapOf("userId" to uid, "userGameOption" to userGameOption)
|
||||
}
|
||||
"GetUserActivity" {
|
||||
val kind = parsing { data["kind"]!!.int }
|
||||
val a = db.userActivity.findAllByUser_Card_ExtIdAndKind(uid, kind).sortedBy { -it.sortNumber }
|
||||
mapOf("userId" to uid, "length" to a.size, "kind" to kind, "userActivityList" to a)
|
||||
}
|
||||
|
||||
"GetUserCharge" {
|
||||
val lst = db.userCharge.findByUser_Card_ExtId(uid)
|
||||
mapOf("userId" to uid, "length" to lst.size, "userChargeList" to lst)
|
||||
}
|
||||
|
||||
"GetUserDuel" {
|
||||
val lst = db.userDuel.findByUser_Card_ExtId(uid)
|
||||
mapOf("userId" to uid, "length" to lst.size, "userDuelList" to lst)
|
||||
}
|
||||
|
||||
"GetUserGacha" {
|
||||
val lst = db.userGacha.findByUser_Card_ExtId(uid)
|
||||
mapOf("userId" to uid, "length" to lst.size, "userGachaList" to lst)
|
||||
}
|
||||
|
||||
"RollGacha" {
|
||||
val (gachaId, times) = parsing { data["gachaId"]!!.int to data["times"]!!.int }
|
||||
val lst = db.gameGachaCard.findAllByGachaId(gachaId).shuffled().take(times)
|
||||
mapOf("length" to lst.size, "gameGachaCardList" to lst)
|
||||
}
|
||||
|
||||
"GetGameGachaCardById" { db.gameGachaCard.findAllByGachaId(parsing { data["gachaId"]!!.int }).let {
|
||||
mapOf("gachaId" to it.size, "length" to it.size, "isPickup" to false, "gameGachaCardList" to it,
|
||||
"emissionList" to empty, "afterCalcList" to empty
|
||||
)
|
||||
} }
|
||||
|
||||
"GetUserCMission" {
|
||||
parsing { UserCMissionResp().apply {
|
||||
userId = uid
|
||||
missionId = parsing { data["missionId"]!!.int }
|
||||
} }.apply {
|
||||
db.userCMission.findByUser_Card_ExtIdAndMissionId(uid, missionId)()?.let {
|
||||
point = it.point
|
||||
userCMissionProgressList = db.userCMissionProgress.findByUser_Card_ExtIdAndMissionId(uid, missionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"GetUserCardPrintError" {
|
||||
val lst = db.userCardPrintState.findByUser_Card_ExtIdAndHasCompleted(uid, false)
|
||||
mapOf("userId" to uid, "length" to lst.size, "userCardPrintStateList" to lst)
|
||||
}
|
||||
|
||||
ls("GetUserCharacter", "CMGetUserCharacter") all {
|
||||
// Let's try not paging at all
|
||||
val lst = db.userCharacter.findByUser_Card_ExtId(uid)
|
||||
mapOf("userId" to uid, "length" to lst.size, "nextIndex" to -1, "userCharacterList" to lst)
|
||||
}
|
||||
|
||||
"GetUserCourse" {
|
||||
val lst = db.userCourse.findByUser_Card_ExtId(uid)
|
||||
mutableMapOf("userId" to uid, "length" to lst.size, "userCourseList" to lst).apply {
|
||||
if (data.containsKey("nextIndex")) this["nextIndex"] = -1
|
||||
}
|
||||
}
|
||||
|
||||
ls("GetUserItem", "CMGetUserItem") all {
|
||||
val kind = parsing { (data["nextIndex"]!!.long / 10000000000L).int }
|
||||
val maxCount = parsing { data["maxCount"]!!.int }
|
||||
// TODO pagination
|
||||
val lst = db.userItem.findAllByUser_Card_ExtIdAndItemKind(uid, kind).take(maxCount)
|
||||
|
||||
// TODO: All unlock
|
||||
mapOf("userId" to uid, "length" to lst.size, "nextIndex" to -1, "itemKind" to kind, "userItemList" to lst)
|
||||
}
|
||||
|
||||
"GetUserFavoriteItem" {
|
||||
val kind = parsing { data["kind"]!!.int }
|
||||
|
||||
// TODO: Actually store this info at UpsertUserAll
|
||||
val fav = when (kind) {
|
||||
1 -> "favorite_music"
|
||||
3 -> "favorite_chara"
|
||||
else -> null
|
||||
}?.let { db.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(uid, it)() }?.propertyValue
|
||||
|
||||
val lst = fav?.ifBlank { null }?.split(",")?.map { it.int } ?: emptyList()
|
||||
mapOf("userId" to uid, "kind" to kind, "length" to lst.size, "nextIndex" to -1, "userFavoriteItemList" to lst)
|
||||
}
|
||||
|
||||
val userPreviewKeys = ("userName,reincarnationNum,level,exp,playerRating,lastGameId,lastRomVersion," +
|
||||
"lastDataVersion,trophyId,classEmblemMedal,classEmblemBase,battleRankId").split(',').toSet()
|
||||
|
||||
"GetUserPreview" {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
val chara = db.userCharacter.findByUserAndCharacterId(user, user.characterId)
|
||||
val option = db.userGameOption.findSingleByUser(user)()
|
||||
val userDict = user.toJson().jsonMap().filterKeys { it in userPreviewKeys }
|
||||
|
||||
mapOf(
|
||||
"userId" to uid, "isLogin" to false, "emoneyBrandId" to 0,
|
||||
"lastLoginDate" to user.lastLoginDate, "lastPlayDate" to user.lastPlayDate,
|
||||
"userCharacter" to chara,
|
||||
"playerLevel" to option?.playerLevel,
|
||||
"rating" to option?.rating,
|
||||
"headphone" to option?.headphone,
|
||||
"chargeState" to 1, "userNameEx" to "", "banState" to 0,
|
||||
) + userDict
|
||||
}
|
||||
|
||||
"GetUserMusic" {
|
||||
// Compatibility: Older chusan uses boolean for isSuccess
|
||||
fun checkAncient(d: List<UserMusicDetail>) =
|
||||
data["version"]?.double?.let { if (it >= 2.15) d else d.map {
|
||||
d.toJson().jsonMap().toMutableMap().apply { this["isSuccess"] = this["isSuccess"].truthy }
|
||||
} } ?: d
|
||||
|
||||
val lst = db.userMusicDetail.findByUser_Card_ExtId(uid).groupBy { it.musicId }
|
||||
.mapValues { mapOf("length" to it.value.size, "userMusicDetailList" to checkAncient(it.value)) }
|
||||
|
||||
mapOf("userId" to uid, "length" to lst.size, "nextIndex" to -1, "userMusicList" to lst.values)
|
||||
}
|
||||
|
||||
"GetUserLoginBonus" api@ {
|
||||
if (!props.loginBonusEnable) return@api mapOf("userId" to uid, "length" to 0, "userLoginBonusList" to empty)
|
||||
|
||||
val lst = db.userLoginBonus.findAllLoginBonus(uid.int, 1, 0)
|
||||
mapOf("userId" to uid, "length" to lst.size, "userLoginBonusList" to lst)
|
||||
}
|
||||
|
||||
"GetUserRecentRating" {
|
||||
val lst = db.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(uid, "recent_rating_list")()
|
||||
?.propertyValue?.ifBlank { null }
|
||||
?.split(',')?.dropLastWhile { it.isEmpty() }?.map { it.split(':') }
|
||||
?.map { (musicId, level, score) -> UserRecentRating(musicId.int, level.int, "2000001", score.int) }
|
||||
?: listOf()
|
||||
|
||||
mapOf("userId" to uid, "length" to lst.size, "userRecentRatingList" to lst)
|
||||
}
|
||||
|
||||
"GetUserMapArea" {
|
||||
val maps = parsing { data["mapAreaIdList"] as List<Map<String, String>> }
|
||||
.mapNotNull { it["mapAreaId"]?.toIntOrNull() }
|
||||
|
||||
mapOf("userId" to uid, "userMapAreaList" to db.userMap.findAllByUserCardExtIdAndMapAreaIdIn(uid, maps))
|
||||
}
|
||||
|
||||
"GetUserTeam" {
|
||||
val playDate = parsing { data["playDate"] as String }
|
||||
val team = db.userData.findByCard_ExtId(uid)()?.card?.aquaUser?.gameOptions?.chusanTeamName?.ifBlank { null }
|
||||
?: props.teamName?.ifBlank { null } ?: "一緒に歌おう!"
|
||||
|
||||
mapOf(
|
||||
"userId" to uid, "teamId" to 1, "teamRank" to 1, "teamName" to team,
|
||||
"userTeamPoint" to mapOf("userId" to uid, "teamId" to 1, "orderId" to 1, "teamPoint" to 1, "aggrDate" to playDate)
|
||||
)
|
||||
}
|
||||
|
||||
// Game settings
|
||||
"GetGameSetting" {
|
||||
val version = data["version"].toString()
|
||||
|
||||
// Fixed reboot time triggers chusan maintenance lockout, so let's try minime method which sets it dynamically
|
||||
// Special thanks to skogaby
|
||||
// Hardcode so that the reboot time always started 3 hours ago and ended 2 hours ago
|
||||
val fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss")
|
||||
|
||||
// Get the request url as te address
|
||||
val addr = (req.getHeader("wrapper original url") ?: req.requestURL.toString())
|
||||
.removeSuffix("GetGameSettingApi")
|
||||
|
||||
mapOf(
|
||||
"gameSetting" to mapOf(
|
||||
"romVersion" to "$version.00", // Chusan checks these two versions to determine if it can enable game modes
|
||||
"dataVersion" to versionHelper[data["clientId"].toString()],
|
||||
"isMaintenance" to false,
|
||||
"requestInterval" to 0,
|
||||
"rebootStartTime" to LocalDateTime.now().minusHours(3).format(fmt),
|
||||
"rebootEndTime" to LocalDateTime.now().minusHours(2).format(fmt),
|
||||
"isBackgroundDistribute" to false,
|
||||
"maxCountCharacter" to 300,
|
||||
"maxCountItem" to 300,
|
||||
"maxCountMusic" to 300,
|
||||
"matchStartTime" to LocalDateTime.now().minusHours(5).format(fmt),
|
||||
"matchEndTime" to LocalDateTime.now().plusHours(5).format(fmt),
|
||||
"matchTimeLimit" to 10,
|
||||
"matchErrorLimit" to 10,
|
||||
"matchingUri" to addr,
|
||||
"matchingUriX" to addr,
|
||||
"udpHolePunchUri" to addr,
|
||||
"reflectorUri" to addr
|
||||
),
|
||||
"isDumpUpload" to false,
|
||||
"isAou" to false
|
||||
)
|
||||
}
|
||||
|
||||
// Upserts
|
||||
"UpsertUserChargelog" {
|
||||
val charge = parsing { mapper.convert<UserCharge>(data["userCharge"] as JDict) }
|
||||
charge.user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
charge.id = db.userCharge.findByUser_Card_ExtIdAndChargeId(uid, charge.chargeId)?.id ?: 0
|
||||
db.userCharge.save(charge)
|
||||
"""{"returnCode":"1"}"""
|
||||
}
|
||||
|
||||
// Static
|
||||
"GetGameEvent" static { db.gameEvent.findByEnable(true).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 }
|
||||
|
||||
// CardMaker (TODO: Somebody test this, I don't have a card maker)
|
||||
"CMGetUserData" {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
user.userEmoney = UserEmoney()
|
||||
mapOf("userId" to uid, "userData" to user, "userEmoney" to user.userEmoney)
|
||||
}
|
||||
"CMGetUserPreview" {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user