mirror of https://github.com/hykilpikonna/AquaDX
[+] Import from a userMusicDetailList Json
parent
daa5129f65
commit
a84bf9efef
|
@ -16,6 +16,7 @@
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.1.0",
|
"@sveltejs/vite-plugin-svelte": "^3.1.0",
|
||||||
"@tsconfig/svelte": "^5.0.4",
|
"@tsconfig/svelte": "^5.0.4",
|
||||||
"@types/d3": "^7",
|
"@types/d3": "^7",
|
||||||
|
"@types/wicg-file-system-access": "^2023.10.5",
|
||||||
"@unocss/svelte-scoped": "^0.62.4",
|
"@unocss/svelte-scoped": "^0.62.4",
|
||||||
"chartjs-adapter-moment": "^1.0.1",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
@ -39,7 +40,8 @@
|
||||||
"lxgw-wenkai-lite-webfont": "^1.7.0",
|
"lxgw-wenkai-lite-webfont": "^1.7.0",
|
||||||
"modern-normalize": "^2.0.0",
|
"modern-normalize": "^2.0.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
|
"show-open-file-picker": "^0.2.2",
|
||||||
"svelte-chartjs": "^3.1.5"
|
"svelte-chartjs": "^3.1.5"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.1.1"
|
"packageManager": "pnpm@9.7.0+sha512.dc09430156b427f5ecfc79888899e1c39d2d690f004be70e05230b72cb173d96839587545d09429b55ac3c429c801b4dc3c0e002f653830a420fa2dd4e3cf9cf"
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -305,6 +305,8 @@ export const GAME = {
|
||||||
post(`/api/v2/game/${game}/export`),
|
post(`/api/v2/game/${game}/export`),
|
||||||
import: (game: GameName, data: any): Promise<Record<string, any>> =>
|
import: (game: GameName, data: any): Promise<Record<string, any>> =>
|
||||||
post(`/api/v2/game/${game}/import`, {}, { body: JSON.stringify(data) }),
|
post(`/api/v2/game/${game}/import`, {}, { body: JSON.stringify(data) }),
|
||||||
|
importMusicDetail: (game: GameName, data: any): Promise<Record<string, any>> =>
|
||||||
|
post(`/api/v2/game/${game}/import-music-detail`, {}, {body: JSON.stringify(data), headers: {'Content-Type': 'application/json'}}),
|
||||||
setRival: (game: GameName, rivalUserName: string, isAdd: boolean) =>
|
setRival: (game: GameName, rivalUserName: string, isAdd: boolean) =>
|
||||||
post(`/api/v2/game/${game}/set-rival`, { rivalUserName, isAdd }),
|
post(`/api/v2/game/${game}/set-rival`, { rivalUserName, isAdd }),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import StatusOverlays from "../../components/StatusOverlays.svelte";
|
import StatusOverlays from "../../components/StatusOverlays.svelte";
|
||||||
import { CARD, GAME, USER } from "../../libs/sdk";
|
import { CARD, GAME, USER } from "../../libs/sdk";
|
||||||
import Icon from "@iconify/svelte";
|
import Icon from "@iconify/svelte";
|
||||||
|
import { showOpenFilePicker } from 'show-open-file-picker'
|
||||||
|
|
||||||
let load = false;
|
let load = false;
|
||||||
let error = "";
|
let error = "";
|
||||||
|
@ -17,8 +18,8 @@
|
||||||
let confirmAction: (override: boolean) => void;
|
let confirmAction: (override: boolean) => void;
|
||||||
|
|
||||||
const startImport = async () => {
|
const startImport = async () => {
|
||||||
const [fileHandle] = await window.showOpenFilePicker({
|
const [fileHandle] = await (window.showOpenFilePicker || showOpenFilePicker)({
|
||||||
id: 'aquadx_import',
|
id: 'aquadx_import' as any,
|
||||||
startIn: 'downloads',
|
startIn: 'downloads',
|
||||||
types: [
|
types: [
|
||||||
{
|
{
|
||||||
|
@ -36,9 +37,16 @@
|
||||||
try {
|
try {
|
||||||
const file = await fileHandle.getFile();
|
const file = await fileHandle.getFile();
|
||||||
const data = JSON.parse(await file.text()) as any;
|
const data = JSON.parse(await file.text()) as any;
|
||||||
const game = getGameByCode(data.gameId);
|
|
||||||
|
|
||||||
const me = await USER.me();
|
const me = await USER.me();
|
||||||
|
|
||||||
|
if (Array.isArray(data) && data.every(it => Array.isArray(it?.userMusicDetailList))) {
|
||||||
|
// Is music list array
|
||||||
|
await GAME.importMusicDetail("mai2", data.flatMap(it => it.userMusicDetailList));
|
||||||
|
location.href = `/u/${me.username}/mai2`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const game = getGameByCode(data.gameId);
|
||||||
const userGames = await CARD.userGames(me.username);
|
const userGames = await CARD.userGames(me.username);
|
||||||
|
|
||||||
const existed = userGames[game];
|
const existed = userGames[game];
|
||||||
|
@ -78,42 +86,42 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionCard color="209, 124, 102" icon="bxs:file-import" on:click={startImport}>
|
<ActionCard color="209, 124, 102" icon="bxs:file-import" on:click={startImport}>
|
||||||
<h3>{t('home.import')}</h3>
|
<h3>{t('home.import')}</h3>
|
||||||
<span>{t('home.import-description')}</span>
|
<span>{t('home.import-description')}</span>
|
||||||
</ActionCard>
|
</ActionCard>
|
||||||
|
|
||||||
<StatusOverlays {error} loading={load}/>
|
<StatusOverlays {error} loading={load}/>
|
||||||
|
|
||||||
{#if conflict}
|
{#if conflict}
|
||||||
<div class="overlay" transition:fade>
|
<div class="overlay" transition:fade>
|
||||||
<div>
|
<div>
|
||||||
<h2>{t('home.import.data-conflict')}</h2>
|
<h2>{t('home.import.data-conflict')}</h2>
|
||||||
<p></p>
|
<p></p>
|
||||||
<div class="conflict-cards">
|
<div class="conflict-cards">
|
||||||
<div class="old card">
|
<div class="old card">
|
||||||
<span class="type">{t('home.linkcard.account-card')}</span>
|
<span class="type">{t('home.linkcard.account-card')}</span>
|
||||||
<span>{t('home.linkcard.name')}: {conflict.oldName}</span>
|
<span>{t('home.linkcard.name')}: {conflict.oldName}</span>
|
||||||
<span>{t('home.linkcard.rating')}: {conflict.oldRating}</span>
|
<span>{t('home.linkcard.rating')}: {conflict.oldRating}</span>
|
||||||
<div class="trash">
|
<div class="trash">
|
||||||
<Icon icon="ph:trash-duotone"/>
|
<Icon icon="ph:trash-duotone"/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="icon">
|
||||||
|
<Icon icon="icon-park-outline:down"/>
|
||||||
|
</div>
|
||||||
|
<div class="new card">
|
||||||
|
<span class="type">{t('home.import.new-data')}</span>
|
||||||
|
<span>{t('home.linkcard.name')}: {conflict.newName}</span>
|
||||||
|
<span>{t('home.linkcard.rating')}: {conflict.newRating}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p></p>
|
||||||
|
<div class="buttons">
|
||||||
|
<button on:click={() => confirmAction(false)}>{t('action.cancel')}</button>
|
||||||
|
<button class="error" on:click={() => confirmAction(true)}>{t('action.confirm')}</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon">
|
|
||||||
<Icon icon="icon-park-outline:down"/>
|
|
||||||
</div>
|
|
||||||
<div class="new card">
|
|
||||||
<span class="type">{t('home.import.new-data')}</span>
|
|
||||||
<span>{t('home.linkcard.name')}: {conflict.newName}</span>
|
|
||||||
<span>{t('home.linkcard.rating')}: {conflict.newRating}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p></p>
|
|
||||||
<div class="buttons">
|
|
||||||
<button on:click={() => confirmAction(false)}>{t('action.cancel')}</button>
|
|
||||||
<button class="error" on:click={() => confirmAction(true)}>{t('action.confirm')}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package icu.samnyan.aqua.net.games.mai2
|
||||||
|
|
||||||
|
import ext.*
|
||||||
|
import icu.samnyan.aqua.net.db.AquaUserServices
|
||||||
|
import icu.samnyan.aqua.net.utils.SUCCESS
|
||||||
|
import icu.samnyan.aqua.sega.maimai2.model.Mai2Repos
|
||||||
|
import icu.samnyan.aqua.sega.maimai2.model.userdata.Mai2UserMusicDetail
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@API("api/v2/game/mai2")
|
||||||
|
class Mai2MusicDetailImport(
|
||||||
|
val us: AquaUserServices,
|
||||||
|
val repos: Mai2Repos,
|
||||||
|
) {
|
||||||
|
@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")
|
||||||
|
data.forEach { newMusic ->
|
||||||
|
val musicRec = repos.userMusicDetail.findByUserAndMusicIdAndLevel(user, newMusic.musicId, newMusic.level)
|
||||||
|
if (musicRec.isPresent) {
|
||||||
|
val music = musicRec.get()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repos.userMusicDetail.saveAll(data)
|
||||||
|
SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue