118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
import sqlite3 from "better-sqlite3";
|
|
import path from "node:path";
|
|
import fs from "node:fs/promises";
|
|
|
|
const mainDB = sqlite3("tmp/yomitan/index.db");
|
|
mainDB.exec(/* sql */ `
|
|
CREATE TABLE IF NOT EXISTS dictionaries (
|
|
id INTEGER PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
revision TEXT NOT NULL,
|
|
author TEXT,
|
|
[url] TEXT,
|
|
[description] TEXT,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
installed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
lang TEXT NOT NULL, -- custom
|
|
[data] TEXT NOT NULL, -- JSON
|
|
UNIQUE (title, revision)
|
|
);
|
|
`);
|
|
|
|
async function loadFolder(folderpath: string, lang = "ja") {
|
|
const db = sqlite3(path.join(folderpath, "index.db"));
|
|
|
|
db.exec(/* sql */ `
|
|
CREATE TABLE IF NOT EXISTS def_tag_sets (id INTEGER PRIMARY KEY, tags TEXT NOT NULL UNIQUE);
|
|
CREATE TABLE IF NOT EXISTS term_tag_sets (id INTEGER PRIMARY KEY, tags TEXT NOT NULL UNIQUE);
|
|
CREATE TABLE IF NOT EXISTS rule_sets (id INTEGER PRIMARY KEY, rules TEXT NOT NULL UNIQUE);
|
|
CREATE TABLE IF NOT EXISTS terms (
|
|
id INTEGER PRIMARY KEY,
|
|
term TEXT NOT NULL,
|
|
reading TEXT NOT NULL,
|
|
def_tags_id INTEGER,
|
|
rules_id INTEGER,
|
|
score INTEGER,
|
|
glossary TEXT NOT NULL, -- JSON
|
|
glossary_id INTEGER, -- NOT NULL REFERENCES glossaries(id),
|
|
[sequence] INTEGER,
|
|
term_tags_id INTEGER
|
|
);
|
|
CREATE TABLE IF NOT EXISTS term_meta (
|
|
id INTEGER PRIMARY KEY,
|
|
term TEXT NOT NULL,
|
|
mode TEXT NOT NULL,
|
|
reading TEXT,
|
|
[data] TEXT NOT NULL
|
|
);
|
|
CREATE TABLE IF NOT EXISTS tags (
|
|
id INTEGER PRIMARY KEY,
|
|
[name] TEXT NOT NULL,
|
|
category TEXT,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
notes TEXT,
|
|
score INTEGER NOT NULL DEFAULT 0,
|
|
UNIQUE ([name])
|
|
);
|
|
CREATE TABLE IF NOT EXISTS kanji (
|
|
id INTEGER PRIMARY KEY,
|
|
kanji TEXT NOT NULL,
|
|
onyomi TEXT,
|
|
kunyomi TEXT,
|
|
tags TEXT,
|
|
meanings TEXT NOT NULL DEFAULT '[]', -- JSON
|
|
[stats] TEXT NOT NULL DEFAULT '{}' -- JSON
|
|
);
|
|
`);
|
|
|
|
db.exec(/* sql */ `
|
|
CREATE INDEX IF NOT EXISTS terms_term_reading_score ON terms(term, reading, score DESC);
|
|
`);
|
|
|
|
const stmt = (() => {
|
|
let fields = ["title", "revision", "author", "url", "description", "lang"];
|
|
const index = mainDB.prepare(/* sql */ `
|
|
INSERT INTO dictionaries (${fields.map((f) => `[${f}]`).join(",")}, [data])
|
|
VALUES (${fields.map((f) => ":${f}").join(",")}, :data)
|
|
`);
|
|
|
|
fields = [
|
|
"term",
|
|
"reading",
|
|
"def_tags",
|
|
"rules",
|
|
"score",
|
|
"glossary",
|
|
"sequence",
|
|
"term_tags",
|
|
];
|
|
const term = db.prepare(/* sql */ `
|
|
INSERT INTO term (${fields.map((f) => `[${f}]`).join(",")})
|
|
VALUES (${fields.map(() => "?").join(",")})
|
|
`);
|
|
|
|
return {
|
|
index,
|
|
term,
|
|
};
|
|
})();
|
|
|
|
for (const filename of await fs.readdir(folderpath)) {
|
|
try {
|
|
if (!filename.endsWith(".json")) continue;
|
|
|
|
if (filename === "index.json") {
|
|
const obj = JSON.parse(
|
|
await fs.readFile(path.join(folderpath, filename), "utf-8"),
|
|
);
|
|
|
|
stmt.index.run({ lang, data: JSON.stringify(obj), ...obj });
|
|
} else if (filename.startsWith("term_bank_")) {
|
|
}
|
|
} catch (e) {
|
|
console.error(filename);
|
|
throw e;
|
|
}
|
|
}
|
|
}
|