mirror of https://github.com/hykilpikonna/AquaDX
[+] Wacca user/status/login
parent
39d62099df
commit
00c5edcea7
|
@ -111,6 +111,10 @@ fun Str.asDateTime() = try { LocalDateTime.parse(this, DateTimeFormatter.ISO_LOC
|
||||||
catch (e: Exception) { try { LocalDateTime.parse(this, ALT_DATETIME_FORMAT) }
|
catch (e: Exception) { try { LocalDateTime.parse(this, ALT_DATETIME_FORMAT) }
|
||||||
catch (e: Exception) { null } }
|
catch (e: Exception) { null } }
|
||||||
|
|
||||||
|
val Calendar.year get() = get(Calendar.YEAR)
|
||||||
|
val Calendar.month get() = get(Calendar.MONTH) + 1
|
||||||
|
val Calendar.day get() = get(Calendar.DAY_OF_MONTH)
|
||||||
|
|
||||||
// Encodings
|
// Encodings
|
||||||
fun Long.toHex(len: Int = 16): Str = "0x${this.toString(len).padStart(len, '0').uppercase()}"
|
fun Long.toHex(len: Int = 16): Str = "0x${this.toString(len).padStart(len, '0').uppercase()}"
|
||||||
fun Map<String, Any>.toUrl() = entries.joinToString("&") { (k, v) -> "$k=$v" }
|
fun Map<String, Any>.toUrl() = entries.joinToString("&") { (k, v) -> "$k=$v" }
|
||||||
|
|
|
@ -41,6 +41,17 @@ inline fun <reified T> Str.parseJackson() = if (contains("null")) {
|
||||||
else JACKSON.readValue(this, T::class.java)
|
else JACKSON.readValue(this, T::class.java)
|
||||||
fun <T> T.toJson() = JACKSON.writeValueAsString(this)
|
fun <T> T.toJson() = JACKSON.writeValueAsString(this)
|
||||||
|
|
||||||
|
inline fun <reified T> String.json() = try {
|
||||||
|
JACKSON.readValue(this, T::class.java)
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
println("Failed to parse JSON: $this")
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.jsonMap(): Map<String, Any?> = json()
|
||||||
|
fun String.jsonArray(): List<Map<String, Any?>> = json()
|
||||||
|
|
||||||
|
|
||||||
// KotlinX Serialization
|
// KotlinX Serialization
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
|
|
@ -12,24 +12,25 @@ import io.ktor.client.utils.*
|
||||||
import jakarta.servlet.http.HttpServletRequest
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
val empty = emptyList<Any>()
|
val empty = emptyList<Any>()
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@API("/g/wacca/")
|
@API("/g/wacca/")
|
||||||
class WaccaServer(val rp: WaccaRepos, val cardRepo: CardRepository) {
|
class WaccaServer(val rp: WaccaRepos, val cardRepo: CardRepository) {
|
||||||
val handlerMap = mutableMapOf<String, (BaseRequest, List<Any>) -> List<Any>>()
|
val handlerMap = mutableMapOf<String, (BaseRequest, List<Any>) -> Any>()
|
||||||
val cacheMap = mutableMapOf<String, String>()
|
val cacheMap = mutableMapOf<String, String>()
|
||||||
|
|
||||||
val log = logger()
|
val log = logger()
|
||||||
|
|
||||||
init { api() }
|
init { init() }
|
||||||
|
|
||||||
// DSL Functions
|
// DSL Functions
|
||||||
fun options(u: WaccaUser?) = u?.let { rp.option.findByUser(u).associate { it.optId to it.value } } ?: emptyMap()
|
fun options(u: WaccaUser?) = u?.let { rp.option.findByUser(u).associate { it.optId to it.value } } ?: emptyMap()
|
||||||
operator fun Map<Int, Int>.get(type: WaccaOptionType) = getOrDefault(type.id, type.default)
|
operator fun Map<Int, Int>.get(type: WaccaOptionType) = getOrDefault(type.id, type.default)
|
||||||
operator fun String.minus(value: Any) = value
|
operator fun String.minus(value: Any) = value
|
||||||
operator fun String.invoke(block: (BaseRequest, List<Any>) -> List<Any>) { handlerMap[this.lowercase()] = block }
|
operator fun String.invoke(block: (BaseRequest, List<Any>) -> Any) { handlerMap[this.lowercase()] = block }
|
||||||
infix fun String.cached(block: () -> Any) { cacheMap[this.lowercase()] = block().toJson() }
|
infix fun String.cached(block: () -> Any) { cacheMap[this.lowercase()] = block().toJson() }
|
||||||
|
|
||||||
/** Convert "3.07.01.JPN.26935.S" into "3.7.1" */
|
/** Convert "3.07.01.JPN.26935.S" into "3.7.1" */
|
||||||
|
@ -54,13 +55,18 @@ class WaccaServer(val rp: WaccaRepos, val cardRepo: CardRepository) {
|
||||||
if (path in cacheMap) return resp(cacheMap[path]!!)
|
if (path in cacheMap) return resp(cacheMap[path]!!)
|
||||||
if (path !in handlerMap) return resp("[]", 1, "Not Found")
|
if (path !in handlerMap) return resp("[]", 1, "Not Found")
|
||||||
|
|
||||||
|
log.info("Wacca $path < $body")
|
||||||
|
|
||||||
val br = JACKSON.parse<BaseRequest>(body)
|
val br = JACKSON.parse<BaseRequest>(body)
|
||||||
val resp = handlerMap[path]!!(br, br.params)
|
return handlerMap[path]!!(br, br.params).let { when (it) {
|
||||||
return resp(resp.toJson())
|
is String -> return resp(it)
|
||||||
|
is List<*> -> return resp(it.toJson())
|
||||||
|
else -> Error("Invalid response type ${it.javaClass}")
|
||||||
|
} }.let { log.info("Wacca $path > $it") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun WaccaServer.api() {
|
fun WaccaServer.init() {
|
||||||
"housing/get" cached { ls("housingId" - 39, "isNewCab" - 0) }
|
"housing/get" cached { ls("housingId" - 39, "isNewCab" - 0) }
|
||||||
"housing/start" cached { ls("regionId" - 1, "recommendSongList" - ls(1269, 1007, 1270, 1002, 1020, 1003, 1008,
|
"housing/start" cached { ls("regionId" - 1, "recommendSongList" - ls(1269, 1007, 1270, 1002, 1020, 1003, 1008,
|
||||||
1211, 1018, 1092, 1056, 32, 1260, 1230, 1258, 1251, 2212, 1264, 1125, 1037, 2001, 1272, 1126, 1119, 1104, 1070,
|
1211, 1018, 1092, 1056, 32, 1260, 1230, 1258, 1251, 2212, 1264, 1125, 1037, 2001, 1272, 1126, 1119, 1104, 1070,
|
||||||
|
@ -90,7 +96,7 @@ fun WaccaServer.api() {
|
||||||
|
|
||||||
"user/status/create" { _, (uid, name) ->
|
"user/status/create" { _, (uid, name) ->
|
||||||
val u = rp.user.save(WaccaUser().apply {
|
val u = rp.user.save(WaccaUser().apply {
|
||||||
card = cardRepo.findByExtId(uid.long())() ?: (400 - "Card not found")
|
card = cardRepo.findByExtId(uid.long())() ?: (404 - "Card not found")
|
||||||
username = name.toString()
|
username = name.toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -107,4 +113,22 @@ fun WaccaServer.api() {
|
||||||
|
|
||||||
ls(u.lStatus())
|
ls(u.lStatus())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"user/status/login" api@ { _, (uid) ->
|
||||||
|
if (uid == 0) return@api "[[], [], [], 0, [2077, 1, 1, 1, [], []], 0, []]"
|
||||||
|
val u = rp.user.findByCardExtId(uid.long()) ?: (404 - "User not found")
|
||||||
|
|
||||||
|
// Record login
|
||||||
|
u.loginCountConsec = u.loginCount++
|
||||||
|
if (millis() - u.lastLoginDate.time > 86400000) { // Is new day
|
||||||
|
u.loginCountDays++
|
||||||
|
u.loginCountToday = 0
|
||||||
|
if (millis() - u.lastLoginDate.time < 172800000) u.loginCountDaysConsec++
|
||||||
|
}
|
||||||
|
u.loginCountToday++
|
||||||
|
u.lastLoginDate = Date()
|
||||||
|
|
||||||
|
"[[], [], [], 0, [2077, 1, 1, 1, [], []], ${u.lastLoginDate.time / 1000}, []]"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -51,7 +51,8 @@ class WaccaUser : BaseEntity() {
|
||||||
var lastFolderOrder = 0
|
var lastFolderOrder = 0
|
||||||
var lastFolderId = 0
|
var lastFolderId = 0
|
||||||
var lastSongOrder = 0
|
var lastSongOrder = 0
|
||||||
var lastLoginDate: String? = null
|
@Temporal(TemporalType.TIME)
|
||||||
|
var lastLoginDate: Date = Date(0)
|
||||||
var gateTutorialFlags: String? = null
|
var gateTutorialFlags: String? = null
|
||||||
|
|
||||||
fun lStatus() = ls(card.extId, username, 1, xp, danLevel, danType, wp, ls(0, 0, 0), loginCount, loginCountDays,
|
fun lStatus() = ls(card.extId, username, 1, xp, danLevel, danType, wp, ls(0, 0, 0), loginCount, loginCountDays,
|
||||||
|
|
|
@ -12,17 +12,6 @@ const val FTK = "test"
|
||||||
const val HOST = "http://localhost"
|
const val HOST = "http://localhost"
|
||||||
val ACCESS_CODE = "9900" + (1..16).map { Random.nextInt(0..9) }.joinToString("")
|
val ACCESS_CODE = "9900" + (1..16).map { Random.nextInt(0..9) }.joinToString("")
|
||||||
|
|
||||||
inline fun <reified T> String.json() = try {
|
|
||||||
JACKSON.readValue(this, T::class.java)
|
|
||||||
}
|
|
||||||
catch (e: Exception) {
|
|
||||||
println("Failed to parse JSON: $this")
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.jsonMap(): Map<String, Any?> = json()
|
|
||||||
fun String.jsonArray(): List<Map<String, Any?>> = json()
|
|
||||||
|
|
||||||
suspend fun registerUser(): Long {
|
suspend fun registerUser(): Long {
|
||||||
val resp = HTTP.post(HOST.ensureEndingSlash() + "api/v2/frontier/register-card") {
|
val resp = HTTP.post(HOST.ensureEndingSlash() + "api/v2/frontier/register-card") {
|
||||||
parameter("ftk", FTK)
|
parameter("ftk", FTK)
|
||||||
|
|
|
@ -28,31 +28,45 @@ class WaccaTest : StringSpec({
|
||||||
return PostResp(resp, res["params"] as List<Any>)
|
return PostResp(resp, res["params"] as List<Any>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infix fun List<Any?>.exp(expected: List<Any?>) {
|
||||||
|
expected.size shouldBe size
|
||||||
|
for (i in indices) {
|
||||||
|
val a = this[i]
|
||||||
|
when (val b = expected[i]) {
|
||||||
|
null -> {} // Use null to ignore the value
|
||||||
|
is List<*> -> a as List<Any> exp b as List<Any>
|
||||||
|
else -> a shouldBe b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun List<Any?>.exp(json: String) = exp(json.jsonArray())
|
||||||
|
|
||||||
beforeTest {
|
beforeTest {
|
||||||
if (uid == 0L) uid = registerUser()
|
if (uid == 0L) uid = registerUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
"housing/get #1" {
|
"housing/get #1" {
|
||||||
post("housing/get", "[]").res shouldBe "[39, 0]".jsonArray()
|
post("housing/get", "[]").res exp "[39, 0]"
|
||||||
}
|
}
|
||||||
|
|
||||||
"housing/start #1" {
|
"housing/start #1" {
|
||||||
post("housing/start", """["", "2024/03/24 10:39:36, ApiUserStatusLogout,0\\n2024/03/24 10:51:06, ApiUserStatusLogout,0\\n2024/03/24 10:54:19, ApiUserStatusLogout,0\\n2024/03/24 10:59:33, ApiAdvertiseGetNews,0\\n2024/03/24 11:10:31, ApiAdvertiseGetNews,0\\n2024/03/24 11:11:04, ApiUserStatusLogout,0\\n2024/03/24 11:19:51, ,0\\n2024/03/24 11:20:14, ApiAdvertiseGetNews,0\\n", "", [[1, "SERVER"], [2, "JPN"]]]""").res shouldBe
|
post("housing/start", """["", "2024/03/24 10:39:36, ApiUserStatusLogout,0\\n2024/03/24 10:51:06, ApiUserStatusLogout,0\\n2024/03/24 10:54:19, ApiUserStatusLogout,0\\n2024/03/24 10:59:33, ApiAdvertiseGetNews,0\\n2024/03/24 11:10:31, ApiAdvertiseGetNews,0\\n2024/03/24 11:11:04, ApiUserStatusLogout,0\\n2024/03/24 11:19:51, ,0\\n2024/03/24 11:20:14, ApiAdvertiseGetNews,0\\n", "", [[1, "SERVER"], [2, "JPN"]]]""").res exp
|
||||||
"[1, [1269, 1007, 1270, 1002, 1020, 1003, 1008, 1211, 1018, 1092, 1056, 32, 1260, 1230, 1258, 1251, 2212, 1264, 1125, 1037, 2001, 1272, 1126, 1119, 1104, 1070, 1047, 1044, 1027, 1004, 1001, 24, 2068, 2062, 2021, 1275, 1249, 1207, 1203, 1107, 1021, 1009, 9, 4, 3, 23, 22, 2014, 13, 1276, 1247, 1240, 1237, 1128, 1114, 1110, 1109, 1102, 1045, 1043, 1036, 1035, 1030, 1023, 1015]]".jsonArray()
|
"[1, [1269, 1007, 1270, 1002, 1020, 1003, 1008, 1211, 1018, 1092, 1056, 32, 1260, 1230, 1258, 1251, 2212, 1264, 1125, 1037, 2001, 1272, 1126, 1119, 1104, 1070, 1047, 1044, 1027, 1004, 1001, 24, 2068, 2062, 2021, 1275, 1249, 1207, 1203, 1107, 1021, 1009, 9, 4, 3, 23, 22, 2014, 13, 1276, 1247, 1240, 1237, 1128, 1114, 1110, 1109, 1102, 1045, 1043, 1036, 1035, 1030, 1023, 1015]]"
|
||||||
}
|
}
|
||||||
|
|
||||||
"advertise/GetNews #1" {
|
"advertise/GetNews #1" {
|
||||||
post("advertise/GetNews", "[]").res shouldBe
|
post("advertise/GetNews", "[]").res exp
|
||||||
"[[], [], [], [], [], [], [], [], []]".jsonArray()
|
"[[], [], [], [], [], [], [], [], []]"
|
||||||
}
|
}
|
||||||
|
|
||||||
"user/status/get #1" {
|
"user/status/get #1" {
|
||||||
post("user/status/get", """["$uid"]""").res shouldBe
|
post("user/status/get", """["$uid"]""").res exp
|
||||||
"""[[0, "", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0], 104001, 102001, 1, [2, "1.0.0"], []]""".jsonArray()
|
"""[[0, "", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0], 104001, 102001, 1, [2, "1.0.0"], []]"""
|
||||||
}
|
}
|
||||||
|
|
||||||
"user/status/create #1" {
|
"user/status/create #1" {
|
||||||
post("user/status/create", """["$uid", "AZA"]""").res shouldBe
|
post("user/status/create", """["$uid", "AZA"]""").res exp
|
||||||
"""[[$uid, "AZA", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0]]""".jsonArray()
|
"""[[$uid, "AZA", 1, 0, 0, 0, 0, [0, 0, 0], 0, 0, 0, 0, 0, 0, 0]]"""
|
||||||
}
|
}
|
||||||
})
|
})
|
Loading…
Reference in New Issue