mirror of
https://github.com/MewoLab/AquaDX.git
synced 2025-12-14 11:56:15 +08:00
Compare commits
54 Commits
b0a49d6626
...
drop-the-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6175b372e | ||
|
|
b5e27e859b | ||
|
|
458367668e | ||
|
|
20b6af11cc | ||
|
|
7fd71e389d | ||
|
|
1827c8db55 | ||
|
|
4cdf324f85 | ||
|
|
8e5827eeaf | ||
|
|
3a54798d5f | ||
|
|
55869f9d07 | ||
|
|
8fc2a74f95 | ||
|
|
7e90aec55d | ||
|
|
e90123389c | ||
|
|
b7cb3cb6ea | ||
|
|
619caec2ff | ||
|
|
c7a5458f11 | ||
|
|
419e22cc49 | ||
|
|
8d48ab0d3f | ||
|
|
32c3226db7 | ||
|
|
acf76bd270 | ||
|
|
664365b09b | ||
|
|
38b8831efd | ||
|
|
6767b62fd5 | ||
|
|
458146ae0c | ||
|
|
b2aef08c01 | ||
|
|
e7b96d4b24 | ||
|
|
b87ff18c69 | ||
|
|
f3cf6735e4 | ||
|
|
ccd6367875 | ||
|
|
01d4262fff | ||
|
|
00d74e6b0b | ||
|
|
a61f6022f9 | ||
|
|
69f4f75347 | ||
|
|
45e14e21f1 | ||
|
|
7553c6a863 | ||
|
|
7cd750b11c | ||
|
|
9fe945007c | ||
|
|
567ed059ad | ||
|
|
6d99beafe9 | ||
|
|
1ca1e3edc3 | ||
|
|
c4182fb725 | ||
|
|
32d050cb2f | ||
|
|
34aae0c87a | ||
|
|
69bd35a579 | ||
|
|
3e6c0b4159 | ||
|
|
a33ec8b11c | ||
|
|
dd03ca38a1 | ||
|
|
1cac5e451a | ||
|
|
010d4592e4 | ||
|
|
b0d0f8ef7d | ||
|
|
967d311ee4 | ||
|
|
d5b777d720 | ||
|
|
2ab2666ad0 | ||
|
|
4971f2be78 |
@@ -1,25 +0,0 @@
|
||||
image: gradle:alpine
|
||||
|
||||
before_script:
|
||||
- GRADLE_USER_HOME="$(pwd)/.gradle"
|
||||
- export GRADLE_USER_HOME
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script: gradle --build-cache assemble
|
||||
cache:
|
||||
key: "$CI_COMMIT_REF_NAME"
|
||||
policy: push
|
||||
paths:
|
||||
- build
|
||||
- .gradle
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script: gradle check
|
||||
cache:
|
||||
key: "$CI_COMMIT_REF_NAME"
|
||||
policy: pull
|
||||
paths:
|
||||
- build
|
||||
- .gradle
|
||||
@@ -107,7 +107,8 @@ export interface GenericGameSummary {
|
||||
lastVersion: string
|
||||
ratingComposition: { [key: string]: any }
|
||||
recent: GenericGamePlaylog[]
|
||||
rival?: boolean
|
||||
rival?: boolean,
|
||||
favorites?: number[]
|
||||
}
|
||||
|
||||
export interface MusicMeta {
|
||||
|
||||
@@ -28,6 +28,7 @@ export const EN_REF_USER = {
|
||||
'UserHome.RemoveRival': "Remove from Rival",
|
||||
'UserHome.InvalidGame': "Game ${game} is not supported on the web UI yet. We only support maimai, chunithm, wacca, and ongeki for now.",
|
||||
'UserHome.ShowMoreRecent': 'Show more',
|
||||
'UserHome.FavoriteSongs': 'Favorite Songs'
|
||||
}
|
||||
|
||||
export const EN_REF_Welcome = {
|
||||
|
||||
@@ -40,6 +40,7 @@ const zhUser: typeof EN_REF_USER = {
|
||||
'UserHome.RemoveRival': "移除劲敌",
|
||||
'UserHome.InvalidGame': "游戏 ${game} 还不支持网页端查看。我们目前只支持舞萌、中二、华卡和音击。",
|
||||
'UserHome.ShowMoreRecent': "显示更多",
|
||||
'UserHome.FavoriteSongs': "收藏歌曲"
|
||||
}
|
||||
|
||||
const zhWelcome: typeof EN_REF_Welcome = {
|
||||
|
||||
@@ -80,11 +80,12 @@
|
||||
// Don't know why this isn't just a part of the cropper module. Have to do this myself.. What a shame
|
||||
let canvas = document.createElement("canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
canvas.width = 256;
|
||||
canvas.height = 256;
|
||||
const size = Math.round(Math.min(pfpCrop.width, pfpCrop.height, 1024));
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
let img = document.createElement("img");
|
||||
img.onload = () => {
|
||||
ctx?.drawImage(img, pfpCrop.x, pfpCrop.y, pfpCrop.width, pfpCrop.height, 0, 0, 256, 256);
|
||||
ctx?.drawImage(img, pfpCrop.x, pfpCrop.y, pfpCrop.width, pfpCrop.height, 0, 0, size, size);
|
||||
canvas.toBlob(blob => {
|
||||
if (!blob) return;
|
||||
submitting = 'profilePicture'
|
||||
@@ -282,7 +283,7 @@
|
||||
object-fit: cover
|
||||
aspect-ratio: 1
|
||||
|
||||
|
||||
|
||||
|
||||
.cropper-container
|
||||
position: relative
|
||||
|
||||
@@ -325,7 +325,6 @@
|
||||
<RatingComposition title="Recent 10" comp={d.user.ratingComposition.recent10} {allMusics} game={game != "auto" ? game : "mai2"} top={10}/>
|
||||
{/if}
|
||||
|
||||
|
||||
<div class="recent">
|
||||
<h2>{t('UserHome.RecentScores')}</h2>
|
||||
<div class="scores">
|
||||
@@ -368,6 +367,22 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if d.user.favorites != null && d.user.favorites.length > 0}
|
||||
<div class="favorites">
|
||||
<h2>{t('UserHome.FavoriteSongs')}</h2>
|
||||
<div class="scores">
|
||||
{#each d.user.favorites as favoriteSongId, i}
|
||||
<div>
|
||||
<img src={`${DATA_HOST}/d/${game}/music/00${favoriteSongId.toString().padStart(6, '0').substring(2)}.png`} alt="" on:error={coverNotFound} />
|
||||
<div class="info">
|
||||
<div class="song-title">{allMusics[favoriteSongId.toString()] ? allMusics[favoriteSongId.toString()].name : t("UserHome.UnknownSong")}</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<StatusOverlays {error} loading={!d || isLoading} />
|
||||
@@ -554,6 +569,57 @@
|
||||
flex-direction: row
|
||||
justify-content: space-between
|
||||
|
||||
.favorites
|
||||
.scores
|
||||
display: grid
|
||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr))
|
||||
gap: 20px
|
||||
|
||||
// Image and song info
|
||||
> div
|
||||
display: flex
|
||||
align-items: center
|
||||
gap: 20px
|
||||
|
||||
background-color: rgba(white, 0.03)
|
||||
border-radius: vars.$border-radius
|
||||
|
||||
img
|
||||
width: 50px
|
||||
height: 50px
|
||||
border-radius: vars.$border-radius
|
||||
object-fit: cover
|
||||
|
||||
// Song info and score
|
||||
> div.info
|
||||
flex: 1
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
overflow: hidden
|
||||
flex-direction: column
|
||||
|
||||
.first-line
|
||||
display: flex
|
||||
flex-direction: row
|
||||
|
||||
// Limit song name to one line
|
||||
.song-title
|
||||
max-width: 90%
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
white-space: nowrap
|
||||
|
||||
// Make song score and rank not wrap
|
||||
> div:last-child
|
||||
white-space: nowrap
|
||||
|
||||
@media (max-width: vars.$w-mobile)
|
||||
flex-direction: column
|
||||
gap: 0
|
||||
|
||||
.rank-text
|
||||
text-align: left
|
||||
|
||||
// Recent Scores section
|
||||
.recent
|
||||
.scores
|
||||
|
||||
@@ -7,14 +7,12 @@ plugins {
|
||||
val ktVer = "2.1.10"
|
||||
|
||||
java
|
||||
kotlin("plugin.lombok") version ktVer
|
||||
kotlin("jvm") version ktVer
|
||||
kotlin("plugin.spring") version ktVer
|
||||
kotlin("plugin.jpa") version ktVer
|
||||
kotlin("plugin.serialization") version ktVer
|
||||
kotlin("plugin.allopen") version ktVer
|
||||
kotlin("kapt") version ktVer
|
||||
id("io.freefair.lombok") version "8.6"
|
||||
id("org.springframework.boot") version "3.2.3"
|
||||
id("com.github.ben-manes.versions") version "0.51.0"
|
||||
id("org.hibernate.orm") version "6.4.4.Final"
|
||||
|
||||
@@ -40,6 +40,7 @@ import kotlin.reflect.jvm.jvmErasure
|
||||
|
||||
typealias RP = RequestParam
|
||||
typealias RB = RequestBody
|
||||
typealias RT = RequestPart
|
||||
typealias RH = RequestHeader
|
||||
typealias PV = PathVariable
|
||||
typealias API = RequestMapping
|
||||
@@ -211,6 +212,8 @@ val <K, V> Map<K, V>.mut get() = toMutableMap()
|
||||
val <T> Set<T>.mut get() = toMutableSet()
|
||||
|
||||
fun <T> List<T>.unique(fn: (T) -> Any) = distinctBy(fn).ifEmpty { null }
|
||||
val <T> Collection<T>.csv get() = joinToString(",")
|
||||
val IntArray.csv get() = joinToString(",")
|
||||
|
||||
// Optionals
|
||||
operator fun <T> Optional<T>.invoke(): T? = orElse(null)
|
||||
@@ -227,6 +230,7 @@ fun Str.fromChusanUsername() = String(this.toByteArray(StandardCharsets.ISO_8859
|
||||
fun Str.truncate(len: Int) = if (this.length > len) this.take(len) + "..." else this
|
||||
val Str.some get() = ifBlank { null }
|
||||
val ByteArray.hexStr get() = toHexString()
|
||||
operator fun StringBuilder.plusAssign(other: String) { this.append(other) }
|
||||
|
||||
// Coroutine
|
||||
suspend fun <T> async(block: suspend kotlinx.coroutines.CoroutineScope.() -> T): T = withContext(Dispatchers.IO) { block() }
|
||||
@@ -255,6 +259,7 @@ operator fun <E> List<E>.component13(): E = get(12)
|
||||
|
||||
inline operator fun <reified E> List<Any?>.invoke(i: Int) = get(i) as E
|
||||
val empty = emptyList<Any>()
|
||||
val emptyMap = emptyMap<Any, Any>()
|
||||
|
||||
val <F> Pair<F, *>.l get() = component1()
|
||||
val <S> Pair<*, S>.r get() = component2()
|
||||
|
||||
@@ -4,6 +4,7 @@ import ext.*
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.model.CardStatus
|
||||
import icu.samnyan.aqua.sega.general.model.sensitiveInfo
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos
|
||||
@@ -52,7 +53,7 @@ class BotController(
|
||||
secret.checkSecret()
|
||||
|
||||
// 1. Find user card
|
||||
val oc = (us.cardRepo.findByLuid(card)() ?: (404 - "Card not found")).maybeGhost()
|
||||
val oc = (us.cardRepo.findByLuid(card) ?: (404 - "Card not found")).maybeGhost()
|
||||
|
||||
// 2. Change the status to migrated
|
||||
us.cardRepo.save(oc.apply {
|
||||
@@ -66,7 +67,7 @@ class BotController(
|
||||
fun clearMigrateFlag(@RP secret: Str, @RP card: Str): Any {
|
||||
secret.checkSecret()
|
||||
|
||||
val oc = (us.cardRepo.findByLuid(card)() ?: (404 - "Card not found")).maybeGhost()
|
||||
val oc = (us.cardRepo.findByLuid(card) ?: (404 - "Card not found")).maybeGhost()
|
||||
|
||||
us.cardRepo.save(oc.apply {
|
||||
status = CardStatus.NORMAL
|
||||
@@ -82,14 +83,14 @@ class BotController(
|
||||
secret.checkSecret()
|
||||
|
||||
// 1. Check if the card exist
|
||||
var cards = listOfNotNull(
|
||||
us.cardRepo.findByLuid(cardId)(),
|
||||
var cards: MutableList<Card> = listOfNotNull(
|
||||
us.cardRepo.findByLuid(cardId),
|
||||
).mut
|
||||
|
||||
cardId.toLongOrNull()?.let {
|
||||
cards += listOfNotNull(
|
||||
us.cardRepo.findById(it)(),
|
||||
us.cardRepo.findByExtId(it)(),
|
||||
us.cardRepo.findByExtId(it),
|
||||
)
|
||||
|
||||
cards += listOfNotNull(
|
||||
@@ -110,8 +111,8 @@ class BotController(
|
||||
|
||||
return cards.map { card ->
|
||||
// Find all games played by this card
|
||||
val chu3 = chu3Db.userData.findByCard_ExtId(card.extId)()
|
||||
val mai2 = mai2Db.userData.findByCard_ExtId(card.extId)()
|
||||
val chu3 = chu3Db.userData.findByCard_ExtId(card.extId)
|
||||
val mai2 = mai2Db.userData.findByCard_ExtId(card.extId)
|
||||
val gamesDict = listOfNotNull(chu3, mai2).map {
|
||||
// Find the keychip owner
|
||||
val keychip = it.lastClientId
|
||||
|
||||
@@ -8,6 +8,7 @@ import icu.samnyan.aqua.net.games.IUserData
|
||||
import icu.samnyan.aqua.net.utils.AquaNetProps
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserDataRepo
|
||||
import icu.samnyan.aqua.sega.diva.PlayerProfileRepository
|
||||
import icu.samnyan.aqua.sega.general.dao.CardRepository
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
@@ -19,7 +20,6 @@ import org.springframework.scheduling.annotation.Scheduled
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.random.Random
|
||||
|
||||
@RestController
|
||||
@@ -30,7 +30,8 @@ class CardController(
|
||||
val cardService: CardService,
|
||||
val cardGameService: CardGameService,
|
||||
val cardRepository: CardRepository,
|
||||
val props: AquaNetProps
|
||||
val props: AquaNetProps,
|
||||
val fedy: Fedy
|
||||
) {
|
||||
companion object {
|
||||
val log = logger()
|
||||
@@ -80,10 +81,12 @@ class CardController(
|
||||
val id = cardService.sanitizeCardId(cardId)
|
||||
|
||||
// Create a new card
|
||||
cardService.registerByAccessCode(id, u)
|
||||
val newCard = cardService.registerByAccessCode(id, u)
|
||||
|
||||
log.info("Net /card/link : Created new card $id for user ${u.username}")
|
||||
|
||||
fedy.onCardLinked(newCard.luid, oldExtId = null, ghostExtId = u.ghostCard.extId, emptyList())
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
|
||||
@@ -98,6 +101,9 @@ class CardController(
|
||||
val games = migrate.split(',')
|
||||
cardGameService.migrate(card, games)
|
||||
|
||||
fedy.onCardLinked(card.luid, oldExtId = card.extId, ghostExtId = u.ghostCard.extId,
|
||||
games.map { Fedy.getGameName(it) }.filterNotNull())
|
||||
|
||||
log.info("Net /card/link : Linked card ${card.id} to user ${u.username} and migrated data to ${games.joinToString()}")
|
||||
|
||||
SUCCESS
|
||||
@@ -115,10 +121,14 @@ class CardController(
|
||||
// Ghost cards cannot be unlinked
|
||||
if (card.isGhost) 400 - "Account virtual cards cannot be unlinked"
|
||||
|
||||
val luid = card.luid
|
||||
|
||||
// Unbind the card
|
||||
card.aquaUser = null
|
||||
async { cardRepository.save(card) }
|
||||
|
||||
fedy.onCardUnlinked(luid)
|
||||
|
||||
log.info("Net /card/unlink : Unlinked card ${card.id} from user ${u.username}")
|
||||
|
||||
SUCCESS
|
||||
@@ -136,7 +146,7 @@ class CardController(
|
||||
*
|
||||
* Assumption: The card is already linked to the user.
|
||||
*/
|
||||
suspend fun <T : IUserData> migrateCard(repo: GenericUserDataRepo<T>, cardRepo: CardRepository, card: Card): Bool {
|
||||
suspend fun <T : IUserData> migrateCard(gameName: Str, repo: GenericUserDataRepo<T>, cardRepo: CardRepository, card: Card): Bool {
|
||||
val ghost = card.aquaUser!!.ghostCard
|
||||
|
||||
// Check if data already exists in the user's ghost card
|
||||
@@ -144,7 +154,7 @@ suspend fun <T : IUserData> migrateCard(repo: GenericUserDataRepo<T>, cardRepo:
|
||||
// Create a new dummy card for deleted data
|
||||
it.card = async {
|
||||
cardRepo.save(Card().apply {
|
||||
luid = "Migrated data of ghost card ${ghost.id} for user ${card.aquaUser!!.auId} on ${utcNow().isoDateTime()}"
|
||||
luid = "Migrated data of ghost card ${ghost.id} for user ${card.aquaUser!!.auId} on ${utcNow().isoDateTime()} (${gameName})"
|
||||
// Randomize an extId outside the normal range
|
||||
extId = Random.nextLong(0x7FFFFFF7L shl 32, 0x7FFFFFFFL shl 32)
|
||||
registerTime = LocalDateTime.now()
|
||||
@@ -162,6 +172,23 @@ suspend fun <T : IUserData> migrateCard(repo: GenericUserDataRepo<T>, cardRepo:
|
||||
return true
|
||||
}
|
||||
|
||||
suspend fun <T : IUserData> orphanData(gameName: Str, repo: GenericUserDataRepo<T>, cardRepo: CardRepository, card: Card) {
|
||||
// Orphan the data by assigning them to a dummy card
|
||||
repo.findByCard(card)?.let {
|
||||
// Create a new dummy card for orphaned data
|
||||
it.card = async {
|
||||
cardRepo.save(Card().apply {
|
||||
luid = "Unmigrated data of card ${card.luid} for user ${card.aquaUser!!.auId} on ${utcNow().isoDateTime()} (${gameName})"
|
||||
// Randomize an extId outside the normal range
|
||||
extId = Random.nextLong(0x7FFFFFF7L shl 32, 0x7FFFFFFFL shl 32)
|
||||
registerTime = LocalDateTime.now()
|
||||
accessTime = registerTime
|
||||
})
|
||||
}
|
||||
async { repo.save(it) }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getSummaryFor(repo: GenericUserDataRepo<*>, card: Card): Map<Str, Any>? {
|
||||
val data = async { repo.findByCard(card) } ?: return null
|
||||
return mapOf(
|
||||
@@ -177,7 +204,7 @@ class CardGameService(
|
||||
val chusan: Chu3UserDataRepo,
|
||||
val wacca: WcUserRepo,
|
||||
val ongeki: OgkUserDataRepo,
|
||||
val diva: icu.samnyan.aqua.sega.diva.dao.userdata.PlayerProfileRepository,
|
||||
val diva: PlayerProfileRepository,
|
||||
val safety: AquaNetSafetyService,
|
||||
val cardRepo: CardRepository,
|
||||
val em: EntityManager
|
||||
@@ -189,18 +216,20 @@ class CardGameService(
|
||||
suspend fun migrate(crd: Card, games: List<String>) = async {
|
||||
// Migrate data from the card to the user's ghost card
|
||||
// An easy migration is to change the UserData card field to the user's ghost card
|
||||
val dataRepos = mapOf(
|
||||
"mai2" to maimai2,
|
||||
"chu3" to chusan,
|
||||
"ongeki" to ongeki,
|
||||
"wacca" to wacca,
|
||||
)
|
||||
val remainingGames = dataRepos.keys.toMutableSet()
|
||||
games.forEach { game ->
|
||||
when (game) {
|
||||
"mai2" -> migrateCard(maimai2, cardRepo, crd)
|
||||
"chu3" -> migrateCard(chusan, cardRepo, crd)
|
||||
"ongeki" -> migrateCard(ongeki, cardRepo, crd)
|
||||
"wacca" -> migrateCard(wacca, cardRepo, crd)
|
||||
// TODO: diva
|
||||
// "diva" -> diva.findByPdId(card.extId.toInt()).getOrNull()?.let {
|
||||
// it.pdId = card.aquaUser!!.ghostCard
|
||||
// }
|
||||
}
|
||||
val dataRepo = dataRepos[game] ?: return@forEach
|
||||
migrateCard(game, dataRepo, cardRepo, crd)
|
||||
remainingGames.remove(game)
|
||||
}
|
||||
// For remaining games, orphan the data by assigning them to a dummy card
|
||||
remainingGames.forEach { game -> orphanData(game, dataRepos[game]!!, cardRepo, crd) }
|
||||
}
|
||||
|
||||
suspend fun getSummary(card: Card) = async {
|
||||
@@ -209,7 +238,7 @@ class CardGameService(
|
||||
"chu3" to getSummaryFor(chusan, card),
|
||||
"ongeki" to getSummaryFor(ongeki, card),
|
||||
"wacca" to getSummaryFor(wacca, card),
|
||||
"diva" to diva.findByPdId(card.extId).getOrNull()?.let {
|
||||
"diva" to diva.findByPdId(card.extId)()?.let {
|
||||
mapOf(
|
||||
"name" to it.playerName,
|
||||
"rating" to it.level,
|
||||
|
||||
@@ -1,32 +1,37 @@
|
||||
package icu.samnyan.aqua.net
|
||||
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.security.MessageDigest
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserFedyRepo
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.net.components.EmailProperties
|
||||
import icu.samnyan.aqua.net.components.JWT
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserFedy
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import icu.samnyan.aqua.net.games.ImportController
|
||||
import icu.samnyan.aqua.net.games.mai2.Mai2Import
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.games.ExportOptions
|
||||
import icu.samnyan.aqua.sega.maimai2.handler.UploadUserPlaylogHandler as Mai2UploadUserPlaylogHandler
|
||||
import icu.samnyan.aqua.sega.maimai2.handler.UpsertUserAllHandler as Mai2UpsertUserAllHandler
|
||||
import icu.samnyan.aqua.net.utils.ApiException
|
||||
import java.util.Arrays
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.transaction.PlatformTransactionManager
|
||||
import org.springframework.transaction.support.TransactionTemplate
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserDataRepo
|
||||
import icu.samnyan.aqua.net.games.GenericUserDataRepo
|
||||
import icu.samnyan.aqua.net.games.IUserData
|
||||
import icu.samnyan.aqua.net.games.mai2.Mai2Import
|
||||
import icu.samnyan.aqua.net.utils.ApiException
|
||||
import icu.samnyan.aqua.net.utils.PathProps
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserDataRepo
|
||||
import icu.samnyan.aqua.sega.general.dao.CardRepository
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserDataRepo
|
||||
import icu.samnyan.aqua.sega.ongeki.OgkUserDataRepo
|
||||
import icu.samnyan.aqua.sega.wacca.model.db.WcUserRepo
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.transaction.PlatformTransactionManager
|
||||
import org.springframework.transaction.support.TransactionTemplate
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.io.path.getLastModifiedTime
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.writeBytes
|
||||
import icu.samnyan.aqua.sega.maimai2.handler.UploadUserPlaylogHandler as Mai2UploadUserPlaylogHandler
|
||||
import icu.samnyan.aqua.sega.maimai2.handler.UpsertUserAllHandler as Mai2UpsertUserAllHandler
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.fedy")
|
||||
@@ -36,24 +41,44 @@ class FedyProps {
|
||||
var remote: String = ""
|
||||
}
|
||||
|
||||
enum class FedyEvent {
|
||||
Linked,
|
||||
Unlinked,
|
||||
Upserted,
|
||||
Imported,
|
||||
}
|
||||
data class UserProfilePicture(val url: Str, val lastUpdatedMs: Long)
|
||||
data class UserBasicInfo(
|
||||
val auId: Long, val ghostExtId: Long, val registrationTimeMs: Long,
|
||||
val username: Str, val displayName: Str, val email: Str, val passwordHash: Str, val profileBio: Str,
|
||||
val profilePicture: UserProfilePicture?,
|
||||
)
|
||||
|
||||
private data class UserUpdatedEvent(val user: UserBasicInfo, val isNewlyCreated: Bool)
|
||||
private data class CardCreatedEvent(val luid: Str, val extId: Long)
|
||||
private data class CardLinkedEvent(val luid: Str, val oldExtId: Long?, val ghostExtId: Long, val migratedGames: List<Str>)
|
||||
private data class CardUnlinkedEvent(val luid: Str)
|
||||
private data class DataUpdatedEvent(val extId: Long, val isGhostCard: Bool, val game: Str, val removeOldData: Bool)
|
||||
|
||||
private data class FedyEvent(
|
||||
var userUpdated: UserUpdatedEvent? = null,
|
||||
var cardCreated: CardCreatedEvent? = null,
|
||||
var cardLinked: CardLinkedEvent? = null,
|
||||
var cardUnlinked: CardUnlinkedEvent? = null,
|
||||
var dataUpdated: DataUpdatedEvent? = null,
|
||||
)
|
||||
|
||||
@RestController
|
||||
@API("/api/v2/fedy")
|
||||
@API("/api/v2/fedy", consumes = ["multipart/form-data"])
|
||||
class Fedy(
|
||||
val jwt: JWT,
|
||||
val userRepo: AquaNetUserRepo,
|
||||
val userFedyRepo: AquaNetUserFedyRepo,
|
||||
val us: AquaUserServices,
|
||||
val emailProps: EmailProperties,
|
||||
val cardRepo: CardRepository,
|
||||
val cardService: CardService,
|
||||
val mai2Import: Mai2Import,
|
||||
val mai2UserDataRepo: Mai2UserDataRepo,
|
||||
val mai2UploadUserPlaylog: Mai2UploadUserPlaylogHandler,
|
||||
val mai2UpsertUserAll: Mai2UpsertUserAllHandler,
|
||||
val chu3UserDataRepo: Chu3UserDataRepo,
|
||||
val ongekiUserDataRepo: OgkUserDataRepo,
|
||||
val waccaUserDataRepo: WcUserRepo,
|
||||
val props: FedyProps,
|
||||
val paths: PathProps,
|
||||
val transactionManager: PlatformTransactionManager
|
||||
) {
|
||||
val transaction by lazy { TransactionTemplate(transactionManager) }
|
||||
@@ -63,78 +88,102 @@ class Fedy(
|
||||
if (!MessageDigest.isEqual(this.toByteArray(), props.key.toByteArray())) 403 - "Invalid Key"
|
||||
}
|
||||
|
||||
@API("/status")
|
||||
fun handleStatus(@RP token: Str): Any {
|
||||
val user = jwt.auth(token)
|
||||
val userFedy = userFedyRepo.findByAquaNetUserAuId(user.auId)
|
||||
return mapOf("linkedAt" to (userFedy?.createdAt?.toEpochMilli() ?: 0))
|
||||
val suppressEvents = ThreadLocal.withInitial { false }
|
||||
private fun <T> handleFedy(key: Str, block: () -> T): T {
|
||||
val old = suppressEvents.get()
|
||||
suppressEvents.set(true)
|
||||
try {
|
||||
key.checkKey()
|
||||
return block()
|
||||
} finally { suppressEvents.set(old) }
|
||||
}
|
||||
|
||||
@API("/link")
|
||||
fun handleLink(@RP token: Str, @RP nonce: Str): Any {
|
||||
val user = jwt.auth(token)
|
||||
data class FedyErr(val code: Int, val message: Str)
|
||||
|
||||
if (userFedyRepo.findByAquaNetUserAuId(user.auId) != null) 412 - "User already linked"
|
||||
val userFedy = AquaNetUserFedy(aquaNetUser = user)
|
||||
userFedyRepo.save(userFedy)
|
||||
|
||||
notify(FedyEvent.Linked, mapOf("auId" to user.auId, "nonce" to nonce))
|
||||
return mapOf("linkedAt" to userFedy.createdAt.toEpochMilli())
|
||||
data class UserPullReq(val auId: Long)
|
||||
data class UserPullRes(val user: UserBasicInfo?)
|
||||
@API("/user/pull")
|
||||
fun handleUserPull(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: UserPullReq): UserPullRes = handleFedy(key) {
|
||||
UserPullRes(us.userRepo.findByAuId(req.auId)?.fedyBasicInfo())
|
||||
}
|
||||
|
||||
@API("/unlink")
|
||||
fun handleUnlink(@RP token: Str): Any {
|
||||
val user = jwt.auth(token)
|
||||
|
||||
val userFedy = userFedyRepo.findByAquaNetUserAuId(user.auId) ?: 412 - "User not linked"
|
||||
userFedyRepo.delete(userFedy)
|
||||
|
||||
notify(FedyEvent.Unlinked, mapOf("auId" to user.auId))
|
||||
return SUCCESS
|
||||
data class UserLookupReq(val username: Str?, val email: Str?)
|
||||
data class UserLookupRes(val user: UserBasicInfo?)
|
||||
@API("/user/lookup")
|
||||
fun handleUserLogin(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: UserLookupReq): UserLookupRes = handleFedy(key) {
|
||||
UserLookupRes(user =
|
||||
(req.username?.let { us.userRepo.findByUsernameIgnoreCase(it) } ?: req.email?.let {us.userRepo.findByEmailIgnoreCase(it) })
|
||||
?.takeIf { it.emailConfirmed || !emailProps.enable }
|
||||
?.fedyBasicInfo()
|
||||
)
|
||||
}
|
||||
|
||||
private fun ensureUser(auId: Long): AquaNetUser {
|
||||
val userFedy = userFedyRepo.findByAquaNetUserAuId(auId) ?: 404 - "User not linked"
|
||||
val user = userRepo.findByAuId(auId) ?: 404 - "User not found"
|
||||
return user
|
||||
data class UserRegisterReq(val username: Str, val email: Str, val password: Str)
|
||||
data class UserRegisterRes(val error: FedyErr? = null, val user: UserBasicInfo? = null)
|
||||
@API("/user/register")
|
||||
fun handleUserRegister(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: UserRegisterReq): UserRegisterRes = handleFedy(key) {
|
||||
{
|
||||
UserRegisterRes(user = us.create(req.username, req.email, req.password, "", emailConfirmed = true).fedyBasicInfo())
|
||||
} caught { UserRegisterRes(error = it) }
|
||||
}
|
||||
|
||||
data class UnlinkByRemoteReq(val auId: Long)
|
||||
@API("/unlink-by-remote")
|
||||
fun handleUnlinkByRemote(@RH(KEY_HEADER) key: Str, @RB req: UnlinkByRemoteReq): Any {
|
||||
key.checkKey()
|
||||
val user = ensureUser(req.auId)
|
||||
userFedyRepo.deleteByAquaNetUserAuId(user.auId)
|
||||
// No need to notify remote, because initiated by remote
|
||||
return SUCCESS
|
||||
data class UserUpdateReq(val auId: Long, val fields: Map<Str, Str?>?)
|
||||
data class UserUpdateRes(val error: FedyErr? = null, val user: UserBasicInfo? = null)
|
||||
@API("/user/update")
|
||||
fun handleUserUpdate(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: UserUpdateReq, @RT(PFP_PART) pfpFile: MultipartFile?): UserUpdateRes = handleFedy(key) {
|
||||
{
|
||||
val ru = us.userRepo.findByAuId(req.auId) ?: (404 - "User not found")
|
||||
val fields = req.fields?.filterValues { it != null }?.mapValues { it.value as Str } ?: emptyMap()
|
||||
fields.forEach { (k, v) ->
|
||||
if (k == "email") { ru.email = us.validateEmail(v) }
|
||||
else us.update(ru, k, v)
|
||||
}
|
||||
pfpFile?.run {
|
||||
val mime = TIKA.detect(pfpFile.bytes).takeIf { it.startsWith("image/") } ?: (400 - "Invalid file type")
|
||||
val name = "${ru.auId}${MIMES.forName(mime)?.extension ?: ".jpg"}"
|
||||
(paths.aquaNetPortrait.path() / name).writeBytes(bytes)
|
||||
ru.profilePicture = name
|
||||
}
|
||||
us.userRepo.save(ru)
|
||||
if (fields.containsKey("pwHash") ?: false) { us.clearAllSessions(ru) }
|
||||
UserUpdateRes(user = ru.fedyBasicInfo())
|
||||
} caught { UserUpdateRes(error = it) }
|
||||
}
|
||||
|
||||
data class PullReq(val auId: Long, val game: Str, val exportOptions: ExportOptions)
|
||||
@API("/pull")
|
||||
fun handlePull(@RH(KEY_HEADER) key: Str, @RB req: PullReq): Any {
|
||||
key.checkKey()
|
||||
val user = ensureUser(req.auId)
|
||||
fun catched(block: () -> Any) =
|
||||
try { mapOf("result" to block()) }
|
||||
catch (e: ApiException) { mapOf("error" to mapOf("code" to e.code, "message" to e.message.toString())) }
|
||||
return when (req.game) {
|
||||
"mai2" -> catched { mai2Import.export(user, req.exportOptions) }
|
||||
else -> 406 - "Unsupported game"
|
||||
}
|
||||
private fun AquaNetUser.fedyBasicInfo() = UserBasicInfo(
|
||||
auId, ghostCard.extId, regTime,
|
||||
username, displayName, email, pwHash, profileBio ?: "",
|
||||
profilePicture
|
||||
?.let { paths.aquaNetPortrait.path() / it }?.takeIf { it.isRegularFile() }
|
||||
?.let { UserProfilePicture(
|
||||
url = "/uploads/net/portrait/${profilePicture}",
|
||||
lastUpdatedMs = it.getLastModifiedTime().toMillis()
|
||||
) }
|
||||
)
|
||||
|
||||
data class DataPullReq(val extId: Long, val game: Str, val exportOptions: ExportOptions)
|
||||
data class DataPullRes(val error: FedyErr? = null, val result: Any? = null)
|
||||
@API("/data/pull")
|
||||
fun handleDataPull(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: DataPullReq): DataPullRes = handleFedy(key) {
|
||||
val card = cardRepo.findByExtId(req.extId)
|
||||
?: (404 - "Card with extId ${req.extId} not found")
|
||||
{
|
||||
DataPullRes(result = when (req.game) {
|
||||
"mai2" -> mai2Import.export(card, req.exportOptions)
|
||||
else -> 406 - "Unsupported game"
|
||||
})
|
||||
} caught { DataPullRes(error = it) }
|
||||
}
|
||||
|
||||
data class PushReq(val auId: Long, val game: Str, val data: JDict, val removeOldData: Bool)
|
||||
data class DataPushReq(val extId: Long, val game: Str, val data: JDict, val removeOldData: Bool)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@API("/push")
|
||||
fun handlePush(@RH(KEY_HEADER) key: Str, @RB req: PushReq): Any {
|
||||
key.checkKey()
|
||||
val user = ensureUser(req.auId)
|
||||
val extId = user.ghostCard.extId
|
||||
@API("/data/push")
|
||||
fun handleDataPush(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: DataPushReq): Any = handleFedy(key) {
|
||||
val extId = req.extId
|
||||
fun<UserData : IUserData, UserRepo : GenericUserDataRepo<UserData>> removeOldData(repo: UserRepo) {
|
||||
val oldData = repo.findByCard_ExtId(extId)
|
||||
if (oldData.isPresent) {
|
||||
repo.findByCard_ExtId(extId)?.let { oldData ->
|
||||
log.info("Fedy: Deleting old data for $extId (${req.game})")
|
||||
repo.delete(oldData.get());
|
||||
repo.delete(oldData);
|
||||
repo.flush()
|
||||
}
|
||||
}
|
||||
@@ -149,29 +198,112 @@ class Fedy(
|
||||
else -> 406 - "Unsupported game"
|
||||
} }
|
||||
|
||||
return SUCCESS
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
fun onUpserted(game: Str, maybeExtId: Any?) = maybeNotifyAsync(FedyEvent.Upserted, game, maybeExtId)
|
||||
fun onImported(game: Str, maybeExtId: Any?) = maybeNotifyAsync(FedyEvent.Imported, game, maybeExtId)
|
||||
data class CardResolveReq(val luid: Str, val pairedLuid: Str?, val createIfNotFound: Bool)
|
||||
data class CardResolveRes(val extId: Long, val isGhostCard: Bool, val isNewlyCreated: Bool, val isPairedLuidDiverged: Bool)
|
||||
@API("/card/resolve")
|
||||
fun handleCardResolve(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: CardResolveReq): CardResolveRes = handleFedy(key) {
|
||||
var card = cardService.tryLookup(req.luid)
|
||||
var isNewlyCreated = false
|
||||
if (card != null) {
|
||||
card = card.maybeGhost()
|
||||
if (!card.isGhost) isNewlyCreated = isCardFresh(card)
|
||||
} else if (req.createIfNotFound) {
|
||||
card = cardService.registerByAccessCode(req.luid, null)
|
||||
isNewlyCreated = true
|
||||
log.info("Fedy /card/resolve : Created new card ${card.id} (${card.luid})")
|
||||
}
|
||||
var isPairedLuidDiverged = false
|
||||
if (req.pairedLuid != null) {
|
||||
var pairedCard = cardService.tryLookup(req.pairedLuid)?.maybeGhost()
|
||||
if (pairedCard?.extId != card?.extId) {
|
||||
var isGhost = pairedCard?.isGhost == true
|
||||
var isFresh = pairedCard != null && isCardFresh(pairedCard)
|
||||
if (isGhost && isFresh) isPairedLuidDiverged = true
|
||||
else if (!isGhost && card?.isGhost == true) {
|
||||
// Ensure paired card is linked, if the main card is linked
|
||||
// If the main card is not linked, there's nothing Fedy can do. It's Fedy's best effort.
|
||||
if (pairedCard == null) { pairedCard = cardService.registerByAccessCode(req.pairedLuid, card.aquaUser) }
|
||||
else { pairedCard.aquaUser = card.aquaUser; cardRepo.save(pairedCard) }
|
||||
log.info("Fedy /card/resolve : Created paired card ${pairedCard.id} (${pairedCard.luid}) for user ${card.aquaUser?.auId} (${card.aquaUser?.username})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun maybeNotifyAsync(event: FedyEvent, game: Str, maybeExtId: Any?) = if (!props.enabled) {} else CompletableFuture.runAsync { try {
|
||||
val extId = maybeExtId?.long ?: return@runAsync
|
||||
val user = userRepo.findByGhostCardExtId(extId) ?: return@runAsync
|
||||
val userFedy = userFedyRepo.findByAquaNetUserAuId(user.auId) ?: return@runAsync
|
||||
notify(event, mapOf("auId" to user.auId, "game" to game))
|
||||
} catch (e: Exception) {
|
||||
log.error("Error handling Fedy on maybeNotifyAsync($event, $game, $maybeExtId)", e)
|
||||
} }
|
||||
CardResolveRes(
|
||||
card?.extId ?: 0,
|
||||
card?.isGhost ?: false,
|
||||
isNewlyCreated,
|
||||
isPairedLuidDiverged)
|
||||
}
|
||||
|
||||
private fun notify(event: FedyEvent, body: Any?) {
|
||||
data class CardLinkReq(val auId: Long, val luid: Str)
|
||||
@API("/card/link")
|
||||
fun handleCardLink(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: CardLinkReq): Any = handleFedy(key) {
|
||||
val ru = us.userRepo.findByAuId(req.auId) ?: (404 - "User not found")
|
||||
var card = cardService.tryLookup(req.luid)
|
||||
if (card == null) {
|
||||
card = cardService.registerByAccessCode(req.luid, ru)
|
||||
log.info("Fedy /card/link : Linked new card ${card.id} (${card.luid}) to user ${ru.auId} (${ru.username})")
|
||||
} else {
|
||||
if (card.isGhost) 400 - "Account virtual cards cannot be unlinked"
|
||||
val cu = card.aquaUser
|
||||
if (cu != null) {
|
||||
if (cu.auId == req.auId) log.info("Fedy /card/link : Existing card ${card.id} (${card.luid}) already linked to user ${ru.auId} (${ru.username})")
|
||||
else 400 - "Card linked to another user"
|
||||
} else {
|
||||
card.aquaUser = ru
|
||||
cardRepo.save(card)
|
||||
log.info("Fedy /card/link : Linked existing card ${card.id} (${card.luid}) to user ${ru.auId} (${ru.username})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CardUnlinkReq(val auId: Long, val luid: Str)
|
||||
@API("/card/unlink")
|
||||
fun handleCardUnlink(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: CardUnlinkReq): Any = handleFedy(key) {
|
||||
val card = cardService.tryLookup(req.luid)
|
||||
val cu = card?.aquaUser ?: return@handleFedy SUCCESS // Nothing to do
|
||||
|
||||
if (cu.auId != req.auId) 400 - "Card linked to another user"
|
||||
if (card.isGhost) 400 - "Account virtual cards cannot be unlinked"
|
||||
|
||||
card.aquaUser = null
|
||||
cardRepo.save(card)
|
||||
log.info("Fedy /card/unlink : Unlinked card ${card.id} (${card.luid}) from user ${cu.auId} (${cu.username})")
|
||||
}
|
||||
|
||||
fun onUserUpdated(u: AquaNetUser, isNew: Bool = false) = maybeNotifyAsync(FedyEvent(userUpdated = UserUpdatedEvent(u.fedyBasicInfo(), isNew)))
|
||||
fun onCardCreated(luid: Str, extId: Long) = maybeNotifyAsync(FedyEvent(cardCreated = CardCreatedEvent(luid, extId)))
|
||||
fun onCardLinked(luid: Str, oldExtId: Long?, ghostExtId: Long, migratedGames: List<Str>) = maybeNotifyAsync(FedyEvent(cardLinked = CardLinkedEvent(luid, oldExtId, ghostExtId, migratedGames)))
|
||||
fun onCardUnlinked(luid: Str) = maybeNotifyAsync(FedyEvent(cardUnlinked = CardUnlinkedEvent(luid)))
|
||||
fun onDataUpdated(extId: Long, game: Str, removeOldData: Bool) = maybeNotifyAsync({
|
||||
val card = cardRepo.findByExtId(extId) ?: return@maybeNotifyAsync null // Card not found, nothing to do
|
||||
FedyEvent(dataUpdated = DataUpdatedEvent(extId, card.isGhost, game, removeOldData))
|
||||
})
|
||||
|
||||
private fun maybeNotifyAsync(event: FedyEvent) = maybeNotifyAsync({ event })
|
||||
private fun maybeNotifyAsync(getEvent: () -> FedyEvent?) = if (!props.enabled && !suppressEvents.get()) {} else CompletableFuture.runAsync {
|
||||
var event: FedyEvent? = null
|
||||
try {
|
||||
event = getEvent()
|
||||
if (event == null) return@runAsync // Nothing to do
|
||||
notify(event)
|
||||
} catch (e: Exception) {
|
||||
log.error("Error handling Fedy on maybeNotifyAsync($event)", e)
|
||||
}
|
||||
}.let {}
|
||||
|
||||
private fun notify(event: FedyEvent) {
|
||||
val MAX_RETRY = 3
|
||||
val body = body?.toJson() ?: "{}"
|
||||
val body = event.toJson() ?: "{}"
|
||||
var retry = 0
|
||||
var shouldRetry = true
|
||||
while (retry < MAX_RETRY) {
|
||||
while (true) {
|
||||
try {
|
||||
val response = "${props.remote.trimEnd('/')}/notify/${event.name}".request()
|
||||
val response = "${props.remote.trimEnd('/')}/notify".request()
|
||||
.header("Content-Type" to "application/json")
|
||||
.header(KEY_HEADER to props.key)
|
||||
.post(body)
|
||||
@@ -191,13 +323,38 @@ class Fedy(
|
||||
}
|
||||
}
|
||||
|
||||
// Apparently existing cards could possibly be fresh and never used in any game. Treat them as new cards.
|
||||
private fun isCardFresh(c: Card): Bool {
|
||||
fun <T : IUserData> checkForGame(repo: GenericUserDataRepo<T>, card: Card): Bool = repo.findByCard(card) == null
|
||||
return when {
|
||||
checkForGame(mai2UserDataRepo, c) -> false
|
||||
checkForGame(chu3UserDataRepo, c) -> false
|
||||
checkForGame(ongekiUserDataRepo, c) -> false
|
||||
checkForGame(waccaUserDataRepo, c) -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private infix fun <T> (() -> T).caught(onError: (FedyErr) -> T) =
|
||||
try { this() }
|
||||
catch (e: ApiException) { onError(FedyErr(code = e.code, message = e.message.toString())) }
|
||||
|
||||
companion object
|
||||
{
|
||||
const val KEY_HEADER = "X-Fedy-Key"
|
||||
const val REQ_PART = "request"
|
||||
const val PFP_PART = "profilePicture"
|
||||
val log = logger()
|
||||
|
||||
fun getGameName(gameId: Str) = when (gameId) {
|
||||
"mai2" -> "mai2"
|
||||
"SDEZ" -> "mai2"
|
||||
"chu3" -> "chu3"
|
||||
"SDHD" -> "chu3"
|
||||
"ongeki" -> "mu3"
|
||||
"SDDT" -> "mu3"
|
||||
"wacca" -> "wacca"
|
||||
"SDFE" -> "wacca"
|
||||
else -> null // Not supported
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ class FrontierProps {
|
||||
@API("/api/v2/frontier")
|
||||
class Frontier(
|
||||
val cardService: CardService,
|
||||
val props: FrontierProps
|
||||
val props: FrontierProps,
|
||||
val fedy: Fedy
|
||||
) {
|
||||
fun Str.checkFtk() {
|
||||
if (this != props.ftk) 403 - "Invalid FTK"
|
||||
@@ -32,9 +33,12 @@ class Frontier(
|
||||
|
||||
if (accessCode.length != 20) 400 - "Invalid access code"
|
||||
// if (!accessCode.startsWith("9900")) 400 - "Frontier access code must start with 9900"
|
||||
if (async { cardService.cardRepo.findByLuid(accessCode) }.isPresent) 400 - "Card already registered"
|
||||
if (async { cardService.cardRepo.findByLuid(accessCode) } != null) 400 - "Card already registered"
|
||||
|
||||
val card = async { cardService.registerByAccessCode(accessCode) }
|
||||
|
||||
fedy.onCardCreated(accessCode, card.extId)
|
||||
|
||||
return mapOf(
|
||||
"card" to card,
|
||||
"id" to card.extId // Expose hidden ID
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package icu.samnyan.aqua.net
|
||||
|
||||
import ext.JACKSON
|
||||
import ext.invoke
|
||||
import ext.logger
|
||||
import ext.parse
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
@@ -24,7 +23,7 @@ class Migrations(
|
||||
|
||||
@PostConstruct
|
||||
fun migrate() {
|
||||
val db = props.findByPropertyKey("migrations")() ?: PropertyEntry("migrations", "[]")
|
||||
val db = props.findByPropertyKey("migrations") ?: PropertyEntry("migrations", "[]")
|
||||
val p = JACKSON.parse<ArrayList<String>>(db.propertyValue)
|
||||
val old = p.size
|
||||
|
||||
@@ -47,7 +46,7 @@ class Migrations(
|
||||
if (c.extId > max) {
|
||||
var new = c.extId and max
|
||||
log.info("Removing signed bit: {${c.extId} -> $new} for ${c.luid}")
|
||||
while (cardRepo.findByExtId(new).isPresent) {
|
||||
while (cardRepo.findByExtId(new) != null) {
|
||||
log.error("> Conflicting card found for ${c.luid}: $new")
|
||||
new++
|
||||
}
|
||||
|
||||
@@ -2,21 +2,22 @@ package icu.samnyan.aqua.net
|
||||
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.components.*
|
||||
import icu.samnyan.aqua.net.db.*
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices.Companion.SETTING_FIELDS
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.db.EmailConfirmationRepo
|
||||
import icu.samnyan.aqua.net.db.ResetPasswordRepo
|
||||
import icu.samnyan.aqua.net.utils.PathProps
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.general.dao.CardRepository
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.model.CardStatus
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.io.path.writeBytes
|
||||
|
||||
@RestController
|
||||
@@ -31,12 +32,11 @@ class UserRegistrar(
|
||||
val confirmationRepo: EmailConfirmationRepo,
|
||||
val resetPasswordRepo: ResetPasswordRepo,
|
||||
val cardRepo: CardRepository,
|
||||
val cardService: CardService,
|
||||
val validator: AquaUserServices,
|
||||
val emailProps: EmailProperties,
|
||||
val sessionRepo: SessionTokenRepo,
|
||||
final val paths: PathProps
|
||||
) {
|
||||
@Autowired @Lazy lateinit var fedy: Fedy
|
||||
val portraitPath = paths.aquaNetPortrait.path()
|
||||
|
||||
companion object {
|
||||
@@ -68,29 +68,7 @@ class UserRegistrar(
|
||||
val country = geoIP.getCountry(ip)
|
||||
|
||||
// Create user
|
||||
val u = async { AquaNetUser(
|
||||
username = validator.checkUsername(username),
|
||||
email = validator.checkEmail(email),
|
||||
pwHash = validator.checkPwHash(password),
|
||||
regTime = millis(), lastLogin = millis(), country = country,
|
||||
) }
|
||||
|
||||
// Create a ghost card
|
||||
val card = Card().apply {
|
||||
extId = cardService.randExtID(cardExtIdStart, cardExtIdEnd)
|
||||
luid = extId.toString()
|
||||
registerTime = LocalDateTime.now()
|
||||
accessTime = registerTime
|
||||
aquaUser = u
|
||||
isGhost = true
|
||||
}
|
||||
u.ghostCard = card
|
||||
|
||||
// Save the user
|
||||
async {
|
||||
userRepo.save(u)
|
||||
cardRepo.save(card)
|
||||
}
|
||||
val u = async { validator.create(username, email, password, country) }
|
||||
|
||||
// Send confirmation email
|
||||
emailService.sendConfirmation(u)
|
||||
@@ -200,16 +178,13 @@ class UserRegistrar(
|
||||
if (reset.createdAt.plusSeconds(60 * 60 * 24).isBefore(Instant.now())) 400 - "Token expired"
|
||||
|
||||
// Change the password
|
||||
async { userRepo.save(reset.aquaNetUser.apply { pwHash = validator.checkPwHash(password) }) }
|
||||
val u = reset.aquaNetUser
|
||||
async { userRepo.save(u.apply { pwHash = validator.checkPwHash(password) }) }
|
||||
fedy.onUserUpdated(u)
|
||||
|
||||
// Remove the token from the list
|
||||
resetPasswordRepo.delete(reset)
|
||||
|
||||
// Clear all sessions
|
||||
sessionRepo.deleteAll(
|
||||
sessionRepo.findByAquaNetUserAuId(reset.aquaNetUser.auId)
|
||||
)
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
|
||||
@@ -227,8 +202,13 @@ class UserRegistrar(
|
||||
// Check if the token is expired
|
||||
if (confirmation.createdAt.plusSeconds(60 * 60 * 24).isBefore(Instant.now())) 400 - "Token expired"
|
||||
|
||||
// Check if the email is already confirmed
|
||||
val u = confirmation.aquaNetUser
|
||||
if (u.emailConfirmed) 400 - "Email already confirmed"
|
||||
|
||||
// Confirm the email
|
||||
async { userRepo.save(confirmation.aquaNetUser.apply { emailConfirmed = true }) }
|
||||
async { userRepo.save(u.apply { emailConfirmed = true }) }
|
||||
fedy.onUserUpdated(u, isNew = true)
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
@@ -245,22 +225,16 @@ class UserRegistrar(
|
||||
@API("/setting")
|
||||
@Doc("Validate and set a user setting field.", "Success message")
|
||||
suspend fun setting(@RP token: Str, @RP key: Str, @RP value: Str) = jwt.auth(token) { u ->
|
||||
// Check if the key is a settable field
|
||||
val field = SETTING_FIELDS.find { it.name == key } ?: (400 - "Invalid setting")
|
||||
|
||||
async {
|
||||
// Set the validated field
|
||||
field.setter.call(u, field.checker.call(validator, value))
|
||||
validator.update(u, key, value)
|
||||
|
||||
// Save the user
|
||||
userRepo.save(u)
|
||||
|
||||
// Clear all tokens if changing password
|
||||
if (key == "pwHash")
|
||||
sessionRepo.deleteAll(
|
||||
sessionRepo.findByAquaNetUserAuId(u.auId)
|
||||
)
|
||||
if (key == "pwHash") validator.clearAllSessions(u)
|
||||
}
|
||||
fedy.onUserUpdated(u)
|
||||
|
||||
SUCCESS
|
||||
}
|
||||
@@ -299,6 +273,7 @@ class UserRegistrar(
|
||||
(portraitPath / name).writeBytes(bytes)
|
||||
userRepo.save(u.apply { profilePicture = name })
|
||||
}
|
||||
fedy.onUserUpdated(u)
|
||||
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@ package icu.samnyan.aqua.net.components
|
||||
import ext.Bool
|
||||
import ext.Str
|
||||
import ext.logger
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import icu.samnyan.aqua.net.db.EmailConfirmation
|
||||
import icu.samnyan.aqua.net.db.EmailConfirmationRepo
|
||||
import icu.samnyan.aqua.net.db.ResetPassword
|
||||
import icu.samnyan.aqua.net.db.ResetPasswordRepo
|
||||
import icu.samnyan.aqua.net.db.*
|
||||
import org.simplejavamail.api.mailer.Mailer
|
||||
import org.simplejavamail.email.EmailBuilder
|
||||
import org.simplejavamail.springsupport.SimpleJavaMailSpringSupport
|
||||
|
||||
@@ -2,11 +2,7 @@ package icu.samnyan.aqua.net.components
|
||||
|
||||
import ext.Str
|
||||
import ext.minus
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
import icu.samnyan.aqua.net.db.SessionToken
|
||||
import icu.samnyan.aqua.net.db.SessionTokenRepo
|
||||
import icu.samnyan.aqua.net.db.getTokenExpiry
|
||||
import icu.samnyan.aqua.net.db.*
|
||||
import io.jsonwebtoken.JwtParser
|
||||
import io.jsonwebtoken.Jwts
|
||||
import io.jsonwebtoken.security.Keys
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.io.Serializable
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
import java.util.*
|
||||
|
||||
fun getTokenExpiry() = Instant.now().plusSeconds(7 * 86400)
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package icu.samnyan.aqua.net.db
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.UserRegistrar.Companion.cardExtIdEnd
|
||||
import icu.samnyan.aqua.net.UserRegistrar.Companion.cardExtIdStart
|
||||
import icu.samnyan.aqua.net.components.JWT
|
||||
import icu.samnyan.aqua.sega.allnet.AllNetProps
|
||||
import icu.samnyan.aqua.sega.allnet.KeyChipRepo
|
||||
@@ -9,11 +11,13 @@ import icu.samnyan.aqua.sega.allnet.KeychipSession
|
||||
import icu.samnyan.aqua.sega.general.GameMusicPopularity
|
||||
import icu.samnyan.aqua.sega.general.dao.CardRepository
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import jakarta.persistence.*
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.stereotype.Service
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KMutableProperty
|
||||
@@ -124,7 +128,9 @@ class AquaUserServices(
|
||||
val allNetProps: AllNetProps,
|
||||
val jwt: JWT,
|
||||
val em: EntityManager,
|
||||
val pop: GameMusicPopularity
|
||||
val pop: GameMusicPopularity,
|
||||
val cardService: CardService,
|
||||
val sessionRepo: SessionTokenRepo,
|
||||
) {
|
||||
companion object {
|
||||
val SETTING_FIELDS = AquaUserServices::class.functions
|
||||
@@ -136,12 +142,49 @@ class AquaUserServices(
|
||||
}
|
||||
}
|
||||
|
||||
fun create(username: Str, email: Str, password: Str, country: Str, emailConfirmed: Boolean = false): AquaNetUser {
|
||||
// Create user
|
||||
val u = AquaNetUser(
|
||||
username = checkUsername(username),
|
||||
email = validateEmail(email),
|
||||
pwHash = checkPwHash(password),
|
||||
regTime = millis(), lastLogin = millis(), country = country,
|
||||
emailConfirmed = emailConfirmed
|
||||
)
|
||||
|
||||
// Create a ghost card
|
||||
val card = Card().apply {
|
||||
extId = cardService.randExtID(cardExtIdStart, cardExtIdEnd)
|
||||
luid = extId.toString()
|
||||
registerTime = LocalDateTime.now()
|
||||
accessTime = registerTime
|
||||
aquaUser = u
|
||||
isGhost = true
|
||||
}
|
||||
u.ghostCard = card
|
||||
|
||||
// Save the user
|
||||
userRepo.save(u)
|
||||
cardRepo.save(card)
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
fun update(user: AquaNetUser, key: Str, value: Str) {
|
||||
// Check if the key is a settable field
|
||||
val field = SETTING_FIELDS.find { it.name == key } ?: (400 - "Invalid setting")
|
||||
// Set the validated field
|
||||
field.setter.call(user, field.checker.call(this, value))
|
||||
}
|
||||
|
||||
fun clearAllSessions(user: AquaNetUser) = sessionRepo.deleteAll(sessionRepo.findByAquaNetUserAuId(user.auId))
|
||||
|
||||
suspend fun <T> byName(username: Str, callback: suspend (AquaNetUser) -> T) =
|
||||
async { userRepo.findByUsernameIgnoreCase(username) }?.let { callback(it) } ?: (404 - "User not found")
|
||||
|
||||
suspend fun cardByName(username: Str) =
|
||||
if (username.startsWith("user")) username.substring(4).toLongOrNull()
|
||||
?.let { cardRepo.findById(it).getOrNull() } ?: (404 - "Card not found")
|
||||
?.let { cardRepo.findById(it)() } ?: (404 - "Card not found")
|
||||
else byName(username) { it.ghostCard }
|
||||
|
||||
suspend fun <T> cardByName(username: Str, callback: suspend (Card) -> T) = callback(cardByName(username))
|
||||
@@ -173,7 +216,7 @@ class AquaUserServices(
|
||||
400 - "User with username `$this` already exists"
|
||||
}
|
||||
|
||||
fun checkEmail(email: Str) = email.apply {
|
||||
fun validateEmail(email: Str) = email.apply {
|
||||
// Check if email is valid
|
||||
if (!isValidEmail()) 400 - "Invalid email"
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package icu.samnyan.aqua.net.db
|
||||
|
||||
import jakarta.persistence.*
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.io.Serializable
|
||||
import java.time.Instant
|
||||
|
||||
@Entity
|
||||
@Table(name = "aqua_net_user_fedy")
|
||||
class AquaNetUserFedy(
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
var id: Long = 0,
|
||||
|
||||
@Column(nullable = false)
|
||||
var createdAt: Instant = Instant.now(),
|
||||
|
||||
// Linking to the AquaNetUser
|
||||
@OneToOne
|
||||
@JoinColumn(name = "auId", referencedColumnName = "auId")
|
||||
var aquaNetUser: AquaNetUser,
|
||||
) : Serializable
|
||||
|
||||
@Repository
|
||||
interface AquaNetUserFedyRepo : JpaRepository<AquaNetUserFedy, Long> {
|
||||
fun findByAquaNetUserAuId(auId: Long): AquaNetUserFedy?
|
||||
fun deleteByAquaNetUserAuId(auId: Long): Unit
|
||||
}
|
||||
@@ -118,7 +118,7 @@ abstract class GameApiController<T : IUserData>(val name: String, userDataClass:
|
||||
}
|
||||
|
||||
@API("playlog")
|
||||
fun playlog(@RP id: Long): IGenericGamePlaylog = playlogRepo.findById(id).getOrNull() ?: (404 - "Playlog not found")
|
||||
fun playlog(@RP id: Long): IGenericGamePlaylog = playlogRepo.findById(id)() ?: (404 - "Playlog not found")
|
||||
|
||||
val userDetailFields by lazy { userDataClass.gettersMap().let { vm ->
|
||||
(settableFields.keys.toSet() + gettableFields)
|
||||
@@ -148,7 +148,7 @@ abstract class GameApiController<T : IUserData>(val name: String, userDataClass:
|
||||
userMusicRepo.findByUser_Card_ExtIdAndMusicIdIn(card.extId, musicList)
|
||||
}
|
||||
|
||||
fun genericUserSummary(card: Card, ratingComp: Map<String, String>, rival: Boolean? = null): GenericGameSummary {
|
||||
fun genericUserSummary(card: Card, ratingComp: Map<String, String>, rival: Boolean? = null, favorites: List<Int>? = null): GenericGameSummary {
|
||||
// Summary values: total plays, player rating, server-wide ranking
|
||||
// number of each rank, max combo, number of full combo, number of all perfect
|
||||
val user = userDataRepo.findByCard(card) ?: (404 - "Game data not found")
|
||||
@@ -199,7 +199,8 @@ abstract class GameApiController<T : IUserData>(val name: String, userDataClass:
|
||||
ratingComposition = ratingComp,
|
||||
recent = plays.sortedBy { it.userPlayDate.toString() }.takeLast(100).reversed(),
|
||||
lastPlayedHost = user.lastClientId?.let { us.userRepo.findByKeychip(it)?.username },
|
||||
rival = rival
|
||||
rival = rival,
|
||||
favorites = favorites
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ import java.time.LocalDate
|
||||
const val LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||
"abcdefghijklmnopqrstuvwxyz" +
|
||||
"0123456789"
|
||||
const val SYMBOLS = "・:;?!~/+-×÷=♂♀∀#&*@☆○◎◇□△▽♪†‡ΣαβγθφψωДё$()._␣"
|
||||
const val SYMBOLS = "・:;?!~/+-×÷=♂♀∀#&*@☆○◎◇□△▽♪†‡ΣαβγθφψωДё$()._ "
|
||||
const val KANA = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん" +
|
||||
"アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン"
|
||||
const val SEGA_USERNAME_CAHRS = LETTERS + SYMBOLS + KANA
|
||||
const val SEGA_USERNAME_CHARS = LETTERS + SYMBOLS + KANA
|
||||
const val WACCA_USERNAME_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||||
"abcdefghijklmnopqrstuvwxyz" +
|
||||
"0123456789" +
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package icu.samnyan.aqua.net.games
|
||||
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.Fedy
|
||||
import icu.samnyan.aqua.net.db.AquaNetUser
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.Fedy
|
||||
import icu.samnyan.aqua.net.utils.AquaNetProps
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.context.annotation.Lazy
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.data.repository.NoRepositoryBean
|
||||
import org.springframework.transaction.PlatformTransactionManager
|
||||
import org.springframework.transaction.support.TransactionTemplate
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.writeText
|
||||
import kotlin.reflect.KClass
|
||||
import org.springframework.context.annotation.Lazy
|
||||
|
||||
data class ExportOptions(
|
||||
val playlogAfter: String? = null
|
||||
@@ -42,7 +42,7 @@ interface IExportClass<UserModel: IUserData> {
|
||||
@NoRepositoryBean
|
||||
interface IUserRepo<UserModel, ThisModel>: JpaRepository<ThisModel, Long> {
|
||||
fun findByUser(user: UserModel): List<ThisModel>
|
||||
fun findSingleByUser(user: UserModel): Optional<ThisModel>
|
||||
fun findSingleByUser(user: UserModel): ThisModel?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,14 +81,14 @@ abstract class ImportController<ExportModel: IExportClass<UserModel>, UserModel:
|
||||
val listRepos = exportRepos.filter { it.key returns List::class }
|
||||
val singleRepos = exportRepos.filter { !(it.key returns List::class) }
|
||||
|
||||
fun export(u: AquaNetUser): ExportModel = export(u, ExportOptions())
|
||||
fun export(u: AquaNetUser): ExportModel = export(u.ghostCard, ExportOptions())
|
||||
|
||||
fun export(u: AquaNetUser, options: ExportOptions) = createEmpty().apply {
|
||||
fun export(c: Card, options: ExportOptions) = createEmpty().apply {
|
||||
gameId = game
|
||||
userData = userDataRepo.findByCard(u.ghostCard) ?: (404 - "User not found")
|
||||
userData = userDataRepo.findByCard(c) ?: (404 - "User not found")
|
||||
exportRepos.forEach { (f, u) ->
|
||||
if (f returns List::class) f.set(this, u.findByUser(userData))
|
||||
else u.findSingleByUser(userData)()?.let { f.set(this, it) }
|
||||
else u.findSingleByUser(userData)?.let { f.set(this, it) }
|
||||
}
|
||||
customExporters.forEach { (f, exporter) ->
|
||||
exporter(userData, options)?.let { f.set(this, it) }
|
||||
@@ -147,7 +147,7 @@ abstract class ImportController<ExportModel: IExportClass<UserModel>, UserModel:
|
||||
}
|
||||
}
|
||||
|
||||
Fedy.getGameName(game)?.let { fedy.onImported(it, u.ghostCard.extId) }
|
||||
Fedy.getGameName(game)?.let { fedy.onDataUpdated(u.ghostCard.extId, it, true) }
|
||||
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ data class GenericGameSummary(
|
||||
|
||||
val recent: List<IGenericGamePlaylog>,
|
||||
|
||||
val rival: Boolean?
|
||||
val rival: Boolean?,
|
||||
val favorites: List<Int>?
|
||||
)
|
||||
|
||||
data class GenericRankingPlayer(
|
||||
@@ -124,7 +125,7 @@ open class BaseEntity(
|
||||
@NoRepositoryBean
|
||||
interface GenericUserDataRepo<T : IUserData> : JpaRepository<T, Long> {
|
||||
fun findByCard(card: Card): T?
|
||||
fun findByCard_ExtId(extId: Long): Optional<T>
|
||||
fun findByCard_ExtId(extId: Long): T?
|
||||
|
||||
@Query("select e from #{#entityName} e where e.card.rankingBanned = false")
|
||||
fun findAllNonBanned(): List<T>
|
||||
|
||||
@@ -3,8 +3,11 @@ package icu.samnyan.aqua.net.games.chu3
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.games.*
|
||||
import icu.samnyan.aqua.net.utils.*
|
||||
import icu.samnyan.aqua.sega.chusan.model.*
|
||||
import icu.samnyan.aqua.net.utils.chu3Scores
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3Repos
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserDataRepo
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserMusicDetailRepo
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserPlaylogRepo
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@@ -25,7 +28,7 @@ class Chusan(
|
||||
// Only show > AAA rank
|
||||
override val shownRanks = chu3Scores.filter { it.first >= 95 * 10000 }
|
||||
override val settableFields: Map<String, (Chu3UserData, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CAHRS),
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CHARS),
|
||||
"nameplateId" to { u, v -> u.nameplateId = v.int },
|
||||
"frameId" to { u, v -> u.frameId = v.int },
|
||||
"trophyId" to { u, v -> u.trophyId = v.int },
|
||||
@@ -60,7 +63,9 @@ class Chusan(
|
||||
"new" to (extra["rating_new_list"] ?: ""),
|
||||
)
|
||||
|
||||
genericUserSummary(card, ratingComposition)
|
||||
val misc = rp.userMisc.findByUser_Card_ExtId(card.extId).firstOrNull()
|
||||
|
||||
genericUserSummary(card, ratingComposition, null, misc?.favMusic)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ import icu.samnyan.aqua.sega.maimai2.model.userdata.*
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import kotlin.reflect.full.declaredMembers
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@RestController
|
||||
@API("api/v2/game/mai2")
|
||||
class Mai2Import(
|
||||
@@ -61,7 +62,7 @@ class Mai2Import(
|
||||
}
|
||||
},
|
||||
Maimai2DataExport::userFavoriteMusicList to { user: Mai2UserDetail, _: ExportOptions ->
|
||||
repos.userGeneralData.findByUserAndPropertyKey(user, "favorite_music").orElse(null)
|
||||
repos.userGeneralData.findByUserAndPropertyKey(user, "favorite_music")
|
||||
?.propertyValue
|
||||
?.takeIf { it.isNotEmpty() }
|
||||
?.split(",")
|
||||
@@ -78,7 +79,7 @@ class Mai2Import(
|
||||
if (favoriteMusicList.isNotEmpty()) {
|
||||
val key = "favorite_music"
|
||||
// This field always imports as incremental, since the userGeneralData field (for backwards compatibility) is processed before this
|
||||
val data = repos.userGeneralData.findByUserAndPropertyKey(user, key).orElse(null)
|
||||
val data = repos.userGeneralData.findByUserAndPropertyKey(user, key)
|
||||
?: Mai2UserGeneralData().apply { this.user = user; propertyKey = key }
|
||||
repos.userGeneralData.save(data.apply {
|
||||
propertyValue = favoriteMusicList.sortedBy { it.orderId }.map { it.id }.joinToString(",")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package icu.samnyan.aqua.net.games.mai2
|
||||
|
||||
import ext.*
|
||||
import ext.API
|
||||
import ext.RB
|
||||
import ext.RP
|
||||
import ext.minus
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos
|
||||
@@ -17,24 +20,18 @@ class Mai2MusicDetailImport(
|
||||
@PostMapping("import-music-detail")
|
||||
suspend fun importMusicDetail(@RP token: String, @RB data: List<Mai2UserMusicDetail>) = us.jwt.auth(token) { u ->
|
||||
us.cardByName(u.username) { card ->
|
||||
val user = repos.userData.findByCardExtId(card.extId).orElse(null) ?: (404 - "User not found")
|
||||
val user = repos.userData.findByCardExtId(card.extId) ?: (404 - "User not found")
|
||||
data.forEach { newMusic ->
|
||||
val musicRec = repos.userMusicDetail.findByUserAndMusicIdAndLevel(user, newMusic.musicId, newMusic.level)
|
||||
if (musicRec.isPresent) {
|
||||
val music = musicRec.get()
|
||||
newMusic.user = user
|
||||
repos.userMusicDetail.findByUserAndMusicIdAndLevel(user, newMusic.musicId, newMusic.level)?.let { m ->
|
||||
newMusic.apply {
|
||||
id = music.id
|
||||
this.user = user
|
||||
achievement = achievement.coerceAtLeast(music.achievement)
|
||||
scoreRank = scoreRank.coerceAtLeast(music.scoreRank)
|
||||
comboStatus = comboStatus.coerceAtLeast(music.comboStatus)
|
||||
syncStatus = syncStatus.coerceAtLeast(music.syncStatus)
|
||||
deluxscoreMax = deluxscoreMax.coerceAtLeast(music.deluxscoreMax)
|
||||
playCount = playCount.coerceAtLeast(music.playCount)
|
||||
}
|
||||
} else {
|
||||
newMusic.apply {
|
||||
this.user = user
|
||||
id = m.id
|
||||
achievement = achievement.coerceAtLeast(m.achievement)
|
||||
scoreRank = scoreRank.coerceAtLeast(m.scoreRank)
|
||||
comboStatus = comboStatus.coerceAtLeast(m.comboStatus)
|
||||
syncStatus = syncStatus.coerceAtLeast(m.syncStatus)
|
||||
deluxscoreMax = deluxscoreMax.coerceAtLeast(m.deluxscoreMax)
|
||||
playCount = playCount.coerceAtLeast(m.playCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,19 @@ package icu.samnyan.aqua.net.games.mai2
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.games.*
|
||||
import icu.samnyan.aqua.net.utils.*
|
||||
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||
import icu.samnyan.aqua.net.utils.mai2Scores
|
||||
import icu.samnyan.aqua.sega.maimai2.handler.UploadUserPhotoHandler
|
||||
import icu.samnyan.aqua.sega.maimai2.model.*
|
||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.*
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserDataRepo
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserMusicDetailRepo
|
||||
import icu.samnyan.aqua.sega.maimai2.model.Mai2UserPlaylogRepo
|
||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserDetail
|
||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserGeneralData
|
||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserLoginBonus
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.util.*
|
||||
|
||||
@RestController
|
||||
@API("api/v2/game/mai2")
|
||||
@@ -29,7 +34,7 @@ class Maimai2(
|
||||
// Only show > S rank
|
||||
override val shownRanks = mai2Scores.filter { it.first >= 97 * 10000 }
|
||||
override val settableFields: Map<String, (Mai2UserDetail, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CAHRS),
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CHARS),
|
||||
"iconId" to { u, v -> u.iconId = v.int() },
|
||||
"plateId" to { u, v -> u.plateId = v.int() },
|
||||
"titleId" to { u, v -> u.titleId = v.int() },
|
||||
@@ -58,15 +63,15 @@ class Maimai2(
|
||||
us.jwt.auth(t) { u ->
|
||||
if (u.username == username) return@auth null
|
||||
us.cardByName(u.username) { myCard ->
|
||||
val user = repos.userData.findByCardExtId(card.extId).orElse(null) ?: (404 - "User not found")
|
||||
val myRival = repos.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(myCard.extId, "favorite_rival")
|
||||
.map { it.propertyValue.split(',') }.orElse(emptyList()).filter { it.isNotEmpty() }.map { it.long() }
|
||||
val user = repos.userData.findByCardExtId(card.extId) ?: (404 - "User not found")
|
||||
val myRival = (repos.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(myCard.extId, "favorite_rival")?.propertyValue?.split(',') ?: emptyList())
|
||||
.filter { it.isNotEmpty() }.map { it.long() }
|
||||
myRival.contains(user.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genericUserSummary(card, ratingComposition, isMyRival)
|
||||
genericUserSummary(card, ratingComposition, isMyRival, extra["favorite_music"]?.split(",")?.mapNotNull{it -> it.toIntOrNull()})
|
||||
}
|
||||
|
||||
@API("user-rating")
|
||||
@@ -132,7 +137,7 @@ class Maimai2(
|
||||
if (loginBonus.none { it.bonusId == bonusId }) {
|
||||
// create one
|
||||
val newBonus = Mai2UserLoginBonus().apply {
|
||||
user = repos.userData.findByCardExtId(card.extId).orElse(null) ?: (404 - "User not found")
|
||||
user = repos.userData.findByCardExtId(card.extId) ?: (404 - "User not found")
|
||||
this.bonusId = bonusId
|
||||
isCurrent = true
|
||||
}
|
||||
@@ -154,10 +159,10 @@ class Maimai2(
|
||||
suspend fun setRival(@RP token: String, @RP rivalUserName: String, @RP isAdd: Boolean) = us.jwt.auth(token) { u ->
|
||||
us.cardByName(u.username) { myCard ->
|
||||
val rivalCard = us.cardByName(rivalUserName) { it }
|
||||
val rivalUser = repos.userData.findByCardExtId(rivalCard.extId).orElse(null) ?: (404 - "User not found")
|
||||
val myRival = repos.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(myCard.extId, "favorite_rival").orElse(null)
|
||||
val rivalUser = repos.userData.findByCardExtId(rivalCard.extId) ?: (404 - "User not found")
|
||||
val myRival = repos.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(myCard.extId, "favorite_rival")
|
||||
?: Mai2UserGeneralData().apply {
|
||||
user = repos.userData.findByCardExtId(myCard.extId).orElse(null) ?: (404 - "User not found")
|
||||
user = repos.userData.findByCardExtId(myCard.extId) ?: (404 - "User not found")
|
||||
propertyKey = "favorite_rival"
|
||||
}
|
||||
val myRivalList = myRival.propertyValue.split(',').filter { it.isNotEmpty() }.mut
|
||||
|
||||
@@ -3,7 +3,7 @@ package icu.samnyan.aqua.net.games.ongeki
|
||||
import ext.API
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.games.*
|
||||
import icu.samnyan.aqua.net.utils.*
|
||||
import icu.samnyan.aqua.net.utils.ongekiScores
|
||||
import icu.samnyan.aqua.sega.ongeki.OgkUserDataRepo
|
||||
import icu.samnyan.aqua.sega.ongeki.OgkUserGeneralDataRepo
|
||||
import icu.samnyan.aqua.sega.ongeki.OgkUserMusicDetailRepo
|
||||
@@ -27,7 +27,7 @@ class Ongeki(
|
||||
|
||||
override val shownRanks = ongekiScores.filter { it.first >= 950000 }
|
||||
override val settableFields: Map<String, (UserData, String) -> Unit> by lazy { mapOf(
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CAHRS),
|
||||
"userName" to usernameCheck(SEGA_USERNAME_CHARS),
|
||||
|
||||
"lastRomVersion" to { u, v -> u.lastRomVersion = v },
|
||||
"lastDataVersion" to { u, v -> u.lastDataVersion = v },
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package icu.samnyan.aqua.net.games.wacca
|
||||
|
||||
import ext.*
|
||||
import ext.API
|
||||
import ext.RP
|
||||
import ext.isoDate
|
||||
import ext.utc
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.net.games.*
|
||||
import icu.samnyan.aqua.net.utils.waccaScores
|
||||
@@ -31,7 +34,10 @@ class Wacca(
|
||||
|
||||
override suspend fun userSummary(@RP username: String, @RP token: String?) = us.cardByName(username) { card ->
|
||||
// TODO: Rating composition
|
||||
genericUserSummary(card, mapOf())
|
||||
|
||||
val data = userDataRepo.findByCard_ExtId(card.extId)
|
||||
|
||||
genericUserSummary(card, mapOf(), null, data?.favoriteSongs)
|
||||
}
|
||||
|
||||
override val shownRanks: List<Pair<Int, String>> = waccaScores.filter { it.first > 85 * 10000 }
|
||||
|
||||
@@ -3,10 +3,10 @@ package icu.samnyan.aqua.net.transfer
|
||||
import ext.header
|
||||
import ext.post
|
||||
import ext.request
|
||||
import java.net.URI
|
||||
import icu.samnyan.aqua.sega.aimedb.AimeDbClient
|
||||
import icu.samnyan.aqua.sega.allnet.AllNetBillingDecoder
|
||||
import icu.samnyan.aqua.sega.allnet.AllNetBillingDecoder.decodeAllNetResp
|
||||
import java.net.URI
|
||||
|
||||
val keychipPattern = Regex("([A-Z\\d]{4}-[A-Z\\d]{11}|[A-Z\\d]{11})")
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserItem
|
||||
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserMusicDetail
|
||||
import icu.samnyan.aqua.sega.ongeki.model.OngekiUpsertUserAll
|
||||
import icu.samnyan.aqua.sega.ongeki.model.UserItem
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper
|
||||
import icu.samnyan.aqua.sega.util.jackson.IMapper
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper
|
||||
import icu.samnyan.aqua.sega.util.BasicMapper
|
||||
import icu.samnyan.aqua.sega.util.IMapper
|
||||
import icu.samnyan.aqua.sega.util.StringMapper
|
||||
|
||||
|
||||
abstract class DataBroker(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package icu.samnyan.aqua.sega.aimedb
|
||||
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.BotProps
|
||||
import ext.logger
|
||||
import ext.toHex
|
||||
import icu.samnyan.aqua.net.Fedy
|
||||
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||
import icu.samnyan.aqua.sega.allnet.AllNetProps
|
||||
import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.model.CardStatus
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.ByteBufUtil
|
||||
@@ -26,6 +26,7 @@ class AimeDB(
|
||||
val cardService: CardService,
|
||||
val us: AquaUserServices,
|
||||
val allNetProps: AllNetProps,
|
||||
val fedy: Fedy,
|
||||
): ChannelInboundHandlerAdapter() {
|
||||
val logger = logger()
|
||||
|
||||
@@ -68,9 +69,9 @@ class AimeDB(
|
||||
*/
|
||||
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
|
||||
if (msg !is Map<*, *>) return
|
||||
val type = msg["type"] as Int
|
||||
val data = msg["data"] as ByteBuf
|
||||
try {
|
||||
val type = msg["type"] as Int
|
||||
val data = msg["data"] as ByteBuf
|
||||
val base = data.decodeHeader()
|
||||
val handler = handlers[type] ?: return logger.error("AimeDB: Unknown request type 0x${type.toString(16)}")
|
||||
|
||||
@@ -89,6 +90,7 @@ class AimeDB(
|
||||
|
||||
handler.fn(data)?.let { ctx.write(it) }
|
||||
} finally {
|
||||
data.release()
|
||||
ctx.flush()
|
||||
ctx.close()
|
||||
}
|
||||
@@ -124,7 +126,7 @@ class AimeDB(
|
||||
}
|
||||
}
|
||||
|
||||
fun getCard(accessCode: String) = us.cardRepo.findByLuid(accessCode)()?.maybeGhost()?.let { card ->
|
||||
fun getCard(accessCode: String) = us.cardRepo.findByLuid(accessCode)?.maybeGhost()?.let { card ->
|
||||
// Update card access time and return the extId
|
||||
us.cardRepo.save(card.apply { accessTime = LocalDateTime.now() }).extId
|
||||
} ?: -1
|
||||
@@ -195,11 +197,13 @@ class AimeDB(
|
||||
var status = 0
|
||||
var aimeId = 0L
|
||||
|
||||
if (us.cardRepo.findByLuid(luid).isEmpty) {
|
||||
if (us.cardRepo.findByLuid(luid) == null) {
|
||||
val card: Card = cardService.registerByAccessCode(luid)
|
||||
|
||||
status = 1
|
||||
aimeId = card.extId
|
||||
|
||||
fedy.onCardCreated(luid, card.extId)
|
||||
}
|
||||
else logger.warn("> Duplicated Aime Card Register detected, access code: $luid")
|
||||
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
package icu.samnyan.aqua.sega.aimedb
|
||||
|
||||
import icu.samnyan.aqua.sega.util.ByteBufUtil
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled.copiedBuffer
|
||||
import java.nio.charset.StandardCharsets
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
fun ByteBuf.toBytes(): ByteArray {
|
||||
val readerPos = readerIndex()
|
||||
resetReaderIndex()
|
||||
val result = ByteArray(readableBytes())
|
||||
readBytes(result)
|
||||
readerIndex(readerPos)
|
||||
return result
|
||||
}
|
||||
|
||||
fun ByteBuf.toAllBytes(): ByteArray {
|
||||
val readerPos = readerIndex()
|
||||
resetReaderIndex()
|
||||
writerIndex(capacity())
|
||||
val result = ByteArray(capacity())
|
||||
readBytes(result)
|
||||
readerIndex(readerPos)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@@ -15,7 +33,6 @@ object AimeDbEncryption {
|
||||
val enc = Cipher.getInstance("AES/ECB/NoPadding").apply { init(Cipher.ENCRYPT_MODE, KEY) }
|
||||
val dec = Cipher.getInstance("AES/ECB/NoPadding").apply { init(Cipher.DECRYPT_MODE, KEY) }
|
||||
|
||||
fun decrypt(src: ByteBuf) = copiedBuffer(dec.doFinal(ByteBufUtil.toBytes(src)))
|
||||
|
||||
fun encrypt(src: ByteBuf) = copiedBuffer(enc.doFinal(ByteBufUtil.toAllBytes(src)))
|
||||
fun decrypt(src: ByteBuf) = copiedBuffer(dec.doFinal(src.toBytes()))
|
||||
fun encrypt(src: ByteBuf) = copiedBuffer(enc.doFinal(src.toAllBytes()))
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import io.netty.channel.socket.SocketChannel
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import io.netty.handler.logging.LogLevel
|
||||
import io.netty.handler.logging.LoggingHandler
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@@ -3,7 +3,6 @@ package icu.samnyan.aqua.sega.allnet
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.net.db.AquaNetUserRepo
|
||||
import icu.samnyan.aqua.sega.allnet.AllNetBillingDecoder.decodeAllNet
|
||||
import icu.samnyan.aqua.sega.util.AquaConst
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
@@ -14,7 +13,6 @@ import java.io.InputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "allnet.server")
|
||||
@@ -84,7 +82,7 @@ class AllNet(
|
||||
|
||||
logger.info("AllNet /DownloadOrder : $reqMap")
|
||||
|
||||
val serial = reqMap["serial"] ?: AquaConst.DEFAULT_KEYCHIP_ID
|
||||
val serial = reqMap["serial"] ?: "A69E01A8888"
|
||||
val resp = mapOf(
|
||||
"stat" to "1",
|
||||
"serial" to serial
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker
|
||||
|
||||
import ext.API
|
||||
import ext.logger
|
||||
import ext.long
|
||||
import ext.parsing
|
||||
import icu.samnyan.aqua.sega.allnet.TokenChecker
|
||||
import icu.samnyan.aqua.sega.util.BasicMapper
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.web.bind.annotation.ModelAttribute
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import java.net.InetAddress
|
||||
import java.net.UnknownHostException
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/g/card")
|
||||
class CardMakerController(
|
||||
val mapper: BasicMapper,
|
||||
@param:Value("\${allnet.server.host:}") val ALLNET_HOST: String,
|
||||
@param:Value("\${allnet.server.port:}") val ALLNET_PORT: String,
|
||||
@param:Value("\${server.port:}") val SERVER_PORT: String
|
||||
) {
|
||||
val logger = logger()
|
||||
|
||||
@API("GetGameSettingApi")
|
||||
fun getGameSetting(@ModelAttribute request: MutableMap<String, Any>): Any? {
|
||||
val formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss")
|
||||
val rebootStartTime = LocalDateTime.now().minusHours(3)
|
||||
val rebootEndTime = LocalDateTime.now().minusHours(2)
|
||||
|
||||
val gameSetting = mapOf(
|
||||
"dataVersion" to "1.35.0",
|
||||
"ongekiCmVersion" to "1.32.0",
|
||||
"chuniCmVersion" to "1.30.0",
|
||||
"maimaiCmVersion" to "1.45.0",
|
||||
"isMaintenance" to false,
|
||||
"requestInterval" to 10,
|
||||
"rebootStartTime" to rebootStartTime.format(formatter),
|
||||
"rebootEndTime" to rebootEndTime.format(formatter),
|
||||
"isBackgroundDistribute" to false,
|
||||
"maxCountCharacter" to 100,
|
||||
"maxCountItem" to 100,
|
||||
"maxCountCard" to 100,
|
||||
"watermark" to false
|
||||
)
|
||||
|
||||
val json = mapper.write(mapOf(
|
||||
"gameSetting" to gameSetting,
|
||||
"isDumpUpload" to false,
|
||||
"isAou" to false
|
||||
))
|
||||
|
||||
logger.info("Response: {}", json)
|
||||
return json
|
||||
}
|
||||
|
||||
fun gameConnect(modelKind: Int, modelVersion: Int, url: String) =
|
||||
mapOf("modelKind" to modelKind, "modelVersion" to modelVersion, "url" to url)
|
||||
|
||||
@API("GetGameConnectApi")
|
||||
fun getGameConnect(@ModelAttribute request: MutableMap<String, Any>): Any? {
|
||||
val version = parsing { request["version"]!!.long } // Rom version
|
||||
val session = TokenChecker.Companion.getCurrentSession()
|
||||
|
||||
val addr = ALLNET_HOST.ifBlank { null } ?:
|
||||
try { InetAddress.getLocalHost().hostAddress }
|
||||
catch (_: UnknownHostException) { "localhost" }
|
||||
val port = ALLNET_PORT.ifBlank { null } ?: SERVER_PORT
|
||||
|
||||
val base = if (session == null) "/g" else "/gs/" + session.token
|
||||
val json = mapper.write(mapOf(
|
||||
"length" to 3,
|
||||
"gameConnectList" to listOf(
|
||||
gameConnect(0, 1, "http://$addr:$port$base/chu3/$version/"),
|
||||
gameConnect(1, 1, "http://$addr:$port$base/mai2/"),
|
||||
gameConnect(2, 1, "http://$addr:$port$base/ongeki/")
|
||||
)
|
||||
))
|
||||
|
||||
logger.info("Response: $json")
|
||||
return json
|
||||
}
|
||||
|
||||
@API("GetClientBookkeepingApi")
|
||||
fun getClientBookkeeping(@ModelAttribute request: MutableMap<String, Any>): Any? {
|
||||
val placeId = parsing { request["placeId"]!!.long }
|
||||
val json = mapper.write(mapOf(
|
||||
"placeId" to placeId,
|
||||
"length" to 0,
|
||||
"clientBookkeepingList" to mutableListOf<Any>()
|
||||
))
|
||||
|
||||
logger.info("Response: $json")
|
||||
return json
|
||||
}
|
||||
|
||||
@API("UpsertClientBookkeepingApi")
|
||||
fun upsertClientBookkeeping() = "{\"returnCode\":1,\"apiName\":\"UpsertClientBookkeepingApi\"}"
|
||||
|
||||
@API("UpsertClientSettingApi")
|
||||
fun upsertClientSetting() = "{\"returnCode\":1,\"apiName\":\"UpsertClientSettingApi\"}"
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import ext.logger
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.web.bind.annotation.ModelAttribute
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestControllerAdvice(basePackages = ["icu.samnyan.aqua.sega.cardmaker"])
|
||||
class CardMakerControllerAdvice {
|
||||
val logger = logger()
|
||||
val mapper = ObjectMapper()
|
||||
|
||||
/**
|
||||
* Get the map object from json string
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
*/
|
||||
@ModelAttribute
|
||||
fun preHandle(request: HttpServletRequest): MutableMap<String, Any> {
|
||||
val src = request.inputStream.readAllBytes()
|
||||
val outputString = String(src, StandardCharsets.UTF_8).trim { it <= ' ' }
|
||||
logger.info("Request ${request.requestURI}: $outputString")
|
||||
return mapper.readValue(outputString, object : TypeReference<MutableMap<String, Any>>() {})
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.controller;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.cardmaker.handler.impl.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/g/card")
|
||||
public class CardMakerController {
|
||||
private final GetGameSettingHandler getGameSettingHandler;
|
||||
private final GetClientBookkeepingHandler getClientBookkeepingHandler;
|
||||
private final GetGameConnectHandler getGameConnectHandler;
|
||||
|
||||
@Autowired
|
||||
public CardMakerController(GetGameSettingHandler getGameSettingHandler, GetClientBookkeepingHandler getClientBookkeepingHandler, GetGameConnectHandler getGameConnectHandler) {
|
||||
this.getGameSettingHandler = getGameSettingHandler;
|
||||
this.getClientBookkeepingHandler = getClientBookkeepingHandler;
|
||||
this.getGameConnectHandler = getGameConnectHandler;
|
||||
}
|
||||
|
||||
@PostMapping("GetGameSettingApi")
|
||||
public String getGameSetting(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameSettingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameConnectApi")
|
||||
public String getGameConnect(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameConnectHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetClientBookkeepingApi")
|
||||
public String getClientBookkeeping(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getClientBookkeepingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientBookkeepingApi")
|
||||
public String upsertClientBookkeeping(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":1,\"apiName\":\"UpsertClientBookkeepingApi\"}";
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientSettingApi")
|
||||
public String upsertClientSetting(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":1,\"apiName\":\"UpsertClientSettingApi\"}";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestControllerAdvice(basePackages = "icu.samnyan.aqua.sega.cardmaker")
|
||||
public class CardMakerControllerAdvice {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CardMakerControllerAdvice.class);
|
||||
|
||||
|
||||
/**
|
||||
* Get the map object from json string
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
*/
|
||||
@ModelAttribute
|
||||
public Map<String, Object> preHandle(HttpServletRequest request) throws IOException {
|
||||
byte[] src = request.getInputStream().readAllBytes();
|
||||
String outputString = new String(src, StandardCharsets.UTF_8).trim();
|
||||
logger.info("Request " + request.getRequestURI() + ": " + outputString);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
return mapper.readValue(outputString, new TypeReference<>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component("CardMakerGetClientBookkeepingHandler")
|
||||
public class GetClientBookkeepingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetClientBookkeepingHandler.class);
|
||||
|
||||
private final BasicMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetClientBookkeepingHandler(BasicMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
long placeId = ((Number) request.get("placeId")).longValue();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("placeId", placeId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("clientBookkeepingList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.allnet.KeychipSession;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.cardmaker.model.response.data.GameConnect;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import icu.samnyan.aqua.sega.allnet.TokenChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component("CardMakerGetGameConnectHandler")
|
||||
public class GetGameConnectHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameConnectHandler.class);
|
||||
|
||||
private final BasicMapper mapper;
|
||||
private final String ALLNET_HOST;
|
||||
private final String ALLNET_PORT;
|
||||
private final String SERVER_PORT;
|
||||
|
||||
@Autowired
|
||||
public GetGameConnectHandler(BasicMapper mapper, @Value("${allnet.server.host:}") String ALLNET_HOST,
|
||||
@Value("${allnet.server.port:}") String ALLNET_PORT, @Value("${server.port:}") String SERVER_PORT) {
|
||||
this.mapper = mapper;
|
||||
this.ALLNET_HOST = ALLNET_HOST;
|
||||
this.ALLNET_PORT = ALLNET_PORT;
|
||||
this.SERVER_PORT = SERVER_PORT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
int type = ((Number) request.get("type")).intValue(); // Allnet enabled or not
|
||||
long version = ((Number) request.get("version")).longValue(); // Rom version
|
||||
KeychipSession session = TokenChecker.Companion.getCurrentSession();
|
||||
|
||||
// Unless ip and port is explicitly overridden, use the guessed ip and port as same as AllNet Controller does.
|
||||
String localAddr;
|
||||
try {
|
||||
localAddr = InetAddress.getLocalHost().getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
// If above didn't work then how did this run? I really don't know.
|
||||
localAddr = "localhost";
|
||||
}
|
||||
|
||||
String addr = ALLNET_HOST.equals("") ? localAddr : ALLNET_HOST;
|
||||
String port = ALLNET_PORT.equals("") ? SERVER_PORT : ALLNET_PORT;
|
||||
|
||||
String base = session == null ? "/g" : "/gs/" + session.getToken();
|
||||
List<GameConnect> gameConnectList = new ArrayList<>();
|
||||
GameConnect chuni = new GameConnect(0, 1, "http://" + addr + ":" + port + base + "/chu3/" + version + "/");
|
||||
GameConnect mai = new GameConnect(1, 1, "http://" + addr + ":" + port + base + "/mai2/");
|
||||
GameConnect ongeki = new GameConnect(2, 1, "http://" + addr + ":" + port + base + "/ongeki/");
|
||||
gameConnectList.add(chuni);
|
||||
gameConnectList.add(mai);
|
||||
gameConnectList.add(ongeki);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("length", gameConnectList.size());
|
||||
resultMap.put("gameConnectList", gameConnectList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.cardmaker.model.response.GetGameSettingResp;
|
||||
import icu.samnyan.aqua.sega.cardmaker.model.response.data.GameSetting;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component("CardMakerGetGameSettingHandler")
|
||||
public class GetGameSettingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameSettingHandler.class);
|
||||
|
||||
private final BasicMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameSettingHandler(BasicMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(@NotNull Map<String, ?> request) throws JsonProcessingException {
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
|
||||
LocalDateTime rebootStartTime = LocalDateTime.now().minusHours(3);
|
||||
LocalDateTime rebootEndTime = LocalDateTime.now().minusHours(2);
|
||||
|
||||
GameSetting gameSetting = new GameSetting(
|
||||
"1.35.0",
|
||||
"1.32.0",
|
||||
"1.30.0",
|
||||
"1.45.0",
|
||||
false,
|
||||
10,
|
||||
rebootStartTime.format(formatter),
|
||||
rebootEndTime.format(formatter),
|
||||
false,
|
||||
100,
|
||||
100,
|
||||
100,
|
||||
false);
|
||||
|
||||
GetGameSettingResp resp = new GetGameSettingResp(
|
||||
gameSetting,
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
String json = mapper.write(resp);
|
||||
|
||||
logger.info("Response: {}", json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.model.response;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CodeResp {
|
||||
private int returnCode;
|
||||
private String apiName;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.model.response;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import icu.samnyan.aqua.sega.cardmaker.model.response.data.GameSetting;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GetGameSettingResp {
|
||||
private GameSetting gameSetting;
|
||||
@JsonProperty("isDumpUpload")
|
||||
private boolean isDumpUpload;
|
||||
@JsonProperty("isAou")
|
||||
private boolean isAou;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.model.response.data;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GameConnect {
|
||||
private int modelKind; // 0: chunithm, 1: maimai, 2: ongeki
|
||||
private int type; // 0: LAN, 1: WAN
|
||||
private String titleUri;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.cardmaker.model.response.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GameSetting {
|
||||
private String dataVersion;
|
||||
private String ongekiCmVersion;
|
||||
private String chuniCmVersion;
|
||||
private String maimaiCmVersion;
|
||||
@JsonProperty("isMaintenance")
|
||||
private boolean isMaintenance;
|
||||
private int requestInterval;
|
||||
private String rebootStartTime;
|
||||
private String rebootEndTime;
|
||||
@JsonProperty("isBackgroundDistribute")
|
||||
private boolean isBackgroundDistribute;
|
||||
private int maxCountCharacter;
|
||||
private int maxCountItem;
|
||||
private int maxCountCard;
|
||||
private boolean watermark;
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.controller;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.chunithm.handler.impl.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/g/chu2/{ROM_VERSION}/{CLIENT_ID}/ChuniServlet")
|
||||
@AllArgsConstructor
|
||||
public class ChuniServletController {
|
||||
|
||||
private final GameLoginHandler gameLoginHandler;
|
||||
private final GameLogoutHandler gameLogoutHandler;
|
||||
private final GetGameChargeHandler getGameChargeHandler;
|
||||
private final GetGameEventHandler getGameEventHandler;
|
||||
private final GetGameIdlistHandler getGameIdlistHandler;
|
||||
private final GetGameMessageHandler getGameMessageHandler;
|
||||
private final GetGameRankingHandler getGameRankingHandler;
|
||||
private final GetGameSaleHandler getGameSaleHandler;
|
||||
private final GetGameSettingHandler getGameSettingHandler;
|
||||
private final GetTeamCourseRuleHandler getTeamCourseRuleHandler;
|
||||
private final GetTeamCourseSettingHandler getTeamCourseSettingHandler;
|
||||
private final GetUserActivityHandler getUserActivityHandler;
|
||||
private final GetUserCharacterHandler getUserCharacterHandler;
|
||||
private final GetUserChargeHandler getUserChargeHandler;
|
||||
private final GetUserCourseHandler getUserCourseHandler;
|
||||
private final GetUserDataExHandler getUserDataExHandler;
|
||||
private final GetUserDataHandler getUserDataHandler;
|
||||
private final GetUserDuelHandler getUserDuelHandler;
|
||||
private final GetUserFavoriteItemHandler getUserFavoriteItemHandler;
|
||||
private final GetUserFavoriteMusicHandler getUserFavoriteMusicHandler;
|
||||
private final GetUserItemHandler getUserItemHandler;
|
||||
private final GetUserLoginBonusHandler getUserLoginBonusHandler;
|
||||
private final GetUserMapHandler getUserMapHandler;
|
||||
private final GetUserMusicHandler getUserMusicHandler;
|
||||
private final GetUserOptionExHandler getUserOptionExHandler;
|
||||
private final GetUserOptionHandler getUserOptionHandler;
|
||||
private final GetUserPreviewHandler getUserPreviewHandler;
|
||||
private final GetUserRecentRatingHandler getUserRecentRatingHandler;
|
||||
private final GetUserRegionHandler getUserRegionHandler;
|
||||
private final GetUserRivalDataHandler getUserRivalDataHandler;
|
||||
private final GetUserRivalMusicHandler getUserRivalMusicHandler;
|
||||
private final GetUserTeamHandler getUserTeamHandler;
|
||||
private final UpsertClientSettingHandler upsertClientSettingHandler;
|
||||
private final UpsertUserAllHandler upsertUserAllHandler;
|
||||
private final UpsertUserChargelogHandler upsertUserChargelogHandler;
|
||||
|
||||
|
||||
@PostMapping("GameLoginApi")
|
||||
String gameLogin(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return gameLoginHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GameLogoutApi")
|
||||
String gameLogout(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return gameLogoutHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameChargeApi")
|
||||
String getGameCharge(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameChargeHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameEventApi")
|
||||
String getGameEvent(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameEventHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameIdlistApi")
|
||||
String getGameIdList(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameIdlistHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameMessageApi")
|
||||
String getGameMessage(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameMessageHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameRankingApi")
|
||||
String getGameRanking(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameRankingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetGameSaleApi")
|
||||
String getGameSale(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameSaleHandler.handle(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* The game start up request
|
||||
*
|
||||
* @return json of GameSetting object
|
||||
*/
|
||||
@PostMapping("GetGameSettingApi")
|
||||
String getGameSetting(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getGameSettingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetTeamCourseRuleApi")
|
||||
String getTeamCourseRule(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getTeamCourseRuleHandler.handle(request);
|
||||
}
|
||||
@PostMapping("GetTeamCourseSettingApi")
|
||||
String getTeamCourseSetting(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getTeamCourseSettingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserActivityApi")
|
||||
String getUserActivity(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserActivityHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserCharacterApi")
|
||||
String getUserCharacter(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserCharacterHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserChargeApi")
|
||||
String getUserCharge(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserChargeHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserCourseApi")
|
||||
String getUserCourse(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserCourseHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserDataApi")
|
||||
String getUserData(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserDataHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserDataExApi")
|
||||
String getUserDataEx(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserDataExHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserDuelApi")
|
||||
String getUserDuel(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserDuelHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserFavoriteItemApi")
|
||||
String getUserFavoriteItem(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserFavoriteItemHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserFavoriteMusicApi")
|
||||
public String getUserFavoriteMusic(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserFavoriteMusicHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserItemApi")
|
||||
String getUserItem(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserItemHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserLoginBonusApi")
|
||||
String getUserLoginBonus(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserLoginBonusHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserMapApi")
|
||||
String getUserMap(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserMapHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserMusicApi")
|
||||
String getUserMusic(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserMusicHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserOptionApi")
|
||||
String getUserOption(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserOptionHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserOptionExApi")
|
||||
String getUserOptionEx(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserOptionExHandler.handle(request);
|
||||
}
|
||||
|
||||
// Call when login. Return null if no profile exist
|
||||
@PostMapping("GetUserPreviewApi")
|
||||
String getUserPreview(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserPreviewHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserRecentRatingApi")
|
||||
String getUserRecentRating(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserRecentRatingHandler.handle(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* For older version chunithm
|
||||
*/
|
||||
@PostMapping("GetUserRecentPlayerApi")
|
||||
String getUserRecentPlayerApi(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserRecentRatingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserRegionApi")
|
||||
String getUserRegion(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserRegionHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserRivalDataApi")
|
||||
String getUserRivalData(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserRivalDataHandler.handle(request);
|
||||
}
|
||||
@PostMapping("GetUserRivalMusicApi")
|
||||
String getUserRivalMusic(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserRivalMusicHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("GetUserTeamApi")
|
||||
String getUserTeam(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return getUserTeamHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientBookkeepingApi")
|
||||
String upsertClientBookkeeping(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":\"1\"}";
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientDevelopApi")
|
||||
String upsertClientDevelop(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":\"1\"}";
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientErrorApi")
|
||||
String upsertClientError(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":\"1\"}";
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientSettingApi")
|
||||
String upsertClientSetting(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return upsertClientSettingHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("UpsertClientTestmodeApi")
|
||||
String upsertClientTestmode(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":\"1\"}";
|
||||
}
|
||||
|
||||
@PostMapping("UpsertUserAllApi")
|
||||
String upsertUserAll(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return upsertUserAllHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("UpsertUserChargelogApi")
|
||||
String upsertUserChargelog(@ModelAttribute Map<String, Object> request) throws JsonProcessingException {
|
||||
return upsertUserChargelogHandler.handle(request);
|
||||
}
|
||||
|
||||
@PostMapping("Ping")
|
||||
String ping(@ModelAttribute Map<String, Object> request) {
|
||||
return "{\"returnCode\":\"1\"}";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.controller;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import static icu.samnyan.aqua.sega.util.AquaConst.*;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@RestControllerAdvice(basePackages = "icu.samnyan.aqua.sega.chunithm")
|
||||
public class ChuniServletControllerAdvice {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ChuniServletControllerAdvice.class);
|
||||
|
||||
|
||||
/**
|
||||
* Get the map object from json string
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
*/
|
||||
@ModelAttribute
|
||||
public Map<String, Object> preHandle(HttpServletRequest request) throws IOException {
|
||||
var pathVar = (Map<String, String>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
|
||||
byte[] src = request.getInputStream().readAllBytes();
|
||||
String outputString = new String(src, StandardCharsets.UTF_8).trim();
|
||||
logger.info("Request " + request.getRequestURI() + ": " + outputString);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
Map<String, Object> result = mapper.readValue(outputString, new TypeReference<>() {
|
||||
});
|
||||
result.put(SERIAL_KEY, pathVar.getOrDefault(SERIAL_KEY, DEFAULT_KEYCHIP_ID));
|
||||
result.put(VERSION_KEY, pathVar.getOrDefault(VERSION_KEY, CHUNI_DEFAULT_VERSION));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.Character;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameCharacterRepository")
|
||||
public interface GameCharacterRepository extends JpaRepository<Character, Long> {
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.CharacterSkill;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameCharacterSkillRepository")
|
||||
public interface GameCharacterSkillRepository extends JpaRepository<CharacterSkill, Long> {
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameCharge;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameChargeRepository")
|
||||
public interface GameChargeRepository extends JpaRepository<GameCharge, Long> {
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameEvent;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameEventRepository")
|
||||
public interface GameEventRepository extends JpaRepository<GameEvent, Integer> {
|
||||
|
||||
List<GameEvent> findByEnable(boolean enable);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameMessage;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameMessageRepository")
|
||||
public interface GameMessageRepository extends JpaRepository<GameMessage, Integer> {
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.gamedata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.Music;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniGameMusicRepository")
|
||||
public interface GameMusicRepository extends JpaRepository<Music, Long> {
|
||||
|
||||
Optional<Music> findByMusicId(int musicId);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserActivity;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserActivityRepository extends JpaRepository<UserActivity, Long> {
|
||||
|
||||
Optional<UserActivity> findTopByUserAndActivityIdAndKindOrderByIdDesc(UserData user, int activityId, int kind);
|
||||
|
||||
List<UserActivity> findAllByUser_Card_ExtIdAndKindOrderBySortNumberDesc(Long extId, int kind);
|
||||
|
||||
List<UserActivity> findAllByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharacter;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserCharacterRepository extends JpaRepository<UserCharacter, Long> {
|
||||
|
||||
Page<UserCharacter> findByUser_Card_ExtId(Long extId, Pageable pageable);
|
||||
|
||||
List<UserCharacter> findByUser_Card_ExtId(Long extId);
|
||||
|
||||
Optional<UserCharacter> findTopByUserAndCharacterIdOrderByIdDesc(UserData user, int characterId);
|
||||
|
||||
Optional<UserCharacter> findByUser_Card_ExtIdAndCharacterId(Long extId, int characterId);
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharge;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserChargeRepository extends JpaRepository<UserCharge, Long> {
|
||||
List<UserCharge> findByUser_Card_ExtId(Long extId);
|
||||
|
||||
Optional<UserCharge> findByUserAndChargeId(UserData extId, int chargeId);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCourse;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserCourseRepository extends JpaRepository<UserCourse, Long> {
|
||||
Optional<UserCourse> findTopByUserAndCourseIdOrderByIdDesc(UserData user, int courseId);
|
||||
|
||||
Page<UserCourse> findByUser_Card_ExtId(Long extId, Pageable page);
|
||||
|
||||
List<UserCourse> findByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserDataEx;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserDataExRepository extends JpaRepository<UserDataEx, Long> {
|
||||
|
||||
Optional<UserDataEx> findByUser(UserData user);
|
||||
|
||||
Optional<UserDataEx> findByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.general.model.Card;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserDataRepository extends JpaRepository<UserData, Long> {
|
||||
|
||||
Optional<UserData> findByCard(Card card);
|
||||
|
||||
Optional<UserData> findByCard_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserDuel;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserDuelRepository extends JpaRepository<UserDuel, Long> {
|
||||
|
||||
Optional<UserDuel> findTopByUserAndDuelIdOrderByIdDesc(UserData user, int duelId);
|
||||
|
||||
List<UserDuel> findByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOptionEx;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserGameOptionExRepository extends JpaRepository<UserGameOptionEx, Long> {
|
||||
Optional<UserGameOptionEx> findByUser(UserData user);
|
||||
|
||||
Optional<UserGameOptionEx> findByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOption;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserGameOptionRepository extends JpaRepository<UserGameOption, Long> {
|
||||
|
||||
Optional<UserGameOption> findByUser(UserData user);
|
||||
|
||||
Optional<UserGameOption> findByUser_Card_ExtId(Long extId);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGeneralData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository("ChuniUserGeneralDataRepository")
|
||||
public interface UserGeneralDataRepository extends JpaRepository<UserGeneralData, Long> {
|
||||
|
||||
Optional<UserGeneralData> findByUserAndPropertyKey(UserData user, String key);
|
||||
|
||||
Optional<UserGeneralData> findByUser_Card_ExtIdAndPropertyKey(Long extId, String key);
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserItem;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserItemRepository extends JpaRepository<UserItem, Long> {
|
||||
|
||||
Optional<UserItem> findTopByUserAndItemIdAndItemKindOrderByIdDesc(UserData user, int itemId, int itemKind);
|
||||
|
||||
Page<UserItem> findAllByUser_Card_ExtIdAndItemKind(Long extId, int itemKind, Pageable pageable);
|
||||
|
||||
List<UserItem> findAllByUser_Card_ExtId(Long extId);
|
||||
|
||||
Page<UserItem> findByUser_Card_ExtId(Long extId, Pageable pageable);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMap;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserMapRepository extends JpaRepository<UserMap, Long> {
|
||||
List<UserMap> findAllByUser(UserData user);
|
||||
|
||||
List<UserMap> findAllByUser_Card_ExtId(Long extId);
|
||||
|
||||
Optional<UserMap> findTopByUserAndMapIdOrderByIdDesc(UserData user, int mapId);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMusicDetail;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserMusicDetailRepository extends JpaRepository<UserMusicDetail, Long> {
|
||||
|
||||
Optional<UserMusicDetail> findTopByUserAndMusicIdAndLevelOrderByIdDesc(UserData user, int musicId, int level);
|
||||
|
||||
List<UserMusicDetail> findByUser_Card_ExtId(Long extId);
|
||||
|
||||
List<UserMusicDetail> findByUser_Card_ExtIdAndMusicId(Long extId, int musicId);
|
||||
|
||||
Page<UserMusicDetail> findByUser_Card_ExtId(Long extId, Pageable page);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.dao.userdata;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.GameRanking;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserPlaylog;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Repository
|
||||
public interface UserPlaylogRepository extends JpaRepository<UserPlaylog, Long> {
|
||||
List<UserPlaylog> findByUser_Card_ExtIdAndLevelNot(Long extId, int levelNot, Pageable page);
|
||||
|
||||
Page<UserPlaylog> findByUser_Card_ExtId(Long extId, Pageable page);
|
||||
|
||||
List<UserPlaylog> findByUser_Card_ExtIdAndMusicIdAndLevel(Long extId, int musicId, int level);
|
||||
|
||||
List<UserPlaylog> findByUser_Card_ExtId(Long extId);
|
||||
|
||||
@Query("SELECT NEW icu.samnyan.aqua.sega.chunithm.model.response.data.GameRanking(c.musicId, COUNT(c.musicId)) FROM ChuniUserPlaylog c WHERE NOT c.level = 4 GROUP BY c.musicId ORDER BY COUNT(c.musicId) DESC")
|
||||
Page<GameRanking> findGameRankingByPlaylog(Pageable page);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.CodeResp;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GameLoginHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GameLoginHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserDataService userDataService;
|
||||
|
||||
public GameLoginHandler(StringMapper mapper, UserDataService userDataService) {
|
||||
this.mapper = mapper;
|
||||
this.userDataService = userDataService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Optional<UserData> userDataOptional = userDataService.getUserByExtId(userId);
|
||||
userDataOptional.ifPresent(userDataService::updateLoginTime);
|
||||
|
||||
String json = mapper.write(new CodeResp(1));
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.CodeResp;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GameLogoutHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GameLogoutHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
public GameLogoutHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
|
||||
String json = mapper.write(new CodeResp(1));
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.chunithm.dao.gamedata.GameChargeRepository;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameCharge;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameChargeHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameChargeHandler.class);
|
||||
private final GameChargeRepository gameChargeRepository;
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameChargeHandler(GameChargeRepository gameChargeRepository, StringMapper mapper) {
|
||||
this.gameChargeRepository = gameChargeRepository;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
|
||||
List<GameCharge> gameChargeList = gameChargeRepository.findAll();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("length", gameChargeList.size());
|
||||
resultMap.put("gameChargeList", gameChargeList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.chunithm.dao.gamedata.GameEventRepository;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameEvent;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameEventHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameEventHandler.class);
|
||||
|
||||
private final GameEventRepository gameEventRepository;
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameEventHandler(GameEventRepository gameEventRepository, StringMapper mapper) {
|
||||
this.gameEventRepository = gameEventRepository;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String type = (String) request.get("type");
|
||||
|
||||
List<GameEvent> gameEventList = gameEventRepository.findByEnable(true);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("type", type);
|
||||
resultMap.put("length", gameEventList.size());
|
||||
resultMap.put("gameEventList", gameEventList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameIdlistHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameIdlistHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameIdlistHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String type = (String) request.get("type");
|
||||
|
||||
List<Object> gameIdlistList = new ArrayList<>();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("type", type);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("gameIdlistList", gameIdlistList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.chunithm.dao.gamedata.GameMessageRepository;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.gamedata.GameMessage;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameMessageHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameMessageHandler.class);
|
||||
|
||||
private final GameMessageRepository gameMessageRepository;
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameMessageHandler(GameMessageRepository gameMessageRepository, StringMapper mapper) {
|
||||
this.gameMessageRepository = gameMessageRepository;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String type = (String) request.get("type");
|
||||
|
||||
List<GameMessage> gameMessageList = gameMessageRepository.findAll();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("type", type);
|
||||
resultMap.put("length", gameMessageList.size());
|
||||
resultMap.put("gameMessageList", gameMessageList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import icu.samnyan.aqua.sega.chunithm.dao.userdata.UserPlaylogRepository;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.GameRanking;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameRankingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameRankingHandler.class);
|
||||
|
||||
private final UserPlaylogRepository userPlaylogRepository;
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameRankingHandler(StringMapper mapper, UserPlaylogRepository userPlaylogRepository) {
|
||||
this.userPlaylogRepository = userPlaylogRepository;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String type = (String) request.get("type");
|
||||
|
||||
Page<GameRanking> rankingPage = userPlaylogRepository.findGameRankingByPlaylog(PageRequest.of(0, 10));
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("type", type);
|
||||
resultMap.put("gameRankingList", rankingPage.getContent());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.GameSale;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameSaleHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameSaleHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameSaleHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String type = (String) request.get("type");
|
||||
|
||||
List<GameSale> gameSaleList = new ArrayList<>();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("type", type);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("gameSaleList", gameSaleList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.GetGameSettingResp;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.GameSetting;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetGameSettingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetGameSettingHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetGameSettingHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
|
||||
// Fixed reboot time triggers chunithm maintenance lockout, so let's try minime method which sets it dynamically
|
||||
// Special thanks to skogaby
|
||||
|
||||
// Hardcode so that the reboot time always started 3 hours ago and ended 2 hours ago
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
|
||||
LocalDateTime rebootStartTime = LocalDateTime.now().minusHours(3);
|
||||
LocalDateTime rebootEndTime = LocalDateTime.now().minusHours(2);
|
||||
|
||||
GameSetting gameSetting = new GameSetting(
|
||||
1,
|
||||
false,
|
||||
10,
|
||||
rebootStartTime.format(formatter),
|
||||
rebootEndTime.format(formatter),
|
||||
false,
|
||||
300,
|
||||
300,
|
||||
300);
|
||||
|
||||
GetGameSettingResp resp = new GetGameSettingResp(
|
||||
gameSetting,
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
String json = mapper.write(resp);
|
||||
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.CodeResp;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.GameSale;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class GetTeamCourseRuleHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetTeamCourseRuleHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
|
||||
public GetTeamCourseRuleHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("nextIndex", 0);
|
||||
resultMap.put("teamCourseRuleList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GetTeamCourseSettingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetTeamCourseSettingHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
|
||||
public GetTeamCourseSettingHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("nextIndex", 0);
|
||||
resultMap.put("teamCourseSettingList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserActivity;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserActivityService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserActivityHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserActivityHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserActivityService userActivityService;
|
||||
|
||||
@Autowired
|
||||
public GetUserActivityHandler(StringMapper mapper, UserActivityService userActivityService) {
|
||||
this.mapper = mapper;
|
||||
this.userActivityService = userActivityService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
String kind = (String) request.get("kind");
|
||||
|
||||
List<UserActivity> userActivityList = userActivityService.getAllByUserIdAndKind(userId, kind);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userActivityList.size());
|
||||
resultMap.put("kind", kind);
|
||||
resultMap.put("userActivityList", userActivityList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharacter;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserCharacterService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle getUserCharacter request
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserCharacterHandler implements BaseHandler {
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserCharacterHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserCharacterService userCharacterService;
|
||||
|
||||
|
||||
@Autowired
|
||||
public GetUserCharacterHandler(StringMapper mapper, UserCharacterService userCharacterService) {
|
||||
this.mapper = mapper;
|
||||
this.userCharacterService = userCharacterService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
int nextIndex = Integer.parseInt((String) request.get("nextIndex"));
|
||||
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
||||
|
||||
int pageNum = nextIndex / maxCount;
|
||||
|
||||
Page<UserCharacter> dbPage = userCharacterService.getByUserId(userId, pageNum, maxCount);
|
||||
|
||||
long currentIndex = maxCount * pageNum + dbPage.getNumberOfElements();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", dbPage.getNumberOfElements());
|
||||
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : currentIndex);
|
||||
resultMap.put("userCharacterList", dbPage.getContent());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharge;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserChargeService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserChargeHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserChargeHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserChargeService userChargeService;
|
||||
|
||||
@Autowired
|
||||
public GetUserChargeHandler(StringMapper mapper, UserChargeService userChargeService) {
|
||||
this.mapper = mapper;
|
||||
this.userChargeService = userChargeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
List<UserCharge> userChargeList = userChargeService.getByUserId(userId);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userChargeList.size());
|
||||
resultMap.put("userChargeList", userChargeList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCourse;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserCourseService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle GetUserCourse request
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserCourseHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserCourseHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserCourseService userCourseService;
|
||||
|
||||
@Autowired
|
||||
public GetUserCourseHandler(StringMapper mapper, UserCourseService userCourseService) {
|
||||
this.mapper = mapper;
|
||||
this.userCourseService = userCourseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
|
||||
if(request.containsKey("nextIndex")) {
|
||||
int nextIndex = Integer.parseInt((String) request.get("nextIndex"));
|
||||
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
||||
|
||||
int pageNum = nextIndex / maxCount;
|
||||
|
||||
Page<UserCourse> dbPage = userCourseService.getByUserId(userId, pageNum, maxCount);
|
||||
|
||||
long currentIndex = maxCount * pageNum + dbPage.getNumberOfElements();
|
||||
|
||||
resultMap.put("length", dbPage.getNumberOfElements());
|
||||
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : currentIndex);
|
||||
resultMap.put("userCourseList", dbPage.getContent());
|
||||
} else {
|
||||
List<UserCourse> courseList = userCourseService.getByUserId(userId);
|
||||
resultMap.put("length", courseList.size());
|
||||
resultMap.put("userCourseList", courseList);
|
||||
}
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserDataEx;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDataExService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserDataExHandler implements BaseHandler {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserDataExHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserDataExService userDataExService;
|
||||
|
||||
@Autowired
|
||||
public GetUserDataExHandler(StringMapper mapper, UserDataExService userDataExService) {
|
||||
this.mapper = mapper;
|
||||
this.userDataExService = userDataExService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Optional<UserDataEx> userDataExOptional = userDataExService.getByExtId(userId);
|
||||
|
||||
if (userDataExOptional.isPresent()) {
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("userDataEx", userDataExOptional.get());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.general.service.ClientSettingService;
|
||||
import icu.samnyan.aqua.sega.util.VersionUtil;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static icu.samnyan.aqua.sega.util.AquaConst.SERIAL_KEY;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserDataHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserDataHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final ClientSettingService clientSettingService;
|
||||
|
||||
private final UserDataService userDataService;
|
||||
|
||||
@Autowired
|
||||
public GetUserDataHandler(StringMapper mapper,
|
||||
ClientSettingService clientSettingService, UserDataService userDataService
|
||||
) {
|
||||
this.mapper = mapper;
|
||||
this.clientSettingService = clientSettingService;
|
||||
this.userDataService = userDataService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Optional<UserData> userDataOptional = userDataService.getUserByExtId(userId);
|
||||
|
||||
if (userDataOptional.isPresent()) {
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
UserData user = userDataOptional.get();
|
||||
|
||||
var vo = clientSettingService.getSetting((String) request.get(SERIAL_KEY));
|
||||
if (vo.isPresent()) {
|
||||
var version = vo.get();
|
||||
user.setLastRomVersion(VersionUtil.getTargetVersion(user.getLastRomVersion(), version.getRomVersion()));
|
||||
user.setLastDataVersion(VersionUtil.getTargetVersion(user.getLastDataVersion(), version.getDataVersion()));
|
||||
}
|
||||
|
||||
resultMap.put("userData", user);
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserDuel;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDuelService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle GetUserDuel request
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserDuelHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserDuelHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserDuelService userDuelService;
|
||||
|
||||
@Autowired
|
||||
public GetUserDuelHandler(StringMapper mapper, UserDuelService userDuelService) {
|
||||
this.mapper = mapper;
|
||||
this.userDuelService = userDuelService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
String duelId = (String) request.get("duelId");
|
||||
String isAllDuel = (String) request.get("isAllDuel");
|
||||
|
||||
// TODO:
|
||||
|
||||
List<UserDuel> userDuelList = userDuelService.getByUserId(userId);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userDuelList.size());
|
||||
resultMap.put("userDuelList", userDuelList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle GetUserFavoriteItem request
|
||||
* @author yueou (yueou.xu@gmail.com)
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class GetUserFavoriteItemHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserFavoriteItemHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetUserFavoriteItemHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
String kind = (String) request.get("kind");
|
||||
|
||||
// TODO:
|
||||
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("kind", kind);
|
||||
resultMap.put("nextIndex", -1);
|
||||
resultMap.put("userFavoriteItemList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserDuel;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDuelService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle GetUserDuel request
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserFavoriteMusicHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserFavoriteMusicHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetUserFavoriteMusicHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
// TODO:
|
||||
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("userFavoriteMusicList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserItem;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserItemService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handler for getting user item.
|
||||
* This get call before profile create.
|
||||
*
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserItemHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserItemHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserItemService userItemService;
|
||||
|
||||
public GetUserItemHandler(StringMapper mapper, UserItemService userItemService) {
|
||||
this.mapper = mapper;
|
||||
this.userItemService = userItemService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Long nextIndexVal = Long.parseLong((String) request.get("nextIndex"));
|
||||
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
||||
|
||||
Long mul = 10000000000L;
|
||||
|
||||
int kind = (int) (nextIndexVal / mul);
|
||||
int nextIndex = (int) (nextIndexVal % mul);
|
||||
int pageNum = nextIndex / maxCount;
|
||||
|
||||
Page<UserItem> userItemPage = userItemService.getByUserAndItemKind(userId, kind, pageNum, maxCount);
|
||||
|
||||
List<UserItem> userItemList = userItemPage.getContent();
|
||||
|
||||
long currentIndex = kind * mul + maxCount * pageNum + userItemPage.getNumberOfElements();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userItemPage.getNumberOfElements());
|
||||
resultMap.put("nextIndex", userItemPage.getNumberOfElements() < maxCount ? -1 : currentIndex);
|
||||
resultMap.put("itemKind", kind);
|
||||
resultMap.put("userItemList", userItemList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GetUserLoginBonusHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserLoginBonusHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetUserLoginBonusHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
// TODO:
|
||||
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("userLoginBonusList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMap;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserMapService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handle GetUserMap request
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserMapHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserItemHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserMapService userMapService;
|
||||
|
||||
@Autowired
|
||||
public GetUserMapHandler(StringMapper mapper, UserMapService userMapService) {
|
||||
this.mapper = mapper;
|
||||
this.userMapService = userMapService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
List<UserMap> userMapList = userMapService.getByUserId(userId);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userMapList.size());
|
||||
resultMap.put("userMapList", userMapList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.data.UserMusicListItem;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserMusicDetail;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.GameMusicService;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserMusicDetailService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import icu.samnyan.aqua.spring.data.OffsetPageRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Response:
|
||||
*
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserMusicHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserMusicHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserMusicDetailService userMusicDetailService;
|
||||
|
||||
private final GameMusicService gameMusicService;
|
||||
|
||||
@Autowired
|
||||
public GetUserMusicHandler(StringMapper mapper, UserMusicDetailService userMusicDetailService, GameMusicService gameMusicService) {
|
||||
this.mapper = mapper;
|
||||
this.userMusicDetailService = userMusicDetailService;
|
||||
this.gameMusicService = gameMusicService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
int currentIndex = Integer.parseInt((String) request.get("nextIndex"));
|
||||
int maxCount = Integer.parseInt((String) request.get("maxCount"));
|
||||
if(currentIndex < 0) {
|
||||
currentIndex = 0;
|
||||
}
|
||||
|
||||
Page<UserMusicDetail> dbPage = userMusicDetailService
|
||||
.getByUserId(userId, OffsetPageRequest.of(currentIndex, maxCount, Sort.by("musicId")));
|
||||
|
||||
|
||||
// Convert to result format
|
||||
// Result Map
|
||||
Map<Integer, UserMusicListItem> userMusicMap = new LinkedHashMap<>();
|
||||
|
||||
dbPage.getContent().forEach(userMusicDetail -> {
|
||||
UserMusicListItem list;
|
||||
if (userMusicMap.containsKey(userMusicDetail.getMusicId())) {
|
||||
list = userMusicMap.get(userMusicDetail.getMusicId());
|
||||
} else {
|
||||
list = new UserMusicListItem(0, new ArrayList<>());
|
||||
userMusicMap.put(userMusicDetail.getMusicId(), list);
|
||||
}
|
||||
list.getUserMusicDetailList().add(userMusicDetail);
|
||||
list.setLength(list.getUserMusicDetailList().size());
|
||||
});
|
||||
|
||||
// Remove the last music id if the result length is the same as maxCount,
|
||||
// to prevent a music id split across multiple page, which will cause some
|
||||
// problem with the game.
|
||||
int lastListSize = 0;
|
||||
if(dbPage.getNumberOfElements() >= maxCount) {
|
||||
// Get last key
|
||||
int lastMusicId = userMusicMap.keySet().stream().reduce((a, b) -> b).orElseThrow();
|
||||
List<UserMusicDetail> lastList = userMusicMap.get(lastMusicId).getUserMusicDetailList();
|
||||
lastListSize = lastList.size();
|
||||
// Remove last one from map
|
||||
userMusicMap.remove(lastMusicId);
|
||||
}
|
||||
|
||||
long nextIndex = currentIndex + dbPage.getNumberOfElements() - lastListSize;
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", userMusicMap.size());
|
||||
resultMap.put("nextIndex", dbPage.getNumberOfElements() < maxCount ? -1 : nextIndex);
|
||||
resultMap.put("userMusicList", userMusicMap.values());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOptionEx;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserGameOptionExService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserOptionExHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserOptionExHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserGameOptionExService userGameOptionExService;
|
||||
|
||||
@Autowired
|
||||
public GetUserOptionExHandler(StringMapper mapper, UserGameOptionExService userGameOptionExService) {
|
||||
this.mapper = mapper;
|
||||
this.userGameOptionExService = userGameOptionExService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Optional<UserGameOptionEx> userGameOptionEx = userGameOptionExService.getByUserId(userId);
|
||||
|
||||
if (userGameOptionEx.isPresent()) {
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("userGameOptionEx", userGameOptionEx.get());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOption;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserGameOptionService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserOptionHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserOptionHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserGameOptionService userGameOptionService;
|
||||
|
||||
@Autowired
|
||||
public GetUserOptionHandler(StringMapper mapper, UserGameOptionService userGameOptionService) {
|
||||
this.mapper = mapper;
|
||||
this.userGameOptionService = userGameOptionService;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
Optional<UserGameOption> userGameOption = userGameOptionService.getByUserId(userId);
|
||||
|
||||
if (userGameOption.isPresent()) {
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("userGameOption", userGameOption.get());
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.response.GetUserPreviewResp;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserCharacter;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserData;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGameOption;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserCharacterService;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserGameOptionService;
|
||||
import icu.samnyan.aqua.sega.general.service.ClientSettingService;
|
||||
import icu.samnyan.aqua.sega.util.VersionUtil;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static icu.samnyan.aqua.sega.util.AquaConst.SERIAL_KEY;
|
||||
|
||||
/**
|
||||
* The handler for loading basic profile information.
|
||||
* <p>
|
||||
* return null if no profile exist
|
||||
*
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserPreviewHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserPreviewHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final ClientSettingService clientSettingService;
|
||||
|
||||
private final UserDataService userDataService;
|
||||
private final UserCharacterService userCharacterService;
|
||||
private final UserGameOptionService userGameOptionService;
|
||||
|
||||
@Autowired
|
||||
public GetUserPreviewHandler(StringMapper mapper,
|
||||
ClientSettingService clientSettingService, UserDataService userDataService,
|
||||
UserCharacterService userCharacterService,
|
||||
UserGameOptionService userGameOptionService
|
||||
) {
|
||||
this.mapper = mapper;
|
||||
this.clientSettingService = clientSettingService;
|
||||
this.userDataService = userDataService;
|
||||
this.userCharacterService = userCharacterService;
|
||||
this.userGameOptionService = userGameOptionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
|
||||
Optional<UserData> userData = userDataService.getUserByExtId(userId);
|
||||
|
||||
if (userData.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
UserData user = userData.get();
|
||||
|
||||
GetUserPreviewResp resp = new GetUserPreviewResp();
|
||||
resp.setUserId(userId);
|
||||
resp.setLogin(false);
|
||||
resp.setLastLoginDate(user.getLastLoginDate());
|
||||
resp.setUserName(user.getUserName());
|
||||
resp.setReincarnationNum(user.getReincarnationNum());
|
||||
resp.setLevel(user.getLevel());
|
||||
resp.setExp(user.getExp());
|
||||
resp.setPlayerRating(user.getPlayerRating());
|
||||
resp.setLastGameId(user.getLastGameId());
|
||||
|
||||
var vo = clientSettingService.getSetting((String) request.get(SERIAL_KEY));
|
||||
if (vo.isPresent()) {
|
||||
var version = vo.get();
|
||||
resp.setLastRomVersion(VersionUtil.getTargetVersion(user.getLastRomVersion(), version.getRomVersion()));
|
||||
resp.setLastDataVersion(VersionUtil.getTargetVersion(user.getLastDataVersion(), version.getDataVersion()));
|
||||
} else {
|
||||
resp.setLastRomVersion(user.getLastRomVersion());
|
||||
resp.setLastDataVersion(user.getLastDataVersion());
|
||||
}
|
||||
|
||||
resp.setLastPlayDate(user.getLastPlayDate());
|
||||
resp.setTrophyId(user.getTrophyId());
|
||||
|
||||
Optional<UserCharacter> userCharacterOptional = userCharacterService.getByUserAndCharacterId(user, user.getCharacterId());
|
||||
userCharacterOptional.ifPresent(resp::setUserCharacter);
|
||||
|
||||
Optional<UserGameOption> userGameOptionOptional = userGameOptionService.getByUser(user);
|
||||
userGameOptionOptional.ifPresent(userGameOption -> {
|
||||
resp.setPlayerLevel(userGameOption.getPlayerLevel());
|
||||
resp.setRating(userGameOption.getRating());
|
||||
resp.setHeadphone(userGameOption.getHeadphone());
|
||||
});
|
||||
|
||||
resp.setChargeState(1);
|
||||
resp.setUserNameEx(user.getUserName());
|
||||
|
||||
String json = mapper.write(resp);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserGeneralData;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserGeneralDataService;
|
||||
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating;
|
||||
import icu.samnyan.aqua.sega.chunithm.model.userdata.UserPlaylog;
|
||||
import icu.samnyan.aqua.sega.chunithm.service.UserPlaylogService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Return the recent play to calculate rating. Rating base on top 30 songs plus top 10 in recent 30 plays.
|
||||
*
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserRecentRatingHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserRecentRatingHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final UserPlaylogService userPlaylogService;
|
||||
private final UserGeneralDataService userGeneralDataService;
|
||||
|
||||
@Autowired
|
||||
public GetUserRecentRatingHandler(StringMapper mapper, UserPlaylogService userPlaylogService, UserGeneralDataService userGeneralDataService) {
|
||||
this.mapper = mapper;
|
||||
this.userPlaylogService = userPlaylogService;
|
||||
this.userGeneralDataService = userGeneralDataService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
Optional<UserGeneralData> recentOptional = userGeneralDataService.getByUserIdAndKey(userId, "recent_rating_list");
|
||||
|
||||
List<UserRecentRating> ratingList;
|
||||
if(recentOptional.isPresent()) {
|
||||
ratingList = new LinkedList<>();
|
||||
String val = recentOptional.get().getPropertyValue();
|
||||
if(StringUtils.isNotBlank(val) && val.contains(",")) {
|
||||
String[] records = val.split(",");
|
||||
for (String record :
|
||||
records) {
|
||||
String[] value = record.split(":");
|
||||
ratingList.add(new UserRecentRating(
|
||||
Integer.parseInt(value[0]),
|
||||
Integer.parseInt(value[1]),
|
||||
"1030000",
|
||||
Integer.parseInt(value[2])
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<UserPlaylog> top = userPlaylogService.getRecent30Plays(userId);
|
||||
ratingList = top.stream().map(log -> new UserRecentRating(log.getMusicId(), log.getLevel(), "1030000", log.getScore()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", ratingList.size());
|
||||
resultMap.put("userRecentRatingList", ratingList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component
|
||||
public class GetUserRegionHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserRegionHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public GetUserRegionHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
List<Object> userRegionList = new ArrayList<>();
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("userRegionList", userRegionList);
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GetUserRivalDataHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserRivalDataHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
|
||||
public GetUserRivalDataHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("userRivalData", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GetUserRivalMusicHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserRivalMusicHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
|
||||
public GetUserRivalMusicHandler(StringMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
resultMap.put("rivalId", 0);
|
||||
resultMap.put("length", 0);
|
||||
resultMap.put("nextIndex", 0);
|
||||
resultMap.put("userRivalMusicList", List.of());
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chunithm.handler.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.util.jackson.StringMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class GetUserTeamHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GetUserTeamHandler.class);
|
||||
|
||||
private final StringMapper mapper;
|
||||
|
||||
private final String teamName;
|
||||
|
||||
|
||||
public GetUserTeamHandler(StringMapper mapper, @Value("${game.chunithm.team-name:#{null}}") String teamName) {
|
||||
this.mapper = mapper;
|
||||
this.teamName = teamName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = (String) request.get("userId");
|
||||
String playDate = (String) request.get("playDate");
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("userId", userId);
|
||||
|
||||
if (teamName != null && !teamName.isEmpty()) {
|
||||
resultMap.put("teamId", 1);
|
||||
resultMap.put("teamRank", 1);
|
||||
resultMap.put("teamName", teamName);
|
||||
|
||||
Map<String, Object> userTeamMap = new LinkedHashMap<>();
|
||||
userTeamMap.put("userId", userId);
|
||||
userTeamMap.put("teamId", 1);
|
||||
userTeamMap.put("orderId", 1);
|
||||
userTeamMap.put("teamPoint", 1);
|
||||
userTeamMap.put("aggrDate", playDate);
|
||||
|
||||
resultMap.put("userTeamPoint", userTeamMap);
|
||||
} else {
|
||||
resultMap.put("teamId", 0);
|
||||
}
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user