diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt index 114c285e..ecf317e0 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/ChusanController.kt @@ -4,11 +4,10 @@ import ext.* import icu.samnyan.aqua.net.db.AquaUserServices import icu.samnyan.aqua.net.utils.simpleDescribe import icu.samnyan.aqua.sega.allnet.TokenChecker -import icu.samnyan.aqua.sega.chusan.handler.GameLoginHandler -import icu.samnyan.aqua.sega.chusan.handler.UpsertUserAllHandler import icu.samnyan.aqua.sega.chusan.handler.chusanInit import icu.samnyan.aqua.sega.chusan.model.Chu3Repos -import icu.samnyan.aqua.sega.general.* +import icu.samnyan.aqua.sega.general.MeowApi +import icu.samnyan.aqua.sega.general.RequestContext import icu.samnyan.aqua.sega.util.jackson.BasicMapper import icu.samnyan.aqua.sega.util.jackson.StringMapper import icu.samnyan.aqua.spring.Metrics @@ -16,7 +15,6 @@ 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) @@ -25,9 +23,6 @@ import kotlin.reflect.full.declaredMemberProperties @RestController @API(value = ["/g/chu3/{version}/ChuniServlet", "/g/chu3/{version}"]) class ChusanController( - val gameLogin: GameLoginHandler, - val upsertUserAll: UpsertUserAllHandler, - val mapper: StringMapper, val cmMapper: BasicMapper, val db: Chu3Repos, @@ -40,22 +35,12 @@ class ChusanController( }) { val log = LoggerFactory.getLogger(ChusanController::class.java) - // Below are code related to handling the handlers - val externalHandlers = mutableListOf("GameLoginApi", "UpsertUserAllApi") - 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 = 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") - } + val handlers = initH @API("/{endpoint}", "/MatchingServer/{endpoint}") fun handle(@PV endpoint: Str, @RB data: MutableMap, @PV version: Str, req: HttpServletRequest): Any { diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt index 1c4c0ffa..d0544720 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt @@ -5,17 +5,19 @@ import icu.samnyan.aqua.sega.allnet.TokenChecker import icu.samnyan.aqua.sega.chusan.ChusanController import icu.samnyan.aqua.sega.chusan.ChusanData import icu.samnyan.aqua.sega.chusan.model.request.UserCMissionResp -import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney -import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem +import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus 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.ZoneOffset import java.time.format.DateTimeFormatter @Suppress("UNCHECKED_CAST") fun ChusanController.chusanInit() { matchingApiInit() cmApiInit() + upsertApiInit() // Stub handlers "GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" } @@ -32,9 +34,6 @@ fun ChusanController.chusanInit() { "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"}""" } - // User handlers "GetUserData" { db.userData.findByCard_ExtId(uid)()?.let{ u -> mapOf("userId" to uid, "userData" to u) } @@ -233,29 +232,60 @@ fun ChusanController.chusanInit() { ) } - // Upserts - "UpsertUserChargelog" { - val charge = parsing { mapper.convert(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) + // TODO: Test login bonus + "GameLogin" { + fun process() { + val u = db.userData.findByCard_ExtId(uid)() ?: return + db.userData.save(u.apply { lastLoginDate = LocalDateTime.now() }) + + if (!props.loginBonusEnable) return + val bonusList = db.gameLoginBonusPresets.findLoginBonusPresets(1, 1) + + bonusList.forEach { preset -> + // Check if a user already has some progress and if not, add the login bonus entry + val bonus = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)() + ?: UserLoginBonus(1, uid.int, preset.id).let { db.userLoginBonus.save(it) } + if (bonus.isFinished) return@forEach + + // last login is 24 hours+ ago + if (bonus.lastUpdateDate.toEpochSecond(ZoneOffset.ofHours(0)) < + (LocalDateTime.now().minusHours(24).toEpochSecond(ZoneOffset.ofHours(0))) + ) { + var bCount = bonus.bonusCount + 1 + val lastUpdate = LocalDateTime.now() + val allLoginBonus = db.gameLoginBonus.findGameLoginBonus(1, preset.id) + .ifEmpty { return@forEach } + val maxNeededDays = allLoginBonus[0].needLoginDayCount + + // if all items are redeemed, then don't show the login bonuses. + var finished = false + if (bCount > maxNeededDays) { + if (preset.id < 3000) bCount = 1 + else finished = true + } + db.gameLoginBonus.findByRequiredDays(1, preset.id, bCount)()?.let { + db.userItem.save(UserItem(6, it.presentId, it.itemNum).apply { user = u }) + } + val toSave = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)() + ?: UserLoginBonus().apply { user = uid.int; presetId = preset.id; version = 1 } + + db.userLoginBonus.save(toSave.apply { + bonusCount = bCount + lastUpdateDate = lastUpdate + isWatched = false + isFinished = finished + }) + } + } + } + process() + + """{"returnCode":"1"}""" } } \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt index 3b510834..ad983f78 100644 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanCMApis.kt @@ -1,17 +1,30 @@ package icu.samnyan.aqua.sega.chusan.handler import com.fasterxml.jackson.core.type.TypeReference -import ext.int -import ext.invoke -import ext.mapApply -import ext.parsing +import ext.* import icu.samnyan.aqua.sega.chusan.ChusanController import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserGacha +import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem import java.time.LocalDateTime fun ChusanController.cmApiInit() { + "CMUpsertUserPrint" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintApi"}""" } + "CMUpsertUserPrintlog" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintlogApi"}""" } + + // 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) + } + "CMUpsertUserGacha" api@ { val (gachaId, placeId) = parsing { data["gachaId"]!!.int to data["placeId"]!!.int } diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt new file mode 100644 index 00000000..03f6a2e5 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanUpsertApis.kt @@ -0,0 +1,139 @@ +package icu.samnyan.aqua.sega.chusan.handler + +import ext.* +import icu.samnyan.aqua.sega.chusan.ChusanController +import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserAll +import icu.samnyan.aqua.sega.chusan.model.userdata.* +import icu.samnyan.aqua.sega.general.model.response.UserRecentRating +import java.nio.charset.StandardCharsets +import java.time.LocalDateTime + +@Suppress("UNCHECKED_CAST") +fun ChusanController.upsertApiInit() { + "UpsertUserChargelog" { + val charge = parsing { mapper.convert(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"}""" + } + + "UpsertUserAll" api@ { + val req = mapper.convert(data["upsertUserAll"], UpsertUserAll::class.java) + + req.run { + // UserData + val oldUser = db.userData.findByCard_ExtId(uid)() + val u = (userData?.get(0) ?: return@api null).apply { + id = oldUser?.id ?: 0 + card = oldUser?.card ?: us.cardRepo.findByExtId(uid).expect("Card not found") + userName = String(userName.toByteArray(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8) + userNameEx = "" + }.also { db.userData.saveAndFlush(it) } + + versionHelper[u.lastClientId] = u.lastDataVersion + + // Set users + listOfNotNull( + userPlaylogList, userGameOption, userMapAreaList, userCharacterList, userItemList, + userMusicDetailList, userActivityList, userChargeList, userCourseList, userDuelList, + ).flatten().forEach { it.user = u } + + // Ratings + fun Iterable.str() = joinToString(",") { "${it.musicId}:${it.difficultId}:${it.score}" } + + ls( + userRecentRatingList to "recent_rating_list", userRatingBaseList to "rating_base_list", + userRatingBaseHotList to "rating_hot_list", userRatingBaseNextList to "rating_next_list", + ).filter { it.first != null }.forEach { (list, key) -> + val d = db.userGeneralData.findByUserAndPropertyKey(u, key)() + ?: UserGeneralData().apply { user = u; propertyKey = key } + db.userGeneralData.save(d.apply { propertyValue = list!!.str() }) + } + + userFavoriteMusicList?.filter { it.musicId != -1 }?.let { list -> + val d = db.userGeneralData.findByUserAndPropertyKey(u, "favorite_music")() + ?: UserGeneralData().apply { user = u; propertyKey = "favorite_music" } + db.userGeneralData.save(d.apply { + propertyValue = list.distinct().joinToString(",") { it.musicId.toString() } }) + } + + // Playlog + userPlaylogList?.let { db.userPlaylog.saveAll(it) } + + // List data + userGameOption?.get(0)?.let { obj -> + db.userGameOption.saveAndFlush(obj.apply { + id = db.userGameOption.findSingleByUser(u)()?.id ?: 0 }) } + + userMapAreaList?.let { list -> + db.userMap.saveAll(list.distinctBy { it.mapAreaId }.mapApply { + id = db.userMap.findByUserAndMapAreaId(u, mapAreaId)?.id ?: 0 }) } + + userCharacterList?.let { list -> + db.userCharacter.saveAll(list.distinctBy { it.characterId }.mapApply { + id = db.userCharacter.findByUserAndCharacterId(u, characterId)?.id ?: 0 }) } + + userItemList?.let { list -> + db.userItem.saveAll(list.distinctBy { it.itemId to it.itemKind }.mapApply { + id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0 }) } + + userMusicDetailList?.let { list -> + db.userMusicDetail.saveAll(list.distinctBy { it.musicId to it.level }.mapApply { + id = db.userMusicDetail.findByUserAndMusicIdAndLevel(u, musicId, level)?.id ?: 0 }) } + + userActivityList?.let { list -> + db.userActivity.saveAll(list.distinctBy { it.activityId to it.kind }.mapApply { + id = db.userActivity.findByUserAndActivityIdAndKind(u, activityId, kind)?.id ?: 0 }) } + + userChargeList?.let { list -> + db.userCharge.saveAll(list.distinctBy { it.chargeId }.mapApply { + id = db.userCharge.findByUserAndChargeId(u, chargeId)()?.id ?: 0 }) } + + userCourseList?.let { list -> + db.userCourse.saveAll(list.distinctBy { it.courseId }.mapApply { + id = db.userCourse.findByUserAndCourseId(u, courseId)?.id ?: 0 }) } + + userDuelList?.let { list -> + db.userDuel.saveAll(list.distinctBy { it.duelId }.mapApply { + id = db.userDuel.findByUserAndDuelId(u, duelId)?.id ?: 0 }) } + + // Need testing + userLoginBonusList?.let { list -> + db.userLoginBonus.saveAll(list.distinctBy { it["presetId"] as String }.map { + val id = it["presetId"]!!.int + (db.userLoginBonus.findLoginBonus(uid.int, 1, id)() ?: UserLoginBonus()).apply { + user = u.id.toInt() + presetId = id + lastUpdateDate = LocalDateTime.now() + isWatched = true + } + }) + } + + req.userCMissionList?.forEach { d -> + (db.userCMission.findByUser_Card_ExtIdAndMissionId(uid, d.missionId)() + ?: UserCMission().apply { + missionId = d.missionId + user = u + } + ).apply { point = d.point }.also { db.userCMission.save(it) } + + d.userCMissionProgressList?.forEach inner@ { p -> + (db.userCMissionProgress.findByUser_Card_ExtIdAndMissionIdAndOrder(uid, d.missionId, p.order)() + ?: UserCMissionProgress().apply { + missionId = d.missionId + order = p.order + user = u + } + ).apply { + progress = p.progress + stage = p.stage + }.also { db.userCMissionProgress.save(it) } + } + } + } + + """{"returnCode":1}""" + } +} \ No newline at end of file diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt deleted file mode 100644 index a98a1935..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/GameLoginHandler.kt +++ /dev/null @@ -1,76 +0,0 @@ -package icu.samnyan.aqua.sega.chusan.handler - -import ext.int -import ext.invoke -import ext.long -import icu.samnyan.aqua.sega.chusan.ChusanProps -import icu.samnyan.aqua.sega.chusan.model.Chu3Repos -import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem -import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus -import icu.samnyan.aqua.sega.general.BaseHandler -import lombok.AllArgsConstructor -import org.springframework.stereotype.Component -import java.time.LocalDateTime -import java.time.ZoneOffset - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@AllArgsConstructor -@Component("ChusanGameLoginHandler") -class GameLoginHandler( - val props: ChusanProps, - val db: Chu3Repos -) : BaseHandler { - - override fun handle(request: Map): Any? { - val uid = request["userId"]!!.long - fun process() { - val u = db.userData.findByCard_ExtId(uid)() ?: return - db.userData.save(u.apply { lastLoginDate = LocalDateTime.now() }) - - if (!props.loginBonusEnable) return - val bonusList = db.gameLoginBonusPresets.findLoginBonusPresets(1, 1) - - bonusList.forEach { preset -> - // Check if a user already has some progress and if not, add the login bonus entry - val bonus = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)() - ?: UserLoginBonus(1, uid.int, preset.id).let { db.userLoginBonus.save(it) } - if (bonus.isFinished) return@forEach - - // last login is 24 hours+ ago - if (bonus.lastUpdateDate.toEpochSecond(ZoneOffset.ofHours(0)) < - (LocalDateTime.now().minusHours(24).toEpochSecond(ZoneOffset.ofHours(0))) - ) { - var bCount = bonus.bonusCount + 1 - val lastUpdate = LocalDateTime.now() - val allLoginBonus = db.gameLoginBonus.findGameLoginBonus(1, preset.id) - .ifEmpty { return@forEach } - val maxNeededDays = allLoginBonus[0].needLoginDayCount - - // if all items are redeemed, then don't show the login bonuses. - var finished = false - if (bCount > maxNeededDays) { - if (preset.id < 3000) bCount = 1 - else finished = true - } - db.gameLoginBonus.findByRequiredDays(1, preset.id, bCount)()?.let { - db.userItem.save(UserItem(6, it.presentId, it.itemNum).apply { user = u }) - } - val toSave = db.userLoginBonus.findLoginBonus(uid.int, 1, preset.id)() - ?: UserLoginBonus().apply { user = uid.int; presetId = preset.id; version = 1 } - - db.userLoginBonus.save(toSave.apply { - bonusCount = bCount - lastUpdateDate = lastUpdate - isWatched = false - isFinished = finished - }) - } - } - } - process() - - return """{"returnCode":"1"}""" - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt b/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt deleted file mode 100644 index bab81dae..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/chusan/handler/UpsertUserAllHandler.kt +++ /dev/null @@ -1,153 +0,0 @@ -package icu.samnyan.aqua.sega.chusan.handler - -import ext.* -import icu.samnyan.aqua.sega.chusan.ChusanVersionHelper -import icu.samnyan.aqua.sega.chusan.model.Chu3Repos -import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserAll -import icu.samnyan.aqua.sega.chusan.model.userdata.UserCMission -import icu.samnyan.aqua.sega.chusan.model.userdata.UserCMissionProgress -import icu.samnyan.aqua.sega.chusan.model.userdata.UserGeneralData -import icu.samnyan.aqua.sega.chusan.model.userdata.UserLoginBonus -import icu.samnyan.aqua.sega.general.BaseHandler -import icu.samnyan.aqua.sega.general.dao.CardRepository -import icu.samnyan.aqua.sega.general.model.response.UserRecentRating -import icu.samnyan.aqua.sega.util.jackson.StringMapper -import lombok.AllArgsConstructor -import org.springframework.stereotype.Component -import java.nio.charset.StandardCharsets -import java.time.LocalDateTime - -/** - * The handler for save user data. Only send in the end of the session. - * - * @author samnyan (privateamusement@protonmail.com) - */ -@AllArgsConstructor -@Component("ChusanUpsertUserAllHandler") -class UpsertUserAllHandler( - val mapper: StringMapper, - val rp: Chu3Repos, - val cardRepo: CardRepository, - val versionHelper: ChusanVersionHelper, -) : BaseHandler { - val logger = logger() - - override fun handle(request: Map): Any? { - val ext = request["userId"]?.long ?: return null - val req = mapper.convert(request["upsertUserAll"], UpsertUserAll::class.java) - - req.run { - // UserData - val oldUser = rp.userData.findByCard_ExtId(ext)() - val u = (userData?.get(0) ?: return null).apply { - id = oldUser?.id ?: 0 - card = oldUser?.card ?: cardRepo.findByExtId(ext).expect("Card not found") - userName = String(userName.toByteArray(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8) - userNameEx = "" - }.also { rp.userData.saveAndFlush(it) } - - versionHelper[u.lastClientId] = u.lastDataVersion - - // Set users - listOfNotNull( - userPlaylogList, userGameOption, userMapAreaList, userCharacterList, userItemList, - userMusicDetailList, userActivityList, userChargeList, userCourseList, userDuelList, - ).flatten().forEach { it.user = u } - - // Ratings - fun Iterable.str() = joinToString(",") { "${it.musicId}:${it.difficultId}:${it.score}" } - - ls( - userRecentRatingList to "recent_rating_list", userRatingBaseList to "rating_base_list", - userRatingBaseHotList to "rating_hot_list", userRatingBaseNextList to "rating_next_list", - ).filter { it.first != null }.forEach { (list, key) -> - val d = rp.userGeneralData.findByUserAndPropertyKey(u, key)() - ?: UserGeneralData().apply { user = u; propertyKey = key } - rp.userGeneralData.save(d.apply { propertyValue = list!!.str() }) - } - - userFavoriteMusicList?.let { list -> - val d = rp.userGeneralData.findByUserAndPropertyKey(u, "favorite_music")() - ?: UserGeneralData().apply { user = u; propertyKey = "favorite_music" } - rp.userGeneralData.save(d.apply { propertyValue = list.joinToString(",") { it.musicId.toString() } }) - } - - // Playlog - userPlaylogList?.let { rp.userPlaylog.saveAll(it) } - - // List data - userGameOption?.get(0)?.let { obj -> - rp.userGameOption.saveAndFlush(obj.apply { - id = rp.userGameOption.findSingleByUser(u)()?.id ?: 0 }) } - - userMapAreaList?.let { list -> - rp.userMap.saveAll(list.distinctBy { it.mapAreaId }.mapApply { - id = rp.userMap.findByUserAndMapAreaId(u, mapAreaId)?.id ?: 0 }) } - - userCharacterList?.let { list -> - rp.userCharacter.saveAll(list.distinctBy { it.characterId }.mapApply { - id = rp.userCharacter.findByUserAndCharacterId(u, characterId)?.id ?: 0 }) } - - userItemList?.let { list -> - rp.userItem.saveAll(list.distinctBy { it.itemId to it.itemKind }.mapApply { - id = rp.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0 }) } - - userMusicDetailList?.let { list -> - rp.userMusicDetail.saveAll(list.distinctBy { it.musicId to it.level }.mapApply { - id = rp.userMusicDetail.findByUserAndMusicIdAndLevel(u, musicId, level)?.id ?: 0 }) } - - userActivityList?.let { list -> - rp.userActivity.saveAll(list.distinctBy { it.activityId to it.kind }.mapApply { - id = rp.userActivity.findByUserAndActivityIdAndKind(u, activityId, kind)?.id ?: 0 }) } - - userChargeList?.let { list -> - rp.userCharge.saveAll(list.distinctBy { it.chargeId }.mapApply { - id = rp.userCharge.findByUserAndChargeId(u, chargeId)()?.id ?: 0 }) } - - userCourseList?.let { list -> - rp.userCourse.saveAll(list.distinctBy { it.courseId }.mapApply { - id = rp.userCourse.findByUserAndCourseId(u, courseId)?.id ?: 0 }) } - - userDuelList?.let { list -> - rp.userDuel.saveAll(list.distinctBy { it.duelId }.mapApply { - id = rp.userDuel.findByUserAndDuelId(u, duelId)?.id ?: 0 }) } - - // Need testing - userLoginBonusList?.let { list -> - rp.userLoginBonus.saveAll(list.distinctBy { it["presetId"] as String }.map { - val id = it["presetId"]!!.int - (rp.userLoginBonus.findLoginBonus(ext.int, 1, id)() ?: UserLoginBonus()).apply { - user = u.id.toInt() - presetId = id - lastUpdateDate = LocalDateTime.now() - isWatched = true - } - }) - } - - req.userCMissionList?.forEach { d -> - (rp.userCMission.findByUser_Card_ExtIdAndMissionId(ext, d.missionId)() - ?: UserCMission().apply { - missionId = d.missionId - user = u - } - ).apply { point = d.point }.also { rp.userCMission.save(it) } - - d.userCMissionProgressList?.forEach inner@ { p -> - (rp.userCMissionProgress.findByUser_Card_ExtIdAndMissionIdAndOrder(ext, d.missionId, p.order)() - ?: UserCMissionProgress().apply { - missionId = d.missionId - order = p.order - user = u - } - ).apply { - progress = p.progress - stage = p.stage - }.also { rp.userCMissionProgress.save(it) } - } - } - } - - return """{"returnCode":1}""" - } -}