diff --git a/src/lib/Setting/Pages/UserSettings.svelte b/src/lib/Setting/Pages/UserSettings.svelte
index 5a6c8c00..7b1ee877 100644
--- a/src/lib/Setting/Pages/UserSettings.svelte
+++ b/src/lib/Setting/Pages/UserSettings.svelte
@@ -4,11 +4,13 @@
import { loadRisuAccountData, saveRisuAccountData } from "src/ts/drive/accounter";
import { DataBase } from "src/ts/storage/database";
import Check from "src/lib/UI/GUI/CheckInput.svelte";
- import { alertConfirm } from "src/ts/alert";
+ import { alertConfirm, alertNormal } from "src/ts/alert";
import { forageStorage, isNodeServer, isTauri } from "src/ts/storage/globalApi";
import { unMigrationAccount } from "src/ts/storage/accountStorage";
import { checkDriver } from "src/ts/drive/drive";
- import { LoadLocalBackup, SaveLocalBackup } from "src/ts/drive/backuplocal";
+ import { LoadLocalBackup, SaveLocalBackup } from "src/ts/drive/backuplocal";
+ import Button from "src/lib/UI/GUI/Button.svelte";
+ import { autoServerBackup } from "src/ts/kei/backup";
let openIframe = false
let openIframeURL = ''
let popup:Window = null
@@ -120,7 +122,6 @@
{/if}
{/if}
-
{:else}
{language.notLoggedIn}
{/if}
+
+
{#if openIframe}
diff --git a/src/ts/kei/backup.ts b/src/ts/kei/backup.ts
new file mode 100644
index 00000000..a83d91e5
--- /dev/null
+++ b/src/ts/kei/backup.ts
@@ -0,0 +1,100 @@
+import { get } from "svelte/store"
+import { alertNormal, alertSelect } from "../alert"
+import { keiServerURL } from "./kei"
+import { DataBase, setDatabase } from "../storage/database"
+
+export async function autoServerBackup(){
+ const db = get(DataBase)
+ const res = await fetch(keiServerURL() + '/autobackup/list', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ token: db.account.token
+ })
+ })
+ if(res.status === 200){
+ const json = await res.json()
+ if(json.activated){
+ alertNormal("Auto backup is now activated in your account. Now it would backup automaticly, and you can now restore your data from the backup server.")
+ db.account.kei = true
+ return
+ }
+ const backups:[string,string][] = json.backups
+ let pointer = 0
+ while(true){
+ const slices = backups.slice(pointer, pointer + 5)
+ const menu = slices.map((backup) => backup[0])
+ menu.push("Next")
+ menu.push("Previous")
+ menu.push("Cancel")
+ const selectIndex = parseInt(await alertSelect(menu))
+ const selected = menu[selectIndex]
+ if(selected === "Cancel"){
+ break
+ }
+ else if(selected === "Next"){
+ pointer += 5
+ if(pointer >= backups.length){
+ pointer = 0
+ }
+ }
+ else if(selected === "Previous"){
+ pointer -= 5
+ if(pointer < 0){
+ pointer = Math.floor(backups.length / 5) * 5
+ }
+ }
+ else{
+ const backup = backups.find((backup) => backup[0] === selected)
+ if(backup){
+ const res = await fetch(keiServerURL() + '/autobackup/restore', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ token: db.account.token,
+ backup: backup[1]
+ })
+ })
+ if(res.status === 200){
+ setDatabase(await res.json())
+ alertNormal("Successfully restored!")
+ }
+ else{
+ alertNormal("Error: " + res.text())
+ }
+ }
+ }
+ }
+ }
+ else if(res.status === 401){
+ alertNormal("You need to activate Risu-Kei in your account, or host your Risu-Kei server from github to use this feature.")
+ }
+ else{
+ alertNormal("Error: " + res.text())
+ }
+}
+
+let lastKeiSave = 0
+export async function saveDbKei() {
+ let db = get(DataBase)
+ if(db.account.kei){
+ if(Date.now() - lastKeiSave < 60000 * 5){
+ return
+ }
+ lastKeiSave = Date.now()
+ fetch(keiServerURL() + '/autobackup/save', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ token: db.account.token,
+ database: db
+ })
+ })
+ }
+}
\ No newline at end of file
diff --git a/src/ts/kei/kei.ts b/src/ts/kei/kei.ts
new file mode 100644
index 00000000..648820ba
--- /dev/null
+++ b/src/ts/kei/kei.ts
@@ -0,0 +1,9 @@
+import { get } from "svelte/store";
+import { hubURL } from "../characterCards";
+import { DataBase } from "../storage/database";
+
+export function keiServerURL(){
+ const db = get(DataBase)
+ if(db.keiServerURL) return db.keiServerURL;
+ return hubURL + "/kei";
+}
\ No newline at end of file
diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts
index 0c34570a..f6e0d5c9 100644
--- a/src/ts/storage/database.ts
+++ b/src/ts/storage/database.ts
@@ -368,6 +368,7 @@ export function setDatabase(data:Database){
sendName: false,
utilOverride: false
}
+ data.keiServerURL ??= ''
changeLanguage(data.language)
DataBase.set(data)
@@ -509,6 +510,7 @@ export interface Database{
expires_in?: number
}
useSync?:boolean
+ kei?:boolean
},
classicMaxWidth: boolean,
useChatSticker:boolean,
@@ -572,6 +574,7 @@ export interface Database{
chainOfThought?:boolean
genTime:number
proomptSettings: ProomptSettings
+ keiServerURL:string
}
export interface customscript{
diff --git a/src/ts/storage/globalApi.ts b/src/ts/storage/globalApi.ts
index 390926f9..5164e20b 100644
--- a/src/ts/storage/globalApi.ts
+++ b/src/ts/storage/globalApi.ts
@@ -22,6 +22,7 @@ import { decodeRisuSave, encodeRisuSave } from "./risuSave";
import { AutoStorage } from "./autoStorage";
import { updateAnimationSpeed } from "../gui/animation";
import { updateColorScheme, updateTextTheme } from "../gui/colorscheme";
+import { saveDbKei } from "../kei/backup";
//@ts-ignore
export const isTauri = !!window.__TAURI__
@@ -243,6 +244,7 @@ export async function saveDb(){
}
savetrys = 0
}
+ await saveDbKei()
await sleep(500)
} catch (error) {
if(savetrys > 4){