mirror of https://github.com/hykilpikonna/AquaDX
[F] Fix artemis conversion
parent
5fec57e8e3
commit
e4330fee92
|
@ -1,5 +1,6 @@
|
||||||
package ext
|
package ext
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
|
@ -85,37 +86,42 @@ fun Str.isValidEmail(): Bool = emailRegex.matches(this)
|
||||||
// JSON
|
// JSON
|
||||||
val ACCEPTABLE_FALSE = setOf("0", "false", "no", "off", "False", "None", "null")
|
val ACCEPTABLE_FALSE = setOf("0", "false", "no", "off", "False", "None", "null")
|
||||||
val ACCEPTABLE_TRUE = setOf("1", "true", "yes", "on", "True")
|
val ACCEPTABLE_TRUE = setOf("1", "true", "yes", "on", "True")
|
||||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
|
val JSON_FUZZY_BOOLEAN = SimpleModule().addDeserializer(Boolean::class.java, object : JsonDeserializer<Boolean>() {
|
||||||
val JACKSON = ObjectMapper().apply {
|
|
||||||
findAndRegisterModules()
|
|
||||||
registerModule(SimpleModule().addDeserializer(Boolean::class.java, object : JsonDeserializer<Boolean>() {
|
|
||||||
override fun deserialize(parser: JsonParser, context: DeserializationContext) = when(parser.text) {
|
override fun deserialize(parser: JsonParser, context: DeserializationContext) = when(parser.text) {
|
||||||
in ACCEPTABLE_FALSE -> false
|
in ACCEPTABLE_FALSE -> false
|
||||||
in ACCEPTABLE_TRUE -> true
|
in ACCEPTABLE_TRUE -> true
|
||||||
else -> 400 - "Invalid boolean value ${parser.text}"
|
else -> 400 - "Invalid boolean value ${parser.text}"
|
||||||
}
|
}
|
||||||
}).addDeserializer(List::class.java, object : JsonDeserializer<List<Integer>>() {
|
})
|
||||||
override fun deserialize(parser: JsonParser, context: DeserializationContext) =
|
val JSON_DATETIME = SimpleModule().addDeserializer(LocalDateTime::class.java, object : JsonDeserializer<LocalDateTime>() {
|
||||||
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" }
|
|
||||||
}).addDeserializer(LocalDateTime::class.java, object : JsonDeserializer<LocalDateTime>() {
|
|
||||||
override fun deserialize(parser: JsonParser, context: DeserializationContext) =
|
override fun deserialize(parser: JsonParser, context: DeserializationContext) =
|
||||||
parser.text.asDateTime() ?: (400 - "Invalid date time value ${parser.text}")
|
parser.text.asDateTime() ?: (400 - "Invalid date time value ${parser.text}")
|
||||||
}))
|
})
|
||||||
|
val JACKSON = ObjectMapper().apply {
|
||||||
|
setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL)
|
||||||
|
findAndRegisterModules()
|
||||||
|
registerModule(JSON_FUZZY_BOOLEAN)
|
||||||
|
registerModule(JSON_DATETIME)
|
||||||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||||
}
|
}
|
||||||
inline fun <reified T> Str.parseJson() = JACKSON.readValue(this, T::class.java)
|
inline fun <reified T> ObjectMapper.readValue(str: Str) = readValue(str, T::class.java)
|
||||||
|
// TODO: https://stackoverflow.com/q/78197784/7346633
|
||||||
|
inline fun <reified T> Str.parseJackson() = if (contains("null")) {
|
||||||
|
val map = JACKSON.readValue<MutableMap<String, Any>>(this)
|
||||||
|
JACKSON.convertValue(map.recursiveNotNull(), T::class.java)
|
||||||
|
}
|
||||||
|
else JACKSON.readValue(this, T::class.java)
|
||||||
fun <T> T.toJson() = JACKSON.writeValueAsString(this)
|
fun <T> T.toJson() = JACKSON.writeValueAsString(this)
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
val JSON = Json {
|
val JSON = Json {
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
isLenient = true
|
isLenient = true
|
||||||
namingStrategy = JsonNamingStrategy.SnakeCase
|
namingStrategy = JsonNamingStrategy.SnakeCase
|
||||||
|
explicitNulls = false
|
||||||
|
coerceInputValues = true
|
||||||
}
|
}
|
||||||
|
inline fun <reified T> Json.parse(str: Str) = decodeFromString<T>(str)
|
||||||
// Global Tools
|
// Global Tools
|
||||||
val HTTP = HttpClient(CIO) {
|
val HTTP = HttpClient(CIO) {
|
||||||
install(ContentNegotiation) {
|
install(ContentNegotiation) {
|
||||||
|
@ -160,6 +166,10 @@ fun <K, V: Any> Map<K, V?>.vNotNull(): Map<K, V> = filterValues { it != null }.m
|
||||||
fun <T> MutableList<T>.popAll(list: List<T>) = list.also { removeAll(it) }
|
fun <T> MutableList<T>.popAll(list: List<T>) = list.also { removeAll(it) }
|
||||||
fun <T> MutableList<T>.popAll(vararg items: T) = popAll(items.toList())
|
fun <T> MutableList<T>.popAll(vararg items: T) = popAll(items.toList())
|
||||||
inline fun <T> Iterable<T>.mapApply(block: T.() -> Unit) = map { it.apply(block) }
|
inline fun <T> Iterable<T>.mapApply(block: T.() -> Unit) = map { it.apply(block) }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <K, V: Any> Map<K, V?>.recursiveNotNull(): Map<K, V> = mapNotNull { (k, v) ->
|
||||||
|
k to if (v is Map<*, *>) (v as Map<Any?, Any?>).recursiveNotNull() else v
|
||||||
|
}.toMap() as Map<K, V>
|
||||||
|
|
||||||
// Optionals
|
// Optionals
|
||||||
operator fun <T> Optional<T>.invoke(): T? = orElse(null)
|
operator fun <T> Optional<T>.invoke(): T? = orElse(null)
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package icu.samnyan.aqua.api.model.resp.sega.chuni.v2.external;
|
|
||||||
|
|
||||||
import icu.samnyan.aqua.sega.chusan.model.userdata.*;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is use for exporting chusan profile
|
|
||||||
* @author samnyan (publicamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class Chu3DataExport {
|
|
||||||
public String gameId = "SDHD";
|
|
||||||
public UserData userData;
|
|
||||||
public UserGameOption userGameOption;
|
|
||||||
public List<UserActivity> userActivityList;
|
|
||||||
public List<UserCharacter> userCharacterList;
|
|
||||||
public List<UserCharge> userChargeList;
|
|
||||||
public List<UserCourse> userCourseList;
|
|
||||||
public List<UserDuel> userDuelList;
|
|
||||||
public List<UserItem> userItemList;
|
|
||||||
public List<UserMapArea> userMapList;
|
|
||||||
public List<UserMusicDetail> userMusicDetailList;
|
|
||||||
public List<UserPlaylog> userPlaylogList;
|
|
||||||
public List<UserLoginBonus> userLoginBonusList;
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package icu.samnyan.aqua.api.model.resp.sega.chuni.v2.external
|
||||||
|
|
||||||
|
import icu.samnyan.aqua.sega.chusan.model.userdata.*
|
||||||
|
|
||||||
|
data class Chu3DataExport(
|
||||||
|
var gameId: String = "SDHD",
|
||||||
|
var userData: UserData,
|
||||||
|
var userGameOption: UserGameOption,
|
||||||
|
var userActivityList: List<UserActivity>,
|
||||||
|
var userCharacterList: List<UserCharacter>,
|
||||||
|
var userChargeList: List<UserCharge>,
|
||||||
|
var userCourseList: List<UserCourse>,
|
||||||
|
var userDuelList: List<UserDuel>,
|
||||||
|
var userItemList: List<UserItem>,
|
||||||
|
var userMapList: List<UserMapArea>,
|
||||||
|
var userMusicDetailList: List<UserMusicDetail>,
|
||||||
|
var userPlaylogList: List<UserPlaylog>,
|
||||||
|
var userLoginBonusList: List<UserLoginBonus>,
|
||||||
|
) {
|
||||||
|
constructor() : this("SDHD", UserData(), UserGameOption(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList())
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,11 @@ import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||||
import ext.API
|
import ext.*
|
||||||
import ext.JACKSON
|
|
||||||
import ext.minus
|
|
||||||
import ext.splitLines
|
|
||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KMutableProperty1
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
// Import class with renaming
|
// Import class with renaming
|
||||||
data class ImportClass<T : Any>(
|
data class ImportClass<T : Any>(
|
||||||
|
@ -19,7 +18,7 @@ data class ImportClass<T : Any>(
|
||||||
)
|
)
|
||||||
|
|
||||||
abstract class ImportController<T: Any>(
|
abstract class ImportController<T: Any>(
|
||||||
val exportFields: Map<String, Field>,
|
val exportFields: Map<String, KMutableProperty1<T, Any>>,
|
||||||
val renameTable: Map<String, ImportClass<*>>
|
val renameTable: Map<String, ImportClass<*>>
|
||||||
) {
|
) {
|
||||||
abstract fun createEmpty(): T
|
abstract fun createEmpty(): T
|
||||||
|
@ -35,14 +34,14 @@ abstract class ImportController<T: Any>(
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@API("convert-artemis")
|
@API("convert-artemis")
|
||||||
fun importArtemisSql(sql: String): ImportResult {
|
fun importArtemisSql(@RB sql: String): ImportResult {
|
||||||
val data = createEmpty()
|
val data = createEmpty()
|
||||||
val errors = ArrayList<String>()
|
val errors = ArrayList<String>()
|
||||||
val warnings = ArrayList<String>()
|
val warnings = ArrayList<String>()
|
||||||
fun err(msg: String) { errors.add(msg) }
|
fun err(msg: String) { errors.add(msg) }
|
||||||
fun warn(msg: String) { warnings.add(msg) }
|
fun warn(msg: String) { warnings.add(msg) }
|
||||||
|
|
||||||
val lists = exportFields.filter { it.value.type == List::class.java }
|
val lists = exportFields.filter { it.value returns List::class }
|
||||||
.mapValues { it.value.get(data) as ArrayList<Any> }
|
.mapValues { it.value.get(data) as ArrayList<Any> }
|
||||||
|
|
||||||
val statements = sql.splitLines().mapNotNull {
|
val statements = sql.splitLines().mapNotNull {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package icu.samnyan.aqua.net.games.chu3
|
package icu.samnyan.aqua.net.games.chu3
|
||||||
|
|
||||||
import ext.API
|
import ext.API
|
||||||
|
import ext.vars
|
||||||
import icu.samnyan.aqua.api.model.resp.sega.chuni.v2.external.Chu3DataExport
|
import icu.samnyan.aqua.api.model.resp.sega.chuni.v2.external.Chu3DataExport
|
||||||
import icu.samnyan.aqua.net.games.ImportClass
|
import icu.samnyan.aqua.net.games.ImportClass
|
||||||
import icu.samnyan.aqua.net.games.ImportController
|
import icu.samnyan.aqua.net.games.ImportController
|
||||||
|
@ -10,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController
|
||||||
@RestController
|
@RestController
|
||||||
@API("api/v2/game/chu3")
|
@API("api/v2/game/chu3")
|
||||||
class Chu3Import : ImportController<Chu3DataExport>(
|
class Chu3Import : ImportController<Chu3DataExport>(
|
||||||
exportFields = Chu3DataExport::class.java.declaredFields.associateBy {
|
exportFields = Chu3DataExport::class.vars().associateBy {
|
||||||
var name = it.name
|
var name = it.name
|
||||||
if (name == "userMapList") name = "userMapAreaList"
|
if (name == "userMapList") name = "userMapAreaList"
|
||||||
name.replace("List", "").lowercase()
|
name.replace("List", "").lowercase()
|
||||||
|
@ -33,6 +34,5 @@ class Chu3Import : ImportController<Chu3DataExport>(
|
||||||
// "chuni_profile_recent_rating" to ImportClass(UserRecentRating::class),
|
// "chuni_profile_recent_rating" to ImportClass(UserRecentRating::class),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun createEmpty() = Chu3DataExport("SDEZ", UserData(), UserGameOption(), ArrayList(), ArrayList(),
|
override fun createEmpty() = Chu3DataExport()
|
||||||
ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList(), ArrayList())
|
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package icu.samnyan.aqua.net.games.mai2
|
package icu.samnyan.aqua.net.games.mai2
|
||||||
|
|
||||||
import ext.API
|
import ext.API
|
||||||
|
import ext.vars
|
||||||
import icu.samnyan.aqua.api.model.resp.sega.maimai2.external.Maimai2DataExport
|
import icu.samnyan.aqua.api.model.resp.sega.maimai2.external.Maimai2DataExport
|
||||||
import icu.samnyan.aqua.net.games.ImportClass
|
import icu.samnyan.aqua.net.games.ImportClass
|
||||||
import icu.samnyan.aqua.net.games.ImportController
|
import icu.samnyan.aqua.net.games.ImportController
|
||||||
|
@ -10,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController
|
||||||
@RestController
|
@RestController
|
||||||
@API("api/v2/game/mai2")
|
@API("api/v2/game/mai2")
|
||||||
class Mai2Import : ImportController<Maimai2DataExport>(
|
class Mai2Import : ImportController<Maimai2DataExport>(
|
||||||
exportFields = Maimai2DataExport::class.java.declaredFields.associateBy {
|
exportFields = Maimai2DataExport::class.vars().associateBy {
|
||||||
it.name.replace("List", "").lowercase()
|
it.name.replace("List", "").lowercase()
|
||||||
},
|
},
|
||||||
renameTable = mapOf(
|
renameTable = mapOf(
|
||||||
|
|
Loading…
Reference in New Issue