From 911aeed9ea78b7f377f44f9ecaa3bd1f19c0b451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9B=AE=E6=A3=83?= Date: Sun, 29 Sep 2024 10:15:05 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=95=B0=E6=8D=AE=E5=A4=87?= =?UTF-8?q?=E4=BB=BD&=E6=81=A2=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #126 --- src/plugins/Sqlite/modules/userAccount.ts | 51 +++++++++++++++++ src/plugins/Sqlite/modules/userAchi.ts | 13 +++-- src/plugins/Sqlite/modules/userGacha.ts | 63 ++++++++++++++++++++ src/utils/dataBS.ts | 70 +++++------------------ 4 files changed, 134 insertions(+), 63 deletions(-) diff --git a/src/plugins/Sqlite/modules/userAccount.ts b/src/plugins/Sqlite/modules/userAccount.ts index b04665e4..3ee3a621 100644 --- a/src/plugins/Sqlite/modules/userAccount.ts +++ b/src/plugins/Sqlite/modules/userAccount.ts @@ -4,6 +4,10 @@ * @since Beta v0.6.0 */ +import { path } from "@tauri-apps/api"; +import { exists, mkdir, readTextFile, writeTextFile } from "@tauri-apps/plugin-fs"; + +import TGLogger from "../../../utils/TGLogger.js"; import { timestampToDate } from "../../../utils/toolFunc.js"; import TGSqlite from "../index.js"; @@ -120,6 +124,51 @@ async function saveAccount(data: TGApp.App.Account.User): Promise { ); } +/** + * @description 备份用户数据 + * @since Beta v0.6.0 + * @param {string} dir - 备份目录 + * @returns {Promise} + */ +async function backUpAccount(dir: string): Promise { + if (!(await exists(dir))) { + await TGLogger.Warn("不存在指定的账户备份目录,即将创建"); + await mkdir(dir, { recursive: true }); + } + const accounts = await getAllAccount(); + await writeTextFile(`${dir}${path.sep()}accounts.json`, JSON.stringify(accounts, null, 2)); + await TGLogger.Info("账户数据备份完成"); +} + +/** + * @description 恢复用户数据 + * @since Beta v0.6.0 + * @param {string} dir + * @returns {Promise} + */ +async function restoreAccount(dir: string): Promise { + if (!(await exists(dir))) { + await TGLogger.Warn("不存在指定的账户备份目录"); + return false; + } + try { + const filePath = `${dir}${path.sep()}accounts.json`; + if (!(await exists(filePath))) { + await TGLogger.Warn("不存在指定的账户备份文件"); + return false; + } + const data = await readTextFile(filePath); + const accounts: TGApp.App.Account.User[] = JSON.parse(data); + for (const account of accounts) { + await saveAccount(account); + } + } catch (e) { + await TGLogger.Error(`[UserAccount][restoreAccount] ${e}`); + return false; + } + return true; +} + /** * @description 复制cookie * @since Beta v0.6.0 @@ -236,6 +285,8 @@ const TSUserAccount = { saveAccount, copy: copyCookie, deleteAccount, + backup: backUpAccount, + restore: restoreAccount, }, game: { getAccount: getGameAccount, diff --git a/src/plugins/Sqlite/modules/userAchi.ts b/src/plugins/Sqlite/modules/userAchi.ts index 24c37636..3b8e5c43 100644 --- a/src/plugins/Sqlite/modules/userAchi.ts +++ b/src/plugins/Sqlite/modules/userAchi.ts @@ -306,22 +306,23 @@ async function backupUiaf(dir: string, uid?: number): Promise { async function restoreUiaf(dir: string): Promise { if (!(await exists(dir))) return false; const filesRead = await readDir(dir); - const files = filesRead.filter((item) => item.name.includes("UIAF_") && item.isFile); + // 校验 UIAF_xxx.json 文件 + const fileRegex = /^UIAF_\d+\.json$/; + const files = filesRead.filter((item) => item.isFile && fileRegex.test(item.name)); + if (files.length === 0) return false; for (const file of files) { try { - // todo 完善正则判断 - const reg = /UIAF_(\d+).json/; - if (!file.name.match(reg)) return false; - const uid: number = Number(file.name.match(reg)![0]); + const uid = parseInt(file.name.replace("UIAF_", "").replace(".json", "")); const filePath = `${dir}${path.sep()}${file.name}`; const data: TGApp.Plugins.UIAF.Achievement[] = JSON.parse(await readTextFile(filePath)); await TSUserAchi.mergeUiaf(data, uid); } catch (e) { await TGLogger.Error(`[UIAF][RESTORE] 恢复成就数据${file.name} `); await TGLogger.Error(`${e}`); + return false; } } - return false; + return true; } /** diff --git a/src/plugins/Sqlite/modules/userGacha.ts b/src/plugins/Sqlite/modules/userGacha.ts index f7b234ac..38ae4093 100644 --- a/src/plugins/Sqlite/modules/userGacha.ts +++ b/src/plugins/Sqlite/modules/userGacha.ts @@ -4,7 +4,12 @@ * @since Beta v0.6.0 */ +import { path } from "@tauri-apps/api"; +import { exists, mkdir, readDir } from "@tauri-apps/plugin-fs"; + import { AppCharacterData, AppWeaponData } from "../../../data/index.js"; +import TGLogger from "../../../utils/TGLogger.js"; +import { exportUigfData, readUigfData, verifyUigfData } from "../../../utils/UIGF.js"; import TGSqlite from "../index.js"; type gachaItemTypeRes = @@ -177,6 +182,62 @@ async function mergeUIGF4(data: TGApp.Plugins.UIGF.GachaHk4e): Promise { } } +/** + * @description 备份祈愿数据 + * @since Beta v0.6.0 + * @param {string} dir - 备份目录 + * @returns {Promise} + */ +async function backUpUigf(dir: string): Promise { + if (!(await exists(dir))) { + await TGLogger.Warn("不存在指定的祈愿备份目录,即将创建"); + await mkdir(dir, { recursive: true }); + } + const uidList = await getUidList(); + for (const uid of uidList) { + const dataGacha = await getGachaRecords(uid); + const savePath = `${dir}${path.sep()}UIGF_${uid}.json`; + await exportUigfData(uid, dataGacha, savePath); + } + await TGLogger.Info("祈愿数据备份完成"); +} + +/** + * @description 恢复祈愿数据 + * @since Beta v0.6.0 + * @param {string} dir - 备份目录 + * @returns {Promise} + */ +async function restoreUigf(dir: string): Promise { + if (!(await exists(dir))) { + await TGLogger.Warn("不存在指定的祈愿备份目录"); + return false; + } + const filesRead = await readDir(dir); + // 校验 UIGF_xxx.json 文件 + const fileRegex = /^UIGF_\d+\.json$/; + const files = filesRead.filter((item) => item.isFile && fileRegex.test(item.name)); + if (files.length === 0) return false; + try { + for (const file of files) { + const filePath = `${dir}${path.sep()}${file.name}`; + const check = await verifyUigfData(filePath); + if (!check) { + await TGLogger.Warn(`UIGF数据校验失败${filePath}`); + continue; + } + const data = await readUigfData(filePath); + const uid = data.info.uid; + await mergeUIGF(uid, data.list); + } + } catch (e) { + await TGLogger.Error(`恢复祈愿数据失败${dir}`); + await TGLogger.Error(typeof e === "string" ? e : JSON.stringify(e)); + return false; + } + return true; +} + const TSUserGacha = { getUidList, getGachaCheck, @@ -185,6 +246,8 @@ const TSUserGacha = { deleteGachaRecords, mergeUIGF, mergeUIGF4, + backUpUigf, + restoreUigf, }; export default TSUserGacha; diff --git a/src/utils/dataBS.ts b/src/utils/dataBS.ts index 209dc43a..5af1b64f 100644 --- a/src/utils/dataBS.ts +++ b/src/utils/dataBS.ts @@ -3,18 +3,15 @@ * @description 用户数据的备份、恢复、迁移 * @since Beta v0.6.0 */ - -import { path } from "@tauri-apps/api"; -import { exists, mkdir, writeTextFile, readDir, readTextFile } from "@tauri-apps/plugin-fs"; +import { exists, mkdir } from "@tauri-apps/plugin-fs"; import showSnackbar from "../components/func/snackbar.js"; -import TGSqlite from "../plugins/Sqlite/index.js"; import TSUserAbyss from "../plugins/Sqlite/modules/userAbyss.js"; +import TSUserAccount from "../plugins/Sqlite/modules/userAccount.js"; import TSUserAchi from "../plugins/Sqlite/modules/userAchi.js"; import TSUserGacha from "../plugins/Sqlite/modules/userGacha.js"; import TGLogger from "./TGLogger.js"; -import { exportUigfData, readUigfData, verifyUigfData } from "./UIGF.js"; /** * @description 备份用户数据 @@ -24,23 +21,13 @@ import { exportUigfData, readUigfData, verifyUigfData } from "./UIGF.js"; */ export async function backUpUserData(dir: string): Promise { if (!(await exists(dir))) { - console.log("备份目录不存在,创建备份目录"); + await TGLogger.Warn("备份数据不存在,即将创建"); await mkdir(dir, { recursive: true }); } - // 备份成就 await TSUserAchi.backupUiaf(dir); - // 备份 ck - const dataCK = await TGSqlite.getCookie(); - await writeTextFile(`${dir}${path.sep()}cookie.json`, JSON.stringify(dataCK)); - // 备份深渊数据 + await TSUserAccount.account.backup(dir); await TSUserAbyss.backupAbyss(dir); - // 备份祈愿数据 - const uidList = await TSUserGacha.getUidList(); - for (const uid of uidList) { - const dataGacha = await TSUserGacha.getGachaRecords(uid); - const savePath = `${dir}${path.sep()}UIGF_${uid}.json`; - await exportUigfData(uid, dataGacha, savePath); - } + await TSUserGacha.backUpUigf(dir); } /** @@ -55,56 +42,25 @@ export async function restoreUserData(dir: string): Promise { showSnackbar({ text: "备份目录不存在", color: "error" }); return; } - const filesRead = await readDir(dir); - const files = filesRead.filter((item) => item.isFile && item.name.endsWith(".json")); - await TGLogger.Info(`[DataBS][restoreUserData] files: ${JSON.stringify(files)}`); const restoreAchi = await TSUserAchi.restoreUiaf(dir); if (!restoreAchi) { showSnackbar({ text: `成就数据恢复失败`, color: "error" }); errNum++; } - // 恢复 ck - const ckFind = files.find((item) => item.name === "cookie.json"); - if (ckFind) { - try { - const dataCK = await readTextFile(ckFind.name); - await TGSqlite.saveAppData("cookie", JSON.stringify(JSON.parse(dataCK))); - await TGLogger.Info(`[DataBS][restoreUserData] Cookie 数据恢复成功`); - } catch (e) { - showSnackbar({ text: `Cookie 数据恢复失败 ${e}`, color: "error" }); - await TGLogger.Error(`[DataBS][restoreUserData] Cookie 数据恢复失败 ${e}`); - errNum++; - } - } else { - showSnackbar({ text: "Cookie 数据恢复失败,备份文件不存在", color: "warn" }); - await TGLogger.Warn(`[DataBS][restoreUserData] 未检测到 Cookie 数据备份文件`); - await new Promise((resolve) => setTimeout(resolve, 1500)); + const restoreAccount = await TSUserAccount.account.restore(dir); + if (!restoreAccount) { + showSnackbar({ text: "Cookie 数据恢复失败", color: "error" }); + errNum++; } - // 恢复深渊数据 const restoreAbyss = await TSUserAbyss.restoreAbyss(dir); if (!restoreAbyss) { showSnackbar({ text: "深渊数据恢复失败", color: "error" }); errNum++; } - // 恢复祈愿数据 - const reg = /UIGF_(\d+).json/; - const dataGachaList = files.filter((item) => reg.test(item.name)); - for (const item of dataGachaList) { - const check = await verifyUigfData(item.name); - if (!check) { - errNum++; - continue; - } - const data = await readUigfData(item.name); - const uid = data.info.uid; - try { - await TSUserGacha.mergeUIGF(uid, data.list); - await TGLogger.Info(`[DataBS][restoreUserData] UID: ${uid} 祈愿数据恢复成功`); - } catch (e) { - showSnackbar({ text: `UID: ${uid} 祈愿数据恢复失败`, color: "error" }); - await TGLogger.Error(`[DataBS][restoreUserData] UID: ${uid} 祈愿数据恢复失败 ${e}`); - errNum++; - } + const restoreGacha = await TSUserGacha.restoreUigf(dir); + if (!restoreGacha) { + showSnackbar({ text: "祈愿数据恢复失败", color: "error" }); + errNum++; } if (errNum === 0) { showSnackbar({ text: "数据恢复成功", color: "success" });