218 lines
7.0 KiB
JavaScript
218 lines
7.0 KiB
JavaScript
"use strict";
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
const path = require("path");
|
|
const fs = require("fs");
|
|
async function ensureUserDataDB(dbPath) {
|
|
const dir = path.dirname(dbPath);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
const db = new sqlite3.Database(dbPath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);
|
|
return new Promise((resolve, reject) => {
|
|
const schema = `
|
|
CREATE TABLE IF NOT EXISTS User (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL UNIQUE,
|
|
profile_picture_url TEXT,
|
|
email TEXT UNIQUE,
|
|
password_hash TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS UserIntegration (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL UNIQUE,
|
|
platform TEXT NOT NULL DEFAULT 'AniList',
|
|
access_token TEXT NOT NULL,
|
|
refresh_token TEXT NOT NULL,
|
|
token_type TEXT NOT NULL,
|
|
anilist_user_id INTEGER NOT NULL,
|
|
expires_at DATETIME NOT NULL,
|
|
FOREIGN KEY (user_id) REFERENCES User(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS ListEntry (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
user_id INTEGER NOT NULL,
|
|
entry_id INTEGER NOT NULL,
|
|
source TEXT NOT NULL,
|
|
entry_type TEXT NOT NULL,
|
|
status TEXT NOT NULL,
|
|
progress INTEGER NOT NULL DEFAULT 0,
|
|
score INTEGER,
|
|
|
|
start_date DATE,
|
|
end_date DATE,
|
|
repeat_count INTEGER NOT NULL DEFAULT 0,
|
|
notes TEXT,
|
|
is_private BOOLEAN NOT NULL DEFAULT 0,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE (user_id, entry_id),
|
|
FOREIGN KEY (user_id) REFERENCES User(id) ON DELETE CASCADE
|
|
);
|
|
`;
|
|
db.exec(schema, (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
async function ensureAnilistSchema(db) {
|
|
return new Promise((resolve, reject) => {
|
|
const schema = `
|
|
CREATE TABLE IF NOT EXISTS anime (
|
|
id INTEGER PRIMARY KEY,
|
|
title TEXT,
|
|
updatedAt INTEGER,
|
|
cache_created_at INTEGER DEFAULT 0,
|
|
cache_ttl_ms INTEGER DEFAULT 0,
|
|
full_data JSON
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS trending (
|
|
rank INTEGER PRIMARY KEY,
|
|
id INTEGER,
|
|
full_data JSON,
|
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS top_airing (
|
|
rank INTEGER PRIMARY KEY,
|
|
id INTEGER,
|
|
full_data JSON,
|
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS books (
|
|
id INTEGER PRIMARY KEY,
|
|
title TEXT,
|
|
updatedAt INTEGER,
|
|
full_data JSON
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS trending_books (
|
|
rank INTEGER PRIMARY KEY,
|
|
id INTEGER,
|
|
full_data JSON,
|
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS popular_books (
|
|
rank INTEGER PRIMARY KEY,
|
|
id INTEGER,
|
|
full_data JSON,
|
|
updated_at INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
`;
|
|
db.exec(schema, (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
async function ensureExtensionsTable(db) {
|
|
return new Promise((resolve, reject) => {
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS extension (
|
|
ext_name TEXT NOT NULL,
|
|
id TEXT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
metadata TEXT NOT NULL,
|
|
updated_at INTEGER NOT NULL,
|
|
PRIMARY KEY(ext_name, id)
|
|
);
|
|
`, (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
async function ensureCacheTable(db) {
|
|
return new Promise((resolve, reject) => {
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS cache (
|
|
key TEXT PRIMARY KEY,
|
|
result TEXT NOT NULL,
|
|
created_at INTEGER NOT NULL,
|
|
ttl_ms INTEGER NOT NULL
|
|
);
|
|
`, (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
function ensureFavoritesDB(dbPath) {
|
|
const dir = path.dirname(dbPath);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
const exists = fs.existsSync(dbPath);
|
|
const db = new sqlite3.Database(dbPath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE);
|
|
return new Promise((resolve, reject) => {
|
|
if (!exists) {
|
|
const schema = `
|
|
CREATE TABLE IF NOT EXISTS favorites (
|
|
id TEXT NOT NULL,
|
|
user_id INTEGER NOT NULL,
|
|
title TEXT NOT NULL,
|
|
image_url TEXT NOT NULL,
|
|
thumbnail_url TEXT NOT NULL DEFAULT "",
|
|
tags TEXT NOT NULL DEFAULT "",
|
|
headers TEXT NOT NULL DEFAULT "",
|
|
provider TEXT NOT NULL DEFAULT "",
|
|
PRIMARY KEY (id, user_id)
|
|
);
|
|
`;
|
|
db.exec(schema, (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
return;
|
|
}
|
|
db.all(`PRAGMA table_info(favorites)`, (err, cols) => {
|
|
if (err)
|
|
return reject(err);
|
|
const hasHeaders = cols.some(c => c.name === "headers");
|
|
const hasProvider = cols.some(c => c.name === "provider");
|
|
const hasUserId = cols.some(c => c.name === "user_id");
|
|
const queries = [];
|
|
if (!hasHeaders) {
|
|
queries.push(`ALTER TABLE favorites ADD COLUMN headers TEXT NOT NULL DEFAULT ""`);
|
|
}
|
|
if (!hasProvider) {
|
|
queries.push(`ALTER TABLE favorites ADD COLUMN provider TEXT NOT NULL DEFAULT ""`);
|
|
}
|
|
if (!hasUserId) {
|
|
queries.push(`ALTER TABLE favorites ADD COLUMN user_id INTEGER NOT NULL DEFAULT 1`);
|
|
}
|
|
if (queries.length === 0) {
|
|
return resolve(false);
|
|
}
|
|
db.exec(queries.join(";"), (err) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve(true);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
module.exports = {
|
|
ensureUserDataDB,
|
|
ensureAnilistSchema,
|
|
ensureExtensionsTable,
|
|
ensureCacheTable,
|
|
ensureFavoritesDB
|
|
};
|