forked from Cookies_Github_mirror/AquaDX
[+] Card Timestamp
This commit is contained in:
@@ -27,7 +27,9 @@ import icu.samnyan.aqua.sega.general.model.Card
|
||||
import icu.samnyan.aqua.sega.general.service.CardService
|
||||
import icu.samnyan.aqua.sega.ongeki.OgkUserDataRepo
|
||||
import icu.samnyan.aqua.sega.wacca.model.db.WcUserRepo
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
import java.time.Instant
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.io.path.getLastModifiedTime
|
||||
import kotlin.io.path.isRegularFile
|
||||
@@ -41,7 +43,7 @@ class FedyProps {
|
||||
var remote: String = ""
|
||||
}
|
||||
|
||||
data class UserProfilePicture(val url: Str, val lastUpdatedMs: Long)
|
||||
data class UserProfilePicture(val url: Str, val updatedAtMs: 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,
|
||||
@@ -66,21 +68,23 @@ private data class FedyEvent(
|
||||
@API("/api/v2/fedy", consumes = ["multipart/form-data"])
|
||||
class Fedy(
|
||||
val jwt: JWT,
|
||||
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 transactionManager: PlatformTransactionManager,
|
||||
ctx: ApplicationContext
|
||||
) {
|
||||
val us by ctx.lazy<AquaUserServices>()
|
||||
val cardService by ctx.lazy<CardService>()
|
||||
val mai2Import by ctx.lazy<Mai2Import>()
|
||||
val mai2UploadUserPlaylog by ctx.lazy<Mai2UploadUserPlaylogHandler>()
|
||||
val mai2UpsertUserAll by ctx.lazy<Mai2UpsertUserAllHandler>()
|
||||
|
||||
val transaction by lazy { TransactionTemplate(transactionManager) }
|
||||
|
||||
private fun Str.checkKey() {
|
||||
@@ -157,25 +161,30 @@ class Fedy(
|
||||
?.let { paths.aquaNetPortrait.path() / it }?.takeIf { it.isRegularFile() }
|
||||
?.let { UserProfilePicture(
|
||||
url = "/uploads/net/portrait/${profilePicture}",
|
||||
lastUpdatedMs = it.getLastModifiedTime().toMillis()
|
||||
updatedAtMs = 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)
|
||||
data class DataPullReq(val extId: Long, val game: Str, val createdAtMs: Long, val updatedAtMs: Long, val exportOptions: ExportOptions)
|
||||
data class DataPullResult(val data: Any?, val createdAtMs: Long, val updatedAtMs: Long, val isRebased: Bool)
|
||||
data class DataPullRes(val error: FedyErr? = null, val result: DataPullResult? = 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).orElse(null)
|
||||
?: (404 - "Card with extId ${req.extId} not found")
|
||||
val cardTimestamp = cardService.getCardTimestamp(card, req.game)
|
||||
if (cardTimestamp.updatedAt.toEpochMilli() == req.updatedAtMs) return@handleFedy DataPullRes(error = null, result = null) // No changes
|
||||
val isRebased = req.createdAtMs > 0 && cardTimestamp.createdAt.toEpochMilli() > req.createdAtMs
|
||||
val exportOptions = if (!isRebased) { req.exportOptions } else { req.exportOptions.copy(playlogAfter = null) }
|
||||
{
|
||||
DataPullRes(result = when (req.game) {
|
||||
"mai2" -> mai2Import.export(card, req.exportOptions)
|
||||
DataPullRes(result = DataPullResult(data = when (req.game) {
|
||||
"mai2" -> mai2Import.export(card, exportOptions)
|
||||
else -> 406 - "Unsupported game"
|
||||
})
|
||||
}, createdAtMs = cardTimestamp.createdAt.toEpochMilli(), updatedAtMs = cardTimestamp.updatedAt.toEpochMilli(), isRebased = isRebased))
|
||||
} caught { DataPullRes(error = it) }
|
||||
}
|
||||
|
||||
data class DataPushReq(val extId: 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, val updatedAtMs: Long)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@API("/data/push")
|
||||
fun handleDataPush(@RH(KEY_HEADER) key: Str, @RT(REQ_PART) req: DataPushReq): Any = handleFedy(key) {
|
||||
@@ -188,6 +197,7 @@ class Fedy(
|
||||
repo.flush()
|
||||
}
|
||||
}
|
||||
val card = cardRepo.findByExtId(extId).orElse(null) ?: (404 - "Card not found")
|
||||
transaction.execute { when (req.game) {
|
||||
"mai2" -> {
|
||||
if (req.removeOldData) { removeOldData(mai2UserDataRepo) }
|
||||
@@ -198,7 +208,7 @@ class Fedy(
|
||||
}
|
||||
else -> 406 - "Unsupported game"
|
||||
} }
|
||||
|
||||
cardService.updateCardTimestamp(card, req.game, now = Instant.ofEpochMilli(req.updatedAtMs), resetCreatedAt = req.removeOldData)
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
@@ -221,9 +231,9 @@ class Fedy(
|
||||
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) {
|
||||
var isNonFresh = pairedCard != null && !isCardFresh(pairedCard)
|
||||
if (isGhost || isNonFresh) isPairedLuidDiverged = true
|
||||
else if (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) }
|
||||
@@ -326,7 +336,7 @@ 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
|
||||
fun <T : IUserData> checkForGame(repo: GenericUserDataRepo<T>, card: Card): Bool = repo.findByCard(card) != null
|
||||
return when {
|
||||
checkForGame(mai2UserDataRepo, c) -> false
|
||||
checkForGame(chu3UserDataRepo, c) -> false
|
||||
@@ -346,17 +356,5 @@ class Fedy(
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user