diff --git a/config.example.json b/config.example.jsonc similarity index 94% rename from config.example.json rename to config.example.jsonc index 5b173b8..ed7ec6e 100644 --- a/config.example.json +++ b/config.example.jsonc @@ -8,5 +8,5 @@ // Maximum task count "max_task_count": 1, // Fetch page data from Multi-Page Viewer - "mpv": false, + "mpv": false } diff --git a/db.ts b/db.ts index e288460..55269ee 100644 --- a/db.ts +++ b/db.ts @@ -64,7 +64,25 @@ type Tag = { id: number; tag: string; }; -const ALL_TABLES = ["version", "task", "gmeta", "pmeta", "tag", "gtag"]; +export type EhFile = { + id: number; + gid: number; + token: string; + path: string; + width: number; + height: number; + is_original: boolean; +}; +export type EhFileRaw = { + id: number; + gid: number; + token: string; + path: string; + width: number; + height: number; + is_original: number; +}; +const ALL_TABLES = ["version", "task", "gmeta", "pmeta", "tag", "gtag", "file"]; const VERSION_TABLE = `CREATE TABLE version ( id TEXT, ver TEXT, @@ -114,6 +132,15 @@ const GTAG_TABLE = `CREATE TABLE gtag ( id INT, PRIMARY KEY (gid, id) );`; +const FILE_TABLE = `CREATE TABLE file ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + gid INT, + token TEXT, + path TEXT, + width INT, + height INT, + is_original BOOLEAN +);`; export class EhDb { db; @@ -189,6 +216,9 @@ export class EhDb { if (!this.#exist_table.has("gtag")) { this.db.execute(GTAG_TABLE); } + if (!this.#exist_table.has("file")) { + this.db.execute(FILE_TABLE); + } this.#updateExistsTable(); } #read_version() { @@ -260,6 +290,32 @@ export class EhDb { this.db.query("INSERT INTO gtag VALUES (?, ?);", [gid, id]); } } + add_file(f: EhFile, overwrite = true) { + if (overwrite) { + const ofiles = this.get_files(f.gid, f.token); + if (ofiles.length) { + const o = ofiles[0]; + f.id = o.id; + ofiles.slice(1).forEach((o) => { + this.delete_file(o); + }); + } + } + if (f.id) { + this.db.query( + "INSERT OR REPLACE INTO file VALUES (:id, :gid, :token, :path, :width, :height, :is_original);", + f, + ); + return structuredClone(f); + } else { + this.db.query( + "INSERT INTO file (gid, token, path, width, height, is_original) VALUES (?, ?, ?, ?, ?, ?);", + [f.gid, f.token, f.path, f.width, f.height, f.is_original], + ); + const s = this.get_files(f.gid, f.token); + return s[s.length - 1]; + } + } add_pmeta(pmeta: PMeta) { this.db.queryEntries( "INSERT OR REPLACE INTO pmeta VALUES (:gid, :index, :token, :name, :width, :height)", @@ -324,6 +380,14 @@ export class EhDb { } } } + convert_file(f: EhFileRaw[]) { + return f.map((m) => { + const b = m.is_original !== 0; + const t = m; + t.is_original = b; + return t; + }); + } convert_gmeta(m: GMetaRaw[]): GMeta[] { return m.map((m) => { const b = m.expunged !== 0; @@ -332,6 +396,9 @@ export class EhDb { return t; }); } + delete_file(f: EhFile) { + this.db.query("DELETE FROM file WHERE id = ?;", [f.id]); + } delete_task(task: Task) { return this.transaction(() => { this.db.query("DELETE FROM task WHERE id = ?;", [task.id]); @@ -353,6 +420,12 @@ export class EhDb { if (!this.#dblock) return; eval(`Deno.funlockSync(${this.#dblock.rid});`); } + get_files(gid: number, token: string) { + return this.convert_file(this.db.queryEntries( + "SELECT * FROM file WHERE gid = ? AND token = ?;", + [gid, token], + )); + } get_gmeta_by_gid(gid: number) { const s = this.convert_gmeta( this.db.queryEntries( diff --git a/db_test.ts b/db_test.ts index f103053..a1019c3 100644 --- a/db_test.ts +++ b/db_test.ts @@ -1,5 +1,5 @@ import { assertEquals } from "std/testing/asserts.ts"; -import { EhDb, GMeta, PMeta } from "./db.ts"; +import { EhDb, EhFile, GMeta, PMeta } from "./db.ts"; import { TaskType } from "./task.ts"; import { remove_if_exists } from "./test_base.ts"; import { sure_dir } from "./utils.ts"; @@ -54,5 +54,31 @@ Deno.test("DbTest", async () => { const tags = new Set(["std", "df2", "ef3"]); await db.add_gtag(1, tags); assertEquals(tags, db.get_gtags(1)); + const f: EhFile = { + id: 0, + gid: 1, + token: "s", + path: "a.png", + width: 1280, + height: 720, + is_original: true, + }; + const f2 = db.add_file(f); + f.id = f2.id; + assertEquals(f, f2); + f.path = "df.png"; + f.id = 0; + const f3 = db.add_file(f); + f.id = f2.id; + assertEquals(f, f3); + f3.path = "s.ppp"; + f3.id = 0; + const f4 = db.add_file(f3, false); + f3.id = f4.id; + assertEquals(f3, f4); + assertEquals(f.id, f2.id); + assertEquals(db.get_files(1, "s").length, 2); + db.add_file(f3); + assertEquals(db.get_files(1, "s").length, 1); db.close(); });