♻️ 合并 TGSql 与 TGSqlite,重构代码作为 Plugin 使用

This commit is contained in:
BTMuli
2023-05-31 17:32:00 +08:00
parent 1a9ca12363
commit 51058c6825
8 changed files with 477 additions and 434 deletions

View File

@@ -1,67 +1,59 @@
/**
* @file utils TGSqlite.ts
* @description
* @file plugins Sqlite index.ts
* @description Sqlite
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.6
* @since Alpha v0.2.0
*/
// tauri
import Database from "tauri-plugin-sql-api";
// utils
import { importUIAFData, initSQLiteData, initSQLiteTable } from "./TGSql";
import minifySql from "./minifySql";
import { getUiafStatus } from "./UIAF";
import initDataSql from "./sql/initData";
import initTableSql from "./sql/initTable";
import { importUIAFData } from "./sql/updateData";
import { getUiafStatus } from "../../utils/UIAF";
import { insertAppData, insertGameAccountData } from "./sql/insertData";
class TGSqlite {
class Sqlite {
/**
* @description
* @private
* @type {string}
* @memberOf TGSqlite
* @since Alpha v0.1.4
*/
* @description
* @since Alpha v0.2.0
* @private
*/
private readonly dbPath: string = "sqlite:tauri-genshin.db";
/**
* @description
* @private
* @type {string[]}
* @memberOf TGSqlite
* @since Alpha v0.1.4
*/
* @description
* @since Alpha v0.2.0
* @private
*/
private readonly tables: string[] = [
"AppData",
"Achievements",
"AchievementSeries",
"AppData",
"GameAccount",
"NameCard",
"SprialAbyss",
];
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.4
* @returns {Promise<void>}
* @memberOf TGSqlite
*/
public async init (): Promise<void> {
* @description
* @since Alpha v0.2.0
* @returns {Promise<void>}
*/
public async initDB (): Promise<void> {
const db = await Database.load(this.dbPath);
const sqlT = initSQLiteTable();
for (const item of sqlT) {
await db.execute(item);
}
const sqlD = await initSQLiteData();
for (const item of sqlD) {
const sql = [...initTableSql(), ...await initDataSql()];
for (const item of sql) {
await db.execute(item);
}
await db.close();
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.4
* @returns {Promise<TGApp.Sqlite.AppData.Item[]>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<TGApp.Sqlite.AppData.Item[]>}
*/
public async getAppData (): Promise<TGApp.Sqlite.AppData.Item[]> {
const db = await Database.load(this.dbPath);
const sql = "SELECT * FROM AppData;";
@@ -71,11 +63,10 @@ class TGSqlite {
}
/**
* @description cookie
* @memberOf TGSqlite
* @since Alpha v0.2.0
* @returns {Promise<Record<string, string>>}
*/
* @description cookie
* @since Alpha v0.2.0
* @returns {Promise<Record<string, string>>}
*/
public async getCookie (): Promise<Record<string, string>> {
const db = await Database.load(this.dbPath);
const sql = "SELECT value FROM AppData WHERE key='cookie';";
@@ -86,29 +77,14 @@ class TGSqlite {
/**
* @description Account
* @memberOf TGSqlite
* @since Alpha v0.1.5
* @since Alpha v0.2.0
* @param {TGApp.User.Account.Game[]} accounts
* @returns {Promise<void>}
*/
public async insertAccount (accounts: TGApp.User.Account.Game[]): Promise<void> {
const db = await Database.load(this.dbPath);
for (const a of accounts) {
const isChosen = a.is_chosen ? 1 : 0;
const isOfficial = a.is_official ? 1 : 0;
const sql = minifySql(`
INSERT INTO GameAccount (gameBiz, gameUid, isChosen, isOfficial, level, nickname, region, regionName, updated)
VALUES ('${a.game_biz}', '${a.game_uid}', ${isChosen}, ${isOfficial}, '${a.level}', '${a.nickname}',
'${a.region}', '${a.region_name}', datetime('now', 'localtime'))
ON CONFLICT(gameBiz, gameUid) DO UPDATE SET
isChosen = ${isChosen},
isOfficial = ${isOfficial},
level = ${a.level},
nickname = '${a.nickname}',
region = '${a.region}',
regionName = '${a.region_name}',
updated = datetime('now', 'localtime');
`);
const sql = insertGameAccountData(a);
await db.execute(sql);
}
await db.close();
@@ -116,7 +92,6 @@ class TGSqlite {
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.2.0
* @returns {Promise<TGApp.Sqlite.Account.Game|false>}
*/
@@ -129,33 +104,27 @@ class TGSqlite {
}
/**
* @description appData
* @memberOf TGSqlite
* @since Alpha v0.1.5
* @param {string} key
* @param {string} value
* @returns {Promise<void>}
*/
* @description appData
* @since Alpha v0.2.0
* @param {string} key
* @param {string} value
* @returns {Promise<void>}
*/
public async saveAppData (key: string, value: string): Promise<void> {
const db = await Database.load(this.dbPath);
const sql = minifySql(`
INSERT INTO AppData (key, value, updated)
VALUES ('${key}', '${value}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${value}',updated = datetime('now', 'localtime');
`);
const sql = insertAppData(key, value);
await db.execute(sql);
await db.close();
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.4
* @returns {Promise<void>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<void>}
*/
public async update (): Promise<void> {
const db = await Database.load(this.dbPath);
const sqlD = await initSQLiteData();
const sqlD = await initDataSql();
for (const item of sqlD) {
await db.execute(item);
}
@@ -163,33 +132,30 @@ class TGSqlite {
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.2.0
* @returns {Promise<boolean>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<boolean>}
*/
public async check (): Promise<boolean> {
const db = await Database.load(this.dbPath);
let isVerified = false;
// 检测数据表是否都存在
const sqlT = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";
const res: Array<{ name: string }> = await db.select(sqlT);
// 考虑到 sqlite_sequence 表,所以需要 +1
await db.close();
if (res.length === this.tables.length) {
if (this.tables.every((item) => res.map((i) => i.name).includes(item))) {
isVerified = true;
}
}
await db.close();
return isVerified;
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.4
* @returns {Promise<void>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<void>}
*/
public async reset (): Promise<void> {
const db = await Database.load(this.dbPath);
this.tables.map(async (item) => {
@@ -197,15 +163,14 @@ class TGSqlite {
await db.execute(sql);
});
await db.close();
await this.init();
await this.initDB();
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.5
* @returns {Promise<TGApp.Sqlite.Achievement.SeriesTable[]>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<TGApp.Sqlite.Achievement.SeriesTable[]>}
*/
public async getAchievementSeries (): Promise<TGApp.Sqlite.Achievement.SeriesTable[]> {
const db = await Database.load(this.dbPath);
const sql = "SELECT * FROM AchievementSeries ORDER BY `order`;";
@@ -215,12 +180,11 @@ class TGSqlite {
}
/**
* @description
* @memberOf TGSqlite
* @since Alpha v0.1.5
* @param {number} seriesId ID
* @returns {Promise<TGApp.Sqlite.NameCard.Item>}
*/
* @description
* @since Alpha v0.2.0
* @param {number} seriesId ID
* @returns {Promise<TGApp.Sqlite.NameCard.Item>}
*/
public async getNameCard (seriesId: number): Promise<TGApp.Sqlite.NameCard.Item> {
const db = await Database.load(this.dbPath);
const sql = `SELECT * FROM NameCard WHERE name = (SELECT nameCard FROM AchievementSeries WHERE id = ${seriesId});`;
@@ -230,12 +194,11 @@ class TGSqlite {
}
/**
* @description
* @memberOf TGSqlite
* @param {number} [seriesId] ID
* @since Alpha v0.1.5
* @returns {Promise<TGApp.Sqlite.Achievement.SingleTable[]>}
*/
* @description
* @since Alpha v0.2.0
* @param {number} [seriesId] ID
* @returns {Promise<TGApp.Sqlite.Achievement.SingleTable[]>}
*/
public async getAchievements (seriesId?: number): Promise<TGApp.Sqlite.Achievement.SingleTable[]> {
const db = await Database.load(this.dbPath);
let sql;
@@ -250,11 +213,10 @@ class TGSqlite {
}
/**
* @description
* @since Alpha v0.1.4
* @memberOf TGSqlite
* @returns {Promise<{total:number,fin:number}>}
*/
* @description
* @since Alpha v0.2.0
* @returns {Promise<{total:number,fin:number}>}
*/
public async getAchievementsOverview (): Promise<{ total: number, fin: number }> {
const db = await Database.load(this.dbPath);
const sql = "SELECT SUM(totalCount) AS total, SUM(finCount) AS fin FROM AchievementSeries;";
@@ -265,8 +227,7 @@ class TGSqlite {
/**
* @description
* @since Alpha v0.1.6
* @memberOf TGSqlite
* @since Alpha v0.2.0
* @returns {Promise<string>}
*/
public async getLatestAchievementVersion (): Promise<string> {
@@ -278,12 +239,11 @@ class TGSqlite {
}
/**
* @description
* @memberOf TGSqlite
* @param {string} keyword
* @since Alpha v0.1.5
* @returns {Promise<TGApp.Sqlite.Achievement.SingleTable[]>}
*/
* @description
* @since Alpha v0.2.0
* @param {string} keyword
* @returns {Promise<TGApp.Sqlite.Achievement.SingleTable[]>}
*/
public async searchAchievements (keyword: string): Promise<TGApp.Sqlite.Achievement.SingleTable[]> {
const db = await Database.load(this.dbPath);
let sql;
@@ -300,12 +260,11 @@ class TGSqlite {
}
/**
* @description UIAF
* @memberOf TGSqlite
* @param {TGApp.Plugins.UIAF.Achievement[]} achievements UIAF
* @since Alpha v0.1.4
* @returns {Promise<void>}
*/
* @description UIAF
* @since Alpha v0.2.0
* @param {TGApp.Plugins.UIAF.Achievement[]} achievements UIAF
* @returns {Promise<void>}
*/
public async mergeUIAF (achievements: TGApp.Plugins.UIAF.Achievement[]): Promise<void> {
const db = await Database.load(this.dbPath);
const sql = importUIAFData(achievements);
@@ -316,11 +275,10 @@ class TGSqlite {
}
/**
* @description UIAF
* @memberOf TGSqlite
* @since Alpha v0.1.4
* @returns {Promise<TGApp.Plugins.UIAF.Achievement[]>}
*/
* @description UIAF
* @since Alpha v0.2.0
* @returns {Promise<TGApp.Plugins.UIAF.Achievement[]>}
*/
public async getUIAF (): Promise<TGApp.Plugins.UIAF.Achievement[]> {
const db = await Database.load(this.dbPath);
const sql = "SELECT * FROM Achievements WHERE isCompleted = 1 OR progress > 0";
@@ -341,4 +299,6 @@ class TGSqlite {
}
}
export default new TGSqlite();
const TGSqlite = new Sqlite();
export default TGSqlite;

View File

@@ -0,0 +1,88 @@
-- @file plugins Sqlite sql createTable.sql
-- @brief sqlite数据库创建表语句
-- @author BTMuli <bt-muli@outlook.com>
-- @since Alpha v0.2.0
-- @brief 创建成就数据表
create table if not exists Achievements
(
id integer primary key,
series integer,
`order` integer,
name text,
description text,
reward integer,
isCompleted boolean default false,
completedTime text,
progress integer default 0,
version text,
updated text
);
-- @brief 创建成就系列数据表
create table if not exists AchievementSeries
(
id integer primary key,
`order` integer,
name text,
version text,
totalCount integer default 0,
finCount integer default 0,
nameCard text,
updated text
);
-- @brief 创建应用数据表
create table if not exists AppData
(
key text primary key,
value text,
updated text
);
-- @brief 创建游戏账号数据表
create table if not exists GameAccount
(
gameBiz text,
gameUid text,
isChosen boolean,
isOfficial boolean,
level integer,
nickname text,
region text,
regionName text,
updated text,
primary key (gameBiz, gameUid)
);
-- @brief 名片数据表
create table if not exists NameCard
(
name text,
desc text,
type text,
source text,
updated text,
primary key (name, type)
);
-- @brief 创建深渊数据表
create table if not exists SpiralAbyss
(
id integer primary key,
startTime text,
endTime text,
totalBattleTimes integer,
totalWinTimes integer,
maxFloor text,
totalStar integer,
isUnlock boolean,
revealRank text,
defeatRank text,
damageRank text,
takeDamageRank text,
normalSkillRank text,
energySkillRank text,
floors text,
updated text
);

View File

@@ -0,0 +1,40 @@
-- @file plugins Sqlite sql createTrigger.sql
-- @brief 创建触发器
-- @author BTMuli <bt-muli@outlook.com>
-- @since Alpha v0.2.0
-- @brief 成就表相关
create trigger if not exists insertAchievement
after insert
on Achievements
for each row
begin
update AchievementSeries
set totalCount = totalCount + 1,
updated = datetime('now', 'localtime')
where id = new.series;
update AchievementSeries
set version = new.version,
updated = datetime('now', 'localtime')
where id = new.series
and new.version > version;
end;
create trigger if not exists updateAchievement
after update
on Achievements
for each row
begin
update AchievementSeries
set updated = datetime('now', 'localtime'),
finCount = finCount + 1
where id = new.series
and old.isCompleted = 0
and new.isCompleted = 1;
update AchievementSeries
set updated = datetime('now', 'localtime'),
finCount = finCount - 1
where id = new.series
and old.isCompleted = 1
and new.isCompleted = 0;
end;

View File

@@ -0,0 +1,90 @@
/**
* @file plugins Sqlite sql initData.ts
* @description Sqlite 初始化数据 sql 语句
* @author BTMuli <bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
// tauri
import { app } from "@tauri-apps/api";
// utils
import { getBuildTime } from "../../../utils/TGBuild";
import { insertAchievementData, insertAchievementSeriesData, insertNameCardData } from "./insertData";
import {
AppAchievementsData,
AppAchievementSeriesData,
AppNameCardsData,
} from "../../../data";
/**
* @description 初始化应用表数据
* @since Alpha v0.2.0
* @returns {Promise<string[]>} sql
*/
async function initAppData (): Promise<string[]> {
const sqlRes: string[] = [];
const appVersion = await app.getVersion();
const buildTime = getBuildTime();
// 初始化应用版本
sqlRes.push(`
INSERT INTO AppData (key, value, updated)
VALUES ('appVersion', '${appVersion}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${appVersion}', updated = datetime('now', 'localtime');`,
);
// 初始化应用数据更新时间
sqlRes.push(`
INSERT INTO AppData (key, value, updated)
VALUES ('dataUpdated', '${buildTime}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${buildTime}', updated = datetime('now', 'localtime');`,
);
// 初始化 cookie
sqlRes.push(`
INSERT INTO AppData (key, value, updated)
VALUES ('cookie', '{}', datetime('now', 'localtime'))
ON CONFLICT(key) DO NOTHING;`,
);
return sqlRes;
}
/**
* @description 初始化成就系列数据
* @since Alpha v0.2.0
* @returns {string[]} sql
*/
function initAchievementSeriesData (): string[] {
return AppAchievementSeriesData.map((item) => insertAchievementSeriesData(item));
}
/**
* @description 初始化成就数据
* @since Alpha v0.2.0
* @returns {string[]} sql
*/
function initAchievementData (): string[] {
return AppAchievementsData.map((item) => insertAchievementData(item));
}
/**
* @description 初始化应用名片数据
* @since Alpha v0.2.0
* @returns {string[]} sql
*/
function initNameCardData (): string[] {
return AppNameCardsData.map((item) => insertNameCardData(item));
}
/**
* @description 初始化数据
* @since Alpha v0.2.0
* @returns {Promise<string[]>} sql
*/
async function initDataSql (): Promise<string[]> {
const sqlRes: string[] = [];
sqlRes.push(...await initAppData());
sqlRes.push(...initAchievementSeriesData());
sqlRes.push(...initAchievementData());
sqlRes.push(...initNameCardData());
return sqlRes;
}
export default initDataSql;

View File

@@ -0,0 +1,24 @@
/**
* @file plugins Sqlite sql initTable.ts
* @description Sqlite 初始化数据 sql 语句
* @author BTMuli <bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
// data
import createTable from "./createTable.sql?raw";
import createTrigger from "./createTrigger.sql?raw";
/**
* @description 初始化数据库表
* @since Alpha v0.2.0
* @returns {string[]} sql
*/
function initTableSql (): string[] {
return [
createTable,
createTrigger,
];
}
export default initTableSql;

View File

@@ -0,0 +1,104 @@
/**
* @file plugins Sqlite sql insertData.ts
* @description Sqlite 插入数据 sql 语句
* @author BTMuli <bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
/**
* @description 插入成就数据
* @since Alpha v0.2.0
* @param {TGApp.App.Achievement.Item} data 成就数据
* @returns {string} sql
*/
export function insertAchievementData (data: TGApp.App.Achievement.Item): string {
return `
INSERT INTO Achievements (id, series, "order", name, description, reward, completedTime, version, updated)
VALUES (${data.id}, ${data.series}, ${data.order}, '${data.name}', '${data.description}', ${data.reward}, '',
'${data.version}', datetime('now', 'localtime'))
ON CONFLICT(id) DO UPDATE
SET series = ${data.series},
"order" = ${data.order},
name = '${data.name}',
description = '${data.description}',
reward = '${data.reward}',
version = '${data.version}',
updated = datetime('now', 'localtime');
`;
}
/**
* @description 插入成就系列数据
* @since Alpha v0.2.0
* @param {TGApp.App.Achievement.Series} data 成就系列数据
* @returns {string} sql
*/
export function insertAchievementSeriesData (data: TGApp.App.Achievement.Series): string {
return `
INSERT INTO AchievementSeries (id, "order", name, version, nameCard, updated)
VALUES (${data.id}, ${data.order}, '${data.name}', '${data.version}','${data.card}', datetime('now', 'localtime'))
ON CONFLICT(id) DO UPDATE
SET name = '${data.name}',
"order" = ${data.order},
version = '${data.version}',
nameCard = '${data.card}',
updated = datetime('now', 'localtime');
`;
}
/**
* @description 插入应用数据
* @since Alpha v0.2.0
* @param {string} key 键
* @param {string} value 值
* @returns {string} sql
*/
export function insertAppData (key: string, value: string): string {
return `
INSERT INTO AppData (key, value, updated)
VALUES ('${key}', '${value}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${value}', updated = datetime('now', 'localtime');
`;
}
/**
* @description 插入游戏账号数据
* @since Alpha v0.2.0
* @param {TGApp.User.Account.Game} data 游戏账号数据
* @returns {string} sql
*/
export function insertGameAccountData (data: TGApp.User.Account.Game): string {
const isChosen = data.is_chosen ? 1 : 0;
const isOfficial = data.is_official ? 1 : 0;
return `
INSERT INTO GameAccount (gameBiz, gameUid, isChosen, isOfficial, level, nickname, region, regionName, updated)
VALUES ('${data.game_biz}', '${data.game_uid}', ${isChosen}, ${isOfficial}, ${data.level}, '${data.nickname}',
'${data.region}', '${data.region_name}', datetime('now', 'localtime'))
ON CONFLICT(gameBiz, gameUid) DO UPDATE
SET isChosen = ${isChosen},
isOfficial = ${isOfficial},
level = ${data.level},
nickname = '${data.nickname}',
region = '${data.region}',
regionName = '${data.region_name}',
updated = datetime('now', 'localtime');
`;
}
/**
* @description 插入名片数据
* @since Alpha v0.2.0
* @param {TGApp.App.NameCard.Item} data 名片数据
* @returns {string} sql
*/
export function insertNameCardData (data: TGApp.App.NameCard.Item): string {
return `
INSERT INTO NameCard (name, "desc", type, source, updated)
VALUES ('${data.name}', '${data.desc}', '${data.type}', '${data.source}', datetime('now', 'localtime'))
ON CONFLICT(name) DO UPDATE
SET "desc" = '${data.desc}',
type = '${data.type}',
source = '${data.source}',
updated = datetime('now', 'localtime');
`;
}

View File

@@ -0,0 +1,37 @@
/**
* @file plugins Sqlite sql updateData.ts
* @description 更新数据
* @author BTMuli <bt-muli@outlook.com>
* @since Alpha v0.2.0
*/
/**
* @description 导入UIAF数据
* @since Alpha v0.1.5
* @param {TGApp.Plugins.UIAF.Achievement[]} data
* @returns {string[]} sql
*/
export function importUIAFData (data: TGApp.Plugins.UIAF.Achievement[]): string[] {
const sqlRes: string[] = [];
data.map((achievement) => {
let sql;
// 获取完成状态
const isCompleted = achievement.status === 2 || achievement.status === 3;
if (isCompleted) {
const completedTime = new Date(achievement.timestamp * 1000).toISOString().replace("T", " ").slice(0, 19);
sql = `
UPDATE Achievements
SET isCompleted = 1, completedTime = '${completedTime}', progress = ${achievement.current}, updated = datetime('now', 'localtime')
WHERE id = ${achievement.id} AND (isCompleted = 0 OR completedTime != '${completedTime}' OR progress != ${achievement.current});
`;
} else {
sql = `
UPDATE Achievements
SET progress = ${achievement.current}, updated = datetime('now', 'localtime')
WHERE id = ${achievement.id} AND progress != ${achievement.current};
`;
}
return sqlRes.push(sql);
});
return sqlRes;
}

View File

@@ -1,300 +0,0 @@
/**
* @file utils TGSql.ts
* @description 数据库sql语句
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.5
*/
// tauri
import { app } from "@tauri-apps/api";
// utils
import { getBuildTime } from "./TGBuild";
import minifySql from "./minifySql";
import { AppAchievementsData, AppAchievementSeriesData, AppNameCardsData } from "../data";
/**
* @description 初始化应用数据表
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initAppTable (): string[] {
const sqlRes = [];
// 创建应用数据表
sqlRes.push(minifySql(`
CREATE TABLE IF NOT EXISTS AppData
(
key TEXT PRIMARY KEY,
value TEXT DEFAULT NULL,
updated TEXT DEFAULT NULL
);
`));
return sqlRes;
}
/**
* @description 初始化游戏账号数据表
* @since Alpha v0.1.5
* @see TGApp.Sqlite.Account.Game
* @returns {string[]} sql
*/
function initGameAccountTable (): string[] {
const sqlRes = [];
// 创建游戏账号数据表
sqlRes.push(minifySql(`
CREATE TABLE IF NOT EXISTS GameAccount
(
gameBiz TEXT NOT NULL,
gameUid TEXT NOT NULL,
isChosen BOOLEAN DEFAULT 0,
isOfficial BOOLEAN DEFAULT 0,
level INTEGER DEFAULT 0,
nickname TEXT DEFAULT NULL,
region TEXT DEFAULT NULL,
regionName TEXT DEFAULT NULL,
updated TEXT DEFAULT NULL,
PRIMARY KEY (gameBiz, gameUid)
);
`));
return sqlRes;
}
/**
* @description 初始化成就系列数据表
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initAchievementSeriesTable (): string[] {
const sqlRes = [];
// 创建成就系列数据表
sqlRes.push(minifySql(`
CREATE TABLE IF NOT EXISTS AchievementSeries
(
id INTEGER PRIMARY KEY,
"order" INTEGER,
name TEXT DEFAULT NULL,
version TEXT DEFAULT NULL,
totalCount INTEGER DEFAULT 0,
finCount INTEGER DEFAULT 0,
icon TEXT NOT NULL,
nameCard TEXT NOT NULL,
updated TEXT DEFAULT NULL
);
`));
return sqlRes;
}
/**
* @description 初始化成就数据表
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initAchievementTable (): string[] {
const sqlRes = [];
// 创建成就数据表
sqlRes.push(minifySql(`
CREATE TABLE IF NOT EXISTS Achievements
(
id INTEGER PRIMARY KEY,
series INTEGER,
"order" INTEGER,
name TEXT DEFAULT NULL,
description TEXT DEFAULT NULL,
reward INTEGER DEFAULT 0,
isCompleted BOOLEAN DEFAULT 0,
completedTime TEXT DEFAULT NULL,
progress INTEGER DEFAULT 0,
version TEXT DEFAULT NULL,
updated TEXT DEFAULT NULL
);
`));
// 创建触发器
sqlRes.push(minifySql(`
CREATE TRIGGER IF NOT EXISTS updateAchievement
AFTER UPDATE ON Achievements
FOR EACH ROW
BEGIN
UPDATE AchievementSeries SET finCount = finCount + 1, updated = datetime('now', 'localtime')
WHERE id = NEW.series AND NEW.isCompleted = 1 AND OLD.isCompleted = 0;
UPDATE AchievementSeries SET finCount = finCount - 1, updated = datetime('now', 'localtime')
WHERE id = NEW.series AND NEW.isCompleted = 0 AND OLD.isCompleted = 1;
END;
`));
sqlRes.push(minifySql(`
CREATE TRIGGER IF NOT EXISTS insertAchievement
AFTER INSERT ON Achievements
FOR EACH ROW
BEGIN
UPDATE AchievementSeries SET totalCount = totalCount + 1, updated = datetime('now', 'localtime')
WHERE id = NEW.series;
UPDATE AchievementSeries SET version = NEW.version, updated = datetime('now', 'localtime')
WHERE id = NEW.series AND NEW.version > version;
END;
`));
return sqlRes;
}
/**
* @description 初始化名片数据表
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initNameCardTable (): string[] {
const sqlRes = [];
// 创建名片数据表
sqlRes.push(minifySql(`
CREATE TABLE IF NOT EXISTS NameCard
(
name TEXT PRIMARY KEY,
"desc" TEXT DEFAULT NULL,
icon TEXT NOT NULL,
bg TEXT NOT NULL,
profile TEXT NOT NULL,
type INTEGER DEFAULT 0,
source TEXT DEFAULT NULL,
updated TEXT DEFAULT NULL
);
`));
return sqlRes;
}
/**
* @description 初始化数据库表
* @since Alpha v0.2.0
* @returns {string[]} sql
*/
export function initSQLiteTable (): string[] {
const sqlRes = [];
sqlRes.push(...initAppTable());
sqlRes.push(...initGameAccountTable());
sqlRes.push(...initAchievementSeriesTable());
sqlRes.push(...initAchievementTable());
sqlRes.push(...initNameCardTable());
return sqlRes;
}
/**
* @description 初始化应用数据
* @since Alpha v0.1.5
* @returns {Promise<string[]>} sql
*/
async function initAppData (): Promise<string[]> {
const sqlRes = [];
const appVersion = await app.getVersion();
const buildTime = getBuildTime();
const dataUpdated = buildTime.startsWith("dev") ? buildTime.slice(4) : buildTime;
// 初始化应用版本
sqlRes.push(minifySql(`
INSERT INTO AppData (key, value, updated)
VALUES ('appVersion', '${appVersion}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${appVersion}', updated = datetime('now', 'localtime');
`));
// 初始化应用数据更新时间
sqlRes.push(minifySql(`
INSERT INTO AppData (key, value, updated)
VALUES ('dataUpdated', '${dataUpdated}', datetime('now', 'localtime'))
ON CONFLICT(key) DO UPDATE SET value = '${dataUpdated}', updated = datetime('now', 'localtime');
`));
// 初始化 cookie
sqlRes.push(minifySql(`
INSERT INTO AppData (key, value, updated)
VALUES ('cookie', '{}', datetime('now', 'localtime'))
ON CONFLICT(key) DO NOTHING;
`));
return sqlRes;
}
/**
* @description 初始化成就系列数据
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initAchievementSeriesData (): string[] {
const sqlRes: string[] = [];
AppAchievementSeriesData.map((data) => {
const sql = minifySql(`
INSERT OR IGNORE INTO AchievementSeries (id, "order", name, version, icon, nameCard, updated)
VALUES (${data.id}, ${data.order}, '${data.name}', '${data.version}', '${data.icon}', '${data.card}', datetime('now', 'localtime'));
`);
return sqlRes.push(sql);
});
return sqlRes;
}
/**
* @description 初始化成就数据
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initAchievementData (): string[] {
const sqlRes: string[] = [];
AppAchievementsData.map((data) => {
const sql = minifySql(`
INSERT OR IGNORE INTO Achievements (id, series, "order", name, description, reward, version, updated)
VALUES (${data.id}, ${data.series}, ${data.order}, '${data.name}', '${data.description}', ${data.reward}, '${data.version}', datetime('now', 'localtime'));
`);
return sqlRes.push(sql);
});
return sqlRes;
}
/**
* @description 初始化名片数据
* @since Alpha v0.1.5
* @returns {string[]} sql
*/
function initNameCardData (): string[] {
const sqlRes: string[] = [];
AppNameCardsData.map((data) => {
const sql = minifySql(`
INSERT OR IGNORE INTO NameCard (name, "desc", icon, bg, profile, type, source, updated)
VALUES ('${data.name}', '${data.desc}', '${data.icon}', '${data.bg}', '${data.profile}', ${data.type}, '${data.source}', datetime('now', 'localtime'));
`);
return sqlRes.push(sql);
});
return sqlRes;
}
/**
* @description 初始化数据库数据
* @since Alpha v0.1.4
* @returns {Promise<string[]>} sql
*/
export async function initSQLiteData (): Promise<string[]> {
const sqlRes = [];
sqlRes.push(...initAchievementSeriesData());
sqlRes.push(...initAchievementData());
sqlRes.push(...initNameCardData());
sqlRes.push(...await initAppData());
return sqlRes;
}
/**
* @description 导入UIAF数据
* @since Alpha v0.1.5
* @param {TGApp.Plugins.UIAF.Achievement[]} data
* @returns {string[]} sql
*/
export function importUIAFData (data: TGApp.Plugins.UIAF.Achievement[]): string[] {
const sqlRes: string[] = [];
data.map((achievement) => {
let sql;
// 获取完成状态
const isCompleted = achievement.status === 2 || achievement.status === 3;
if (isCompleted) {
const completedTime = new Date(achievement.timestamp * 1000).toISOString().replace("T", " ").slice(0, 19);
sql = minifySql(`
UPDATE Achievements
SET isCompleted = 1, completedTime = '${completedTime}', progress = ${achievement.current}, updated = datetime('now', 'localtime')
WHERE id = ${achievement.id} AND (isCompleted = 0 OR completedTime != '${completedTime}' OR progress != ${achievement.current});
`);
} else {
sql = minifySql(`
UPDATE Achievements
SET progress = ${achievement.current}, updated = datetime('now', 'localtime')
WHERE id = ${achievement.id} AND progress != ${achievement.current};
`);
}
return sqlRes.push(sql);
});
return sqlRes;
}