mirror of https://github.com/hykilpikonna/AquaDX
[+] Complete transfer logic
parent
c6af5b7d87
commit
c93f47744b
|
@ -1,8 +1,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { slide } from "svelte/transition";
|
import { slide } from "svelte/transition";
|
||||||
import { ts } from "../../libs/i18n";
|
import { t, ts } from "../../libs/i18n";
|
||||||
import TransferServer from "./TransferServer.svelte";
|
import TransferServer from "./TransferServer.svelte";
|
||||||
import { DATA_HOST } from "../../libs/config";
|
import { DATA_HOST } from "../../libs/config";
|
||||||
|
import type { ConfirmProps } from "../../libs/generalTypes";
|
||||||
|
|
||||||
|
|
||||||
let tabs = ['chu3', 'mai2', 'ongeki']
|
let tabs = ['chu3', 'mai2', 'ongeki']
|
||||||
|
@ -13,16 +14,15 @@
|
||||||
}
|
}
|
||||||
let tab = 0
|
let tab = 0
|
||||||
|
|
||||||
let src = JSON.parse(localStorage.getItem('src') ?? JSON.stringify({
|
let src = JSON.parse(localStorage.getItem('src') ?? `{"dns": "", "card": "", "keychip": ""}`)
|
||||||
dns: "",
|
let dst = JSON.parse(localStorage.getItem('dst') ?? `{"dns": "", "card": "", "keychip": ""}`)
|
||||||
card: "",
|
let [srcTested, dstTested] = [false, false]
|
||||||
keychip: ""
|
let gameInfo = JSON.parse(localStorage.getItem('gameInfo') ?? `{"game": "", "version": ""}`)
|
||||||
}))
|
|
||||||
let dst = JSON.parse(localStorage.getItem('dst') ?? `{ card: "", server: "", keychip: "" }`)
|
let srcEl: TransferServer, dstEl: TransferServer
|
||||||
let gameInfo = JSON.parse(localStorage.getItem('gameInfo') ?? JSON.stringify({
|
let srcExportedData: string
|
||||||
game: "",
|
let loading: boolean = false
|
||||||
version: "",
|
let confirm: ConfirmProps | null = null
|
||||||
}))
|
|
||||||
|
|
||||||
function defaultGame() {
|
function defaultGame() {
|
||||||
gameInfo.game = game[tabs[tab]].game
|
gameInfo.game = game[tabs[tab]].game
|
||||||
|
@ -35,6 +35,27 @@
|
||||||
localStorage.setItem('gameInfo', JSON.stringify(gameInfo))
|
localStorage.setItem('gameInfo', JSON.stringify(gameInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startTransfer() {
|
||||||
|
if (!(srcTested && dstTested)) return alert("Please test both servers first!")
|
||||||
|
if (loading) return alert("Transfer already in progress!")
|
||||||
|
console.log("Starting transfer...")
|
||||||
|
loading = true
|
||||||
|
|
||||||
|
if (!dstEl.exportedData) {
|
||||||
|
// Ask user to make sure to backup their data
|
||||||
|
if (!confirm("It seems like you haven't backed up your destination data. Are you sure you want to proceed? (This will overwrite your destination server's data)")) {
|
||||||
|
loading = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
srcEl.pull()
|
||||||
|
.then(() => dstEl.push(srcExportedData))
|
||||||
|
.then(() => alert("Transfer successful!"))
|
||||||
|
.catch(e => alert(`Transfer failed: ${e}`))
|
||||||
|
.finally(() => loading = false)
|
||||||
|
}
|
||||||
|
|
||||||
defaultGame()
|
defaultGame()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -56,15 +77,21 @@
|
||||||
<p>👋 Welcome to the AquaTrans™ server data transfer tool!</p>
|
<p>👋 Welcome to the AquaTrans™ server data transfer tool!</p>
|
||||||
<p>You can use this to export data from any server, and input data into any server using the connection credentials (card number, server address, and keychip id).</p>
|
<p>You can use this to export data from any server, and input data into any server using the connection credentials (card number, server address, and keychip id).</p>
|
||||||
<p>This tool will simulate a game client and pull your data from the source server, and push your data to the destination server.</p>
|
<p>This tool will simulate a game client and pull your data from the source server, and push your data to the destination server.</p>
|
||||||
<p>Please fill out the form below to get started!</p>
|
<p>Please fill out the info below to get started!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TransferServer bind:src={src} bind:gameInfo={gameInfo} on:change={onChange}
|
||||||
|
bind:tested={srcTested} bind:this={srcEl} bind:exportedData={srcExportedData} />
|
||||||
|
|
||||||
|
<div class="arrow" class:disabled={!(srcTested && dstTested)}>
|
||||||
|
<img src="{DATA_HOST}/d/DownArrow.png" alt="arrow" on:click={startTransfer}>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TransferServer bind:src={src} bind:gameInfo={gameInfo} on:change={onChange} />
|
|
||||||
<div class="arrow"><img src="{DATA_HOST}/d/DownArrow.png" alt="arrow"></div>
|
|
||||||
<TransferServer bind:src={dst} bind:gameInfo={gameInfo} on:change={onChange}
|
<TransferServer bind:src={dst} bind:gameInfo={gameInfo} on:change={onChange}
|
||||||
isSrc={false} />
|
bind:tested={dstTested} bind:this={dstEl} isSrc={false} />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
.arrow
|
.arrow
|
||||||
width: 100%
|
width: 100%
|
||||||
|
@ -72,11 +99,14 @@
|
||||||
justify-content: center
|
justify-content: center
|
||||||
margin-top: -40px
|
margin-top: -40px
|
||||||
margin-bottom: -40px
|
margin-bottom: -40px
|
||||||
z-index: 0
|
z-index: 1
|
||||||
|
|
||||||
// CSS animation to let the image opacity breathe
|
&.disabled
|
||||||
.arrow img
|
filter: grayscale(1)
|
||||||
animation: breathe 1s infinite alternate
|
|
||||||
|
// CSS animation to let the image opacity breathe
|
||||||
|
img
|
||||||
|
animation: breathe 1s infinite alternate
|
||||||
|
|
||||||
@keyframes breathe
|
@keyframes breathe
|
||||||
0%
|
0%
|
||||||
|
|
|
@ -1,18 +1,90 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import StatusOverlays from "../../components/StatusOverlays.svelte";
|
import StatusOverlays from "../../components/StatusOverlays.svelte";
|
||||||
import { TRANSFER } from "../../libs/sdk";
|
import { TRANSFER } from "../../libs/sdk";
|
||||||
|
import { download, selectJsonFile } from "../../libs/ui";
|
||||||
import InputTextShort from "./InputTextShort.svelte";
|
import InputTextShort from "./InputTextShort.svelte";
|
||||||
|
|
||||||
export let src: AllNetSrc
|
export let src: AllNetSrc
|
||||||
export let gameInfo: AllNetGame
|
export let gameInfo: AllNetGame
|
||||||
export let isSrc: boolean = true
|
export let isSrc: boolean = true
|
||||||
|
|
||||||
let tested: boolean = false
|
export let tested: boolean = false
|
||||||
|
let [loading, error, expectedError] = [false, "", ""]
|
||||||
|
|
||||||
|
function testConnection() {
|
||||||
|
if (loading) return
|
||||||
|
|
||||||
|
// Preliminiary checks
|
||||||
|
if (!src.dns || !src.keychip || !src.card || !gameInfo.game || !gameInfo.version) {
|
||||||
|
error = "Please fill out all fields"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loading = true
|
||||||
|
console.log("Testing connection...")
|
||||||
|
TRANSFER.check({...src, ...gameInfo}).then(res => {
|
||||||
|
console.log("Connection test result:", res)
|
||||||
|
tested = true
|
||||||
|
}).catch(err => expectedError = err.message).finally(() => loading = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
let messages: string[] = []
|
||||||
|
export let exportedData: string = ""
|
||||||
|
|
||||||
|
export function pull(): Promise<string> {
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
if (loading || !tested) return reject("Please test connection first")
|
||||||
|
if (exportedData) return resolve(exportedData)
|
||||||
|
console.log("Exporting data...")
|
||||||
|
|
||||||
|
TRANSFER.pull({...src, ...gameInfo}, (msg: TrStreamMessage) => {
|
||||||
|
console.log("Export progress: ", JSON.stringify(msg))
|
||||||
|
|
||||||
|
if ('message' in msg) messages = [...messages, msg.message]
|
||||||
|
|
||||||
|
if ('error' in msg) {
|
||||||
|
expectedError = msg.error
|
||||||
|
reject(msg.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('data' in msg) {
|
||||||
|
// file name: Export YYYY-MM-DD {server host} {game} {card last 6}.json
|
||||||
|
let date = new Date().toISOString().split('T')[0]
|
||||||
|
let host = new URL(src.dns).hostname
|
||||||
|
download(msg.data, `Export ${date} ${host} ${gameInfo.game} ${src.card.slice(-6)}.json`)
|
||||||
|
exportedData = msg.data
|
||||||
|
resolve(msg.data)
|
||||||
|
}
|
||||||
|
}).catch(err => { expectedError = err; reject(err) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushBtn() {
|
||||||
|
if (loading || !tested) return
|
||||||
|
selectJsonFile().then(obj => push(JSON.stringify(obj)))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function push(data: string) {
|
||||||
|
if (loading || !tested) return
|
||||||
|
console.log("Import data...")
|
||||||
|
loading = true
|
||||||
|
|
||||||
|
TRANSFER.push({...src, ...gameInfo}, data).then(() => {
|
||||||
|
console.log("Data imported successfully")
|
||||||
|
messages = ["Data imported successfully"]
|
||||||
|
}).catch(err => expectedError = err.message).finally(() => loading = false)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="server source" class:src={isSrc}>
|
<StatusOverlays {loading} {error} />
|
||||||
|
|
||||||
|
<div class="server source" class:src={isSrc} class:hasError={expectedError} class:tested={tested}>
|
||||||
<h3>{isSrc ? "Source" : "Target"} Server</h3>
|
<h3>{isSrc ? "Source" : "Target"} Server</h3>
|
||||||
|
|
||||||
|
{#if expectedError}
|
||||||
|
<blockquote class="error-msg">{expectedError}</blockquote>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- First input line -->
|
<!-- First input line -->
|
||||||
<div class="inputs">
|
<div class="inputs">
|
||||||
<InputTextShort desc="Server Address" placeholder="e.g. http://aquadx.hydev.org"
|
<InputTextShort desc="Server Address" placeholder="e.g. http://aquadx.hydev.org"
|
||||||
|
@ -33,12 +105,22 @@
|
||||||
bind:value={src.card} on:change disabled={tested} />
|
bind:value={src.card} on:change disabled={tested} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Streaming messages -->
|
||||||
|
{#if messages.length > 0}
|
||||||
|
<div class="stream-messages">
|
||||||
|
{#each messages.slice(Math.max(messages.length - 5, 0), undefined) as msg}
|
||||||
|
<p>{msg}</p>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
<div class="inputs buttons">
|
<div class="inputs buttons">
|
||||||
{#if !tested}
|
{#if !tested}
|
||||||
<button class="flex-1" on:click={() => {}}>Test Connection</button>
|
<button class="flex-1" on:click={testConnection} disabled={loading}>Test Connection</button>
|
||||||
{:else}
|
{:else}
|
||||||
<button class="flex-1" on:click={() => {}}>Export Data</button>
|
<button class="flex-1" on:click={pull}>Export Data</button>
|
||||||
|
<button class="flex-1" on:click={pushBtn}>Import Data</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,14 +129,28 @@
|
||||||
@use "../../vars"
|
@use "../../vars"
|
||||||
@use "sass:color"
|
@use "sass:color"
|
||||||
|
|
||||||
|
.error-msg
|
||||||
|
white-space: pre-wrap
|
||||||
|
margin: 0
|
||||||
|
|
||||||
.server
|
.server
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
gap: 1rem
|
gap: 1rem
|
||||||
|
|
||||||
--c-src: 255, 174, 174
|
// --c-src: 202, 168, 252
|
||||||
&.src
|
--c-src: 179, 198, 255
|
||||||
--c-src: 173, 192, 247
|
// animation: hue-rotate 10s infinite linear
|
||||||
|
// &.src
|
||||||
|
// --c-src: 173, 192, 247
|
||||||
|
// animation: hue-rotate 10s infinite linear reverse
|
||||||
|
|
||||||
|
&.tested
|
||||||
|
--c-src: 169, 255, 186
|
||||||
|
|
||||||
|
&.hasError
|
||||||
|
--c-src: 255, 174, 174
|
||||||
|
animation: none
|
||||||
|
|
||||||
padding: 1rem
|
padding: 1rem
|
||||||
border-radius: vars.$border-radius
|
border-radius: vars.$border-radius
|
||||||
|
@ -71,6 +167,12 @@
|
||||||
text-align: center
|
text-align: center
|
||||||
|
|
||||||
|
|
||||||
|
// @keyframes hue-rotate
|
||||||
|
// 0%
|
||||||
|
// filter: hue-rotate(0deg)
|
||||||
|
// 100%
|
||||||
|
// filter: hue-rotate(360deg)
|
||||||
|
|
||||||
.inputs
|
.inputs
|
||||||
display: flex
|
display: flex
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
|
@ -85,5 +187,12 @@
|
||||||
width: 100px
|
width: 100px
|
||||||
|
|
||||||
&.buttons
|
&.buttons
|
||||||
margin-top: 1rem
|
margin-top: 0.5rem
|
||||||
|
|
||||||
|
.stream-messages
|
||||||
|
font-size: 0.8rem
|
||||||
|
opacity: 0.8
|
||||||
|
|
||||||
|
margin-top: 0.5rem
|
||||||
|
padding: 0 0.5rem
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue