discord-media-server
Version:
Self-hosted Discord bot for scanning and serving information on local media files.
133 lines (111 loc) • 3.86 kB
JavaScript
// lib/database.js (universal MySQL + SQLite handler)
import dotenv from 'dotenv';
dotenv.config();
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import { CONFIG_DIR, DATA_DIR } from './setupConfig.js';
let db;
let isSQLite = false;
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Lazy-loaded config & connection
let initialized = false;
/** Initializes DB connection based on config.json */
export async function initDatabase() {
if (initialized) return;
try {
const dbType = process.env.DB_TYPE || 'sqlite';
isSQLite = dbType === 'sqlite';
if (isSQLite) {
const sqlite3 = (await import('better-sqlite3')).default;
const dbFileName = path.basename(process.env.DB_FILE || 'media.sqlite');
const dataDir = DATA_DIR || path.resolve(CONFIG_DIR || __dirname, 'data');
const sqlitePath = path.resolve(dataDir, dbFileName);
fs.mkdirSync(path.dirname(sqlitePath), { recursive: true });
db = new sqlite3(sqlitePath);
if (!db || typeof db.prepare !== 'function') {
throw new Error(`Failed to initialize SQLite DB at: ${sqlitePath}`);
}
//console.log(`SQLite DB loaded: ${sqlitePath}`);
} else {
const mysql = await import('mysql2/promise');
db = await mysql.createConnection({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME
});
if (!db || typeof db.prepare !== 'function') {
throw new Error('Failed to initialize SQLite database.');
}
//console.log(`MySQL DB connected: ${config.dbConfig.database || config.dbName}`);
}
initialized = true;
} catch(err) {
console.log(`\ninitDatabase error:\nPlease run setup first.\n\n${err.message}`)
}
}
/** Connects to SQLite for setup validation */
export async function connectSQLite(config) {
const sqlite3 = (await import('better-sqlite3')).default;
const dbFileName = path.basename(process.env.DB_FILE || 'media.sqlite');
const dataDir = DATA_DIR || path.resolve(CONFIG_DIR || __dirname, 'data');
const dbPath = path.resolve(dataDir, dbFileName);
// Ensure the folder exists
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
try {
const db = new sqlite3(dbPath);
db.exec('SELECT 1');
db.close();
console.log(`SQLite database ready at ${dbPath}`);
} catch (err) {
console.error('SQLite connection failed:', err.message);
process.exit(1);
}
}
/** Connects to MySQL for setup validation */
export async function connectMySQL(config) {
try {
const mysql = await import('mysql2/promise');
const db = await mysql.createConnection({
host: config.host,
user: config.user,
password: config.password,
database: config.database
});
await db.query('SELECT 1');
await db.end();
console.log('MySQL connection successful');
} catch (err) {
console.error('MySQL connection failed:', err.message);
process.exit(1);
}
}
export async function query(sql, params = []) {
if (!initialized) await initDatabase();
if (!db) {
throw new Error('Database is not initialized.');
}
if (isSQLite) {
const stmt = db.prepare(sql);
if (sql.trim().toLowerCase().startsWith('select')) {
return stmt.all(...params);
} else {
return stmt.run(...params);
}
} else {
const [rows] = await db.execute(sql, params);
return rows;
}
}
export async function close() {
if (!initialized) return;
if (isSQLite) {
db.close();
} else {
await db.end();
}
}
export { isSQLite };