mirror of
https://github.com/MewoLab/AquaDX.git
synced 2026-02-11 09:47:28 +08:00
[F] Fix mai2 import
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
package icu.samnyan.aqua.api.model.resp.sega.maimai2.external;
|
|
||||||
|
|
||||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class Maimai2DataExport {
|
|
||||||
public String gameId = "SDEZ";
|
|
||||||
public Mai2UserDetail userData;
|
|
||||||
public Mai2UserExtend userExtend;
|
|
||||||
public Mai2UserOption userOption;
|
|
||||||
public List<Mai2MapEncountNpc> mapEncountNpcList;
|
|
||||||
public List<Mai2UserAct> userActList;
|
|
||||||
public List<Mai2UserCharacter> userCharacterList;
|
|
||||||
public List<Mai2UserCharge> userChargeList;
|
|
||||||
public List<Mai2UserCourse> userCourseList;
|
|
||||||
public List<Mai2UserFavorite> userFavoriteList;
|
|
||||||
public List<Mai2UserFriendSeasonRanking> userFriendSeasonRankingList;
|
|
||||||
public List<Mai2UserGeneralData> userGeneralDataList;
|
|
||||||
public List<Mai2UserItem> userItemList;
|
|
||||||
public List<Mai2UserLoginBonus> userLoginBonusList;
|
|
||||||
public List<Mai2UserMap> userMapList;
|
|
||||||
public List<Mai2UserMusicDetail> userMusicDetailList;
|
|
||||||
public List<Mai2UserPlaylog> userPlaylogList;
|
|
||||||
public Mai2UserUdemae userUdemae;
|
|
||||||
}
|
|
||||||
29
src/main/java/icu/samnyan/aqua/api/model/resp/sega/maimai2/external/Maimai2DataExport.kt
vendored
Normal file
29
src/main/java/icu/samnyan/aqua/api/model/resp/sega/maimai2/external/Maimai2DataExport.kt
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package icu.samnyan.aqua.api.model.resp.sega.maimai2.external
|
||||||
|
|
||||||
|
import icu.samnyan.aqua.sega.maimai2.model.userdata.*
|
||||||
|
|
||||||
|
data class Maimai2DataExport(
|
||||||
|
var userData: Mai2UserDetail,
|
||||||
|
var userExtend: Mai2UserExtend,
|
||||||
|
var userOption: Mai2UserOption,
|
||||||
|
var userUdemae: Mai2UserUdemae,
|
||||||
|
var mapEncountNpcList: List<Mai2MapEncountNpc>,
|
||||||
|
var userActList: List<Mai2UserAct>,
|
||||||
|
var userCharacterList: List<Mai2UserCharacter>,
|
||||||
|
var userChargeList: List<Mai2UserCharge>,
|
||||||
|
var userCourseList: List<Mai2UserCourse>,
|
||||||
|
var userFavoriteList: List<Mai2UserFavorite>,
|
||||||
|
var userFriendSeasonRankingList: List<Mai2UserFriendSeasonRanking>,
|
||||||
|
var userGeneralDataList: List<Mai2UserGeneralData>,
|
||||||
|
var userItemList: List<Mai2UserItem>,
|
||||||
|
var userLoginBonusList: List<Mai2UserLoginBonus>,
|
||||||
|
var userMapList: List<Mai2UserMap>,
|
||||||
|
var userMusicDetailList: List<Mai2UserMusicDetail>,
|
||||||
|
var userPlaylogList: List<Mai2UserPlaylog>,
|
||||||
|
var gameId: String = "SDEZ",
|
||||||
|
) {
|
||||||
|
constructor() : this(Mai2UserDetail(), Mai2UserExtend(), Mai2UserOption(), Mai2UserUdemae(),
|
||||||
|
mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(),
|
||||||
|
mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(), mutableListOf(),
|
||||||
|
mutableListOf())
|
||||||
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
package icu.samnyan.aqua.net.games
|
package icu.samnyan.aqua.net.games
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||||
import ext.JACKSON
|
import ext.JACKSON
|
||||||
|
import ext.minus
|
||||||
import ext.splitLines
|
import ext.splitLines
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@@ -54,7 +59,7 @@ abstract class ImportController<T: Any>(
|
|||||||
lists[tb.name]?.add(obj) ?: field.set(data, obj)
|
lists[tb.name]?.add(obj) ?: field.set(data, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImportResult(errors, warnings, JACKSON.writeValueAsString(data))
|
return ImportResult(errors, warnings, JACKSON_ARTEMIS.writeValueAsString(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
@@ -69,7 +74,7 @@ abstract class ImportController<T: Any>(
|
|||||||
// Process Nones
|
// Process Nones
|
||||||
dict = dict.filterValues { it != "None" }
|
dict = dict.filterValues { it != "None" }
|
||||||
|
|
||||||
return JACKSON.convertValue(dict, type.java)
|
return JACKSON_ARTEMIS.convertValue(dict, type.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,3 +101,18 @@ fun String.asSqlInsert(): SqlInsert {
|
|||||||
assert(cols.size == vals.size) { "Column and value count mismatch" }
|
assert(cols.size == vals.size) { "Column and value count mismatch" }
|
||||||
return SqlInsert(table, cols.zip(vals).toMap())
|
return SqlInsert(table, cols.zip(vals).toMap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
|
||||||
|
val JSON_INT_LIST_STR = SimpleModule().addDeserializer(List::class.java, object : JsonDeserializer<List<Integer>>() {
|
||||||
|
override fun deserialize(parser: JsonParser, context: DeserializationContext) =
|
||||||
|
try {
|
||||||
|
val text = parser.text.trim('[', ']')
|
||||||
|
if (text.isEmpty()) emptyList()
|
||||||
|
else text.split(',').map { it.trim().toInt() } as List<Integer>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
400 - "Invalid list value ${parser.text}: $e" }
|
||||||
|
})
|
||||||
|
|
||||||
|
val JACKSON_ARTEMIS = JACKSON.copy().apply {
|
||||||
|
registerModule(JSON_INT_LIST_STR)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package icu.samnyan.aqua.net.games
|
package icu.samnyan.aqua.net.games
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||||
|
import ext.JACKSON
|
||||||
import ext.JavaSerializable
|
import ext.JavaSerializable
|
||||||
import icu.samnyan.aqua.sega.general.model.Card
|
import icu.samnyan.aqua.sega.general.model.Card
|
||||||
import jakarta.persistence.*
|
import jakarta.persistence.*
|
||||||
@@ -11,6 +12,8 @@ import org.springframework.data.jpa.repository.JpaRepository
|
|||||||
import org.springframework.data.jpa.repository.Query
|
import org.springframework.data.jpa.repository.Query
|
||||||
import org.springframework.data.repository.NoRepositoryBean
|
import org.springframework.data.repository.NoRepositoryBean
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
data class TrendOut(val date: String, val rating: Int, val plays: Int)
|
data class TrendOut(val date: String, val rating: Int, val plays: Int)
|
||||||
|
|
||||||
@@ -99,13 +102,16 @@ interface IGenericGamePlaylog {
|
|||||||
val isAllPerfect: Boolean
|
val isAllPerfect: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
open class BaseEntity(
|
open class BaseEntity(
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
) : JavaSerializable
|
) : JavaSerializable {
|
||||||
|
override fun toString() = JACKSON.writeValueAsString(this)
|
||||||
|
}
|
||||||
|
|
||||||
@NoRepositoryBean
|
@NoRepositoryBean
|
||||||
interface GenericUserDataRepo<T : IGenericUserData> : JpaRepository<T, Long> {
|
interface GenericUserDataRepo<T : IGenericUserData> : JpaRepository<T, Long> {
|
||||||
|
|||||||
@@ -34,8 +34,5 @@ class Mai2Import : ImportController<Maimai2DataExport>(
|
|||||||
// "mai2_profile_region" to ImportClass(UserRegion::class),
|
// "mai2_profile_region" to ImportClass(UserRegion::class),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun createEmpty() = Maimai2DataExport("SDEZ", Mai2UserDetail(), Mai2UserExtend(), Mai2UserOption(),
|
override fun createEmpty() = Maimai2DataExport()
|
||||||
ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(),
|
|
||||||
ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(),
|
|
||||||
ArrayList(), Mai2UserUdemae())
|
|
||||||
}
|
}
|
||||||
@@ -12,11 +12,11 @@ import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserEntity
|
|||||||
import org.springframework.transaction.PlatformTransactionManager
|
import org.springframework.transaction.PlatformTransactionManager
|
||||||
import org.springframework.transaction.support.TransactionTemplate
|
import org.springframework.transaction.support.TransactionTemplate
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
import kotlin.io.path.writeText
|
import kotlin.io.path.writeText
|
||||||
|
import kotlin.reflect.KMutableProperty1
|
||||||
import kotlin.reflect.full.declaredMembers
|
import kotlin.reflect.full.declaredMembers
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -58,7 +58,7 @@ class Maimai2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use reflection to get all properties in Mai2Repos with matching names in Maimai2DataExport
|
// Use reflection to get all properties in Mai2Repos with matching names in Maimai2DataExport
|
||||||
val exportFields: Map<Field, UserLinked<*>> = listOf(*Maimai2DataExport::class.java.declaredFields)
|
val exportFields: Map<KMutableProperty1<Maimai2DataExport, Any>, UserLinked<*>> = Maimai2DataExport::class.vars()
|
||||||
.filter { f -> f.name !in setOf("gameId", "userData") }
|
.filter { f -> f.name !in setOf("gameId", "userData") }
|
||||||
.associateWith { Mai2Repos::class.declaredMembers
|
.associateWith { Mai2Repos::class.declaredMembers
|
||||||
.filter { f -> f returns UserLinked::class }
|
.filter { f -> f returns UserLinked::class }
|
||||||
@@ -66,15 +66,15 @@ class Maimai2(
|
|||||||
?.call(repos) as UserLinked<*>? ?: error("No matching field found for ${it.name}")
|
?.call(repos) as UserLinked<*>? ?: error("No matching field found for ${it.name}")
|
||||||
}
|
}
|
||||||
|
|
||||||
val listFields = exportFields.filter { it.key.type == List::class.java }
|
val listFields = exportFields.filter { it.key returns List::class }
|
||||||
val singleFields = exportFields.filter { it.key.type != List::class.java }
|
val singleFields = exportFields.filter { !(it.key returns List::class) }
|
||||||
|
|
||||||
fun export(u: AquaNetUser) = Maimai2DataExport().apply {
|
fun export(u: AquaNetUser) = Maimai2DataExport().apply {
|
||||||
gameId = "SDEZ"
|
gameId = "SDEZ"
|
||||||
userData = repos.userData.findByCard(u.ghostCard) ?: (404 - "User not found")
|
userData = repos.userData.findByCard(u.ghostCard) ?: (404 - "User not found")
|
||||||
exportFields.forEach { (f, u) ->
|
exportFields.forEach { (f, u) ->
|
||||||
f.set(this, if (f.type == List::class.java) u.findByUser(userData)
|
if (f returns List::class) f.set(this, u.findByUser(userData))
|
||||||
else u.findSingleByUser(userData).orElse(null))
|
else u.findSingleByUser(userData)()?.let { f.set(this, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,13 +84,11 @@ class Maimai2(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@API("import")
|
@API("import")
|
||||||
fun importUserData(@RP token: Str, @RB json: Str) = us.jwt.auth(token) { u ->
|
fun importUserData(@RP token: Str, @RB json: Str) = us.jwt.auth(token) { u ->
|
||||||
val export = json.parseJson<Maimai2DataExport>()
|
val export = json.parseJackson<Maimai2DataExport>()
|
||||||
if (!export.gameId.equals("SDEZ", true)) 400 - "Invalid game ID"
|
if (!export.gameId.equals("SDEZ", true)) 400 - "Invalid game ID"
|
||||||
|
|
||||||
val lists = listFields.toList().associate { (f, r) -> r to f.gets<List<Mai2UserEntity>>(export) }.vNotNull()
|
val lists = listFields.toList().associate { (f, r) -> r to f.get(export) as List<Mai2UserEntity> }.vNotNull()
|
||||||
val singles = singleFields.toList().associate { (f, r) -> r to f.gets<Mai2UserEntity>(export) }.vNotNull()
|
val singles = singleFields.toList().associate { (f, r) -> r to f.get(export) as Mai2UserEntity }.vNotNull()
|
||||||
|
|
||||||
if (export.userData == null) 400 - "Invalid user data"
|
|
||||||
|
|
||||||
// Validate new user data
|
// Validate new user data
|
||||||
// Check that all ids are 0 (this should be true since all ids are @JsonIgnore)
|
// Check that all ids are 0 (this should be true since all ids are @JsonIgnore)
|
||||||
@@ -120,8 +118,8 @@ class Maimai2(
|
|||||||
lists.values.flatten().forEach { it.user = nu }
|
lists.values.flatten().forEach { it.user = nu }
|
||||||
singles.values.forEach { it.user = nu }
|
singles.values.forEach { it.user = nu }
|
||||||
// Save new data
|
// Save new data
|
||||||
lists.forEach { (repo, list) -> (repo as UserLinked<Any>).saveAll(list) }
|
|
||||||
singles.forEach { (repo, single) -> (repo as UserLinked<Any>).save(single) }
|
singles.forEach { (repo, single) -> (repo as UserLinked<Any>).save(single) }
|
||||||
|
lists.forEach { (repo, list) -> (repo as UserLinked<Any>).saveAll(list) }
|
||||||
}
|
}
|
||||||
|
|
||||||
SUCCESS
|
SUCCESS
|
||||||
|
|||||||
Reference in New Issue
Block a user