mirror of https://github.com/hykilpikonna/AquaDX
[+] user-detail endpoint
parent
abed79441d
commit
c6ecc89ad3
|
@ -47,6 +47,9 @@ annotation class SettingField(val name: Str, val desc: Str)
|
|||
// Reflection
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Any> KClass<T>.vars() = memberProperties.mapNotNull { it as? KMutableProperty1<T, Any> }
|
||||
fun <T : Any> KClass<T>.varsMap() = vars().associateBy { it.name }
|
||||
fun <T : Any> KClass<T>.getters() = java.methods.filter { it.name.startsWith("get") }
|
||||
fun <T : Any> KClass<T>.gettersMap() = getters().associateBy { it.name.removePrefix("get").decapitalize() }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <C, T: Any> KMutableProperty1<C, T>.setCast(obj: C, value: String) = set(obj, when (returnType.classifier) {
|
||||
String::class -> value
|
||||
|
|
|
@ -17,19 +17,20 @@ class Chusan(
|
|||
override val playlogRepo: Chu3UserPlaylogRepo,
|
||||
override val userDataRepo: Chu3UserDataRepo,
|
||||
val userGeneralDataRepository: Chu3UserGeneralDataRepo,
|
||||
): GameApiController<UserData>("chu3") {
|
||||
): GameApiController<UserData>("chu3", UserData::class) {
|
||||
override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card ->
|
||||
findTrend(playlogRepo.findByUserCardExtId(card.extId)
|
||||
.map { TrendLog(it.playDate.toString(), it.playerRating) })
|
||||
}
|
||||
|
||||
|
||||
// Only show > AAA rank
|
||||
override val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 }
|
||||
override val settableFields: Map<String, (UserData, String) -> Unit> = mapOf(
|
||||
"name" to { u, v -> u.setUserName(v)
|
||||
override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to { u, v -> u.setUserName(v)
|
||||
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
|
||||
},
|
||||
)
|
||||
) }
|
||||
|
||||
override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card ->
|
||||
// Summary values: total plays, player rating, server-wide ranking
|
||||
|
|
|
@ -24,7 +24,7 @@ class Maimai2(
|
|||
override val userDataRepo: Mai2UserDataRepo,
|
||||
val userGeneralDataRepository: Mai2UserGeneralDataRepo,
|
||||
val repos: Mai2Repos
|
||||
): GameApiController<UserDetail>("mai2") {
|
||||
): GameApiController<UserDetail>("mai2", UserDetail::class) {
|
||||
override suspend fun trend(@RP username: Str): List<TrendOut> = us.cardByName(username) { card ->
|
||||
findTrend(playlogRepo.findByUserCardExtId(card.extId)
|
||||
.map { TrendLog(it.playDate, it.afterRating) })
|
||||
|
@ -32,11 +32,11 @@ class Maimai2(
|
|||
|
||||
// Only show > S rank
|
||||
override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 }
|
||||
override val settableFields: Map<String, (UserDetail, String) -> Unit> = mapOf(
|
||||
"name" to { u, v -> u.userName = v
|
||||
override val settableFields: Map<String, (UserDetail, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to { u, v -> u.userName = v
|
||||
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
|
||||
},
|
||||
)
|
||||
) }
|
||||
|
||||
override suspend fun userSummary(@RP username: Str) = us.cardByName(username) { card ->
|
||||
val extra = userGeneralDataRepository.findByUser_Card_ExtId(card.extId)
|
||||
|
|
|
@ -3,6 +3,7 @@ package icu.samnyan.aqua.net.games
|
|||
import ext.*
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.utils.*
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserData
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.springframework.data.domain.Page
|
||||
|
@ -12,6 +13,7 @@ import org.springframework.data.jpa.repository.Query
|
|||
import org.springframework.data.repository.NoRepositoryBean
|
||||
import java.util.*
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
data class TrendOut(val date: String, val rating: Int, val plays: Int)
|
||||
|
||||
|
@ -114,7 +116,7 @@ interface GenericPlaylogRepo<T: IGenericGamePlaylog> : JpaRepository<T, Long> {
|
|||
fun findByUserCardExtId(extId: Long, page: Pageable): Page<T>
|
||||
}
|
||||
|
||||
abstract class GameApiController<T : IGenericUserData>(name: String) {
|
||||
abstract class GameApiController<T : IGenericUserData>(name: String, userDataClass: KClass<T>) {
|
||||
val musicMapping = resJson<Map<String, GenericMusicMeta>>("/meta/$name/music.json")
|
||||
?.mapKeys { it.key.toInt() } ?: emptyMap()
|
||||
|
||||
|
@ -165,14 +167,24 @@ abstract class GameApiController<T : IGenericUserData>(name: String) {
|
|||
@API("playlog")
|
||||
fun playlog(@RP id: Long): IGenericGamePlaylog = playlogRepo.findById(id).getOrNull() ?: (404 - "Playlog not found")
|
||||
|
||||
@API("user-setting")
|
||||
suspend fun userSetting(@RP username: String, @RP field: String, @RP value: String): Any {
|
||||
val userDetailFields by lazy { userDataClass.gettersMap().let { vm ->
|
||||
settableFields.map { (k, _) -> k to (vm[k] ?: error("Field $k not found")) }.toMap()
|
||||
} }
|
||||
|
||||
@API("user-detail")
|
||||
suspend fun userDetail(@RP username: String) = us.cardByName(username) { card ->
|
||||
val u = userDataRepo.findByCard(card) ?: (404 - "User not found")
|
||||
userDetailFields.toList().associate { (k, f) -> k to f.invoke(u) }
|
||||
}
|
||||
|
||||
@API("user-detail-set")
|
||||
suspend fun userDetailSet(@RP token: String, @RP field: String, @RP value: String): Any {
|
||||
val prop = settableFields[field] ?: (400 - "Invalid field $field")
|
||||
|
||||
return us.cardByName(username) { card ->
|
||||
val user = userDataRepo.findByCard(card) ?: (404 - "User not found")
|
||||
return us.jwt.auth(token) { u ->
|
||||
val user = async { userDataRepo.findByCard(u.ghostCard) } ?: (404 - "User not found")
|
||||
prop(user, value)
|
||||
userDataRepo.save(user)
|
||||
async { userDataRepo.save(user) }
|
||||
SUCCESS
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,18 @@ class Ongeki(
|
|||
override val playlogRepo: UserPlaylogRepository,
|
||||
override val userDataRepo: UserDataRepository,
|
||||
val userGeneralDataRepository: UserGeneralDataRepository
|
||||
): GameApiController<UserData>("ongeki") {
|
||||
): GameApiController<UserData>("ongeki", UserData::class) {
|
||||
override suspend fun trend(username: String) = us.cardByName(username) { card ->
|
||||
findTrend(playlogRepo.findByUser_Card_ExtId(card.extId)
|
||||
.map { TrendLog(it.playDate, it.playerRating) })
|
||||
}
|
||||
|
||||
override val shownRanks = ongekiScores.filter { it.first >= 950000 }
|
||||
override val settableFields: Map<String, (UserData, String) -> Unit> = mapOf(
|
||||
"name" to { u, v -> u.setUserName(v)
|
||||
override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to { u, v -> u.setUserName(v)
|
||||
if (!v.all { it in USERNAME_CHARS }) { 400 - "Invalid character in username" }
|
||||
},
|
||||
)
|
||||
) }
|
||||
|
||||
override suspend fun userSummary(username: String) = us.cardByName(username) { card ->
|
||||
// val extra = userGeneralDataRepository.findByUser_Card_ExtId(u.ghostCard.extId)
|
||||
|
|
Loading…
Reference in New Issue