discord-media-server
Version:
Self-hosted Discord bot for scanning and serving information on local media files.
133 lines (114 loc) • 4.2 kB
JavaScript
// setup.js — interactive setup for discord-media-server
import fs from 'fs';
import path from 'path';
import readline from 'readline';
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { createTables } from './setupDatabase.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const envPath = path.join(__dirname, '../.env');
dotenv.config({ path: envPath });
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function ask(question) {
return new Promise(resolve => rl.question(question, answer => resolve(answer.trim())));
}
function updateOrAdd(key, value) {
let lines = [];
if (fs.existsSync(envPath)) {
lines = fs.readFileSync(envPath, 'utf8')
.split('\n')
.filter(line => line.trim() !== '' && !line.startsWith(key + '='));
}
lines.push(`${key}=${value}`);
fs.writeFileSync(envPath, lines.join('\n').trim() + '\n', 'utf8');
}
async function promptValidMediaPath() {
let dir = '';
while (true) {
dir = await ask('Full path to media folder (e.g., /home/user/Movies or D:\\Media\\Movies): ');
if (fs.existsSync(dir)) return dir;
console.log('That folder does not exist. Try again.');
}
}
export default async function runSetup() {
await main();
}
async function main() {
console.log('Running setup...\n');
let shouldWriteEnv = false;
if (fs.existsSync(envPath)) {
const overwriteEnv = (await ask('.env already exists. Overwrite? (y/N): ')).toLowerCase();
if (overwriteEnv !== 'y') {
console.log('Using existing .env values...');
} else {
shouldWriteEnv = true;
}
} else {
shouldWriteEnv = true;
}
const { connectMySQL, connectSQLite, query } = await import('./database.js');
// Always update .env from config
let dbConfig = {};
let discordClientId = '';
if (shouldWriteEnv) {
const mediaDirectory = await promptValidMediaPath();
const discordToken = await ask('Discord Bot Token: ');
discordClientId = await ask('Discord Client ID (optional): ');
const tmdbKey = await ask('TMDb API Key (optional): ');
const dbChoice = await ask('Choose database type:\n1. SQLite\n2. MySQL\nEnter number: ');
let dbType = dbChoice === '1' ? 'sqlite' : 'mysql';
let dbName = await ask('Database name: ') || 'media';
if (dbType === 'sqlite') {
dbConfig = {
filename: path.resolve(__dirname, `../data/${dbName}.sqlite`),
database: dbName
};
await connectSQLite(dbConfig);
} else {
dbConfig = {
host: await ask('MySQL Host (localhost): ') || 'localhost',
user: await ask('MySQL User: ') || 'root',
password: await ask('MySQL Password: ') || '',
database: dbName
};
await connectMySQL(dbConfig);
}
let port = await ask('Server port (default 8080): ') || 8080;
// insert into .env
updateOrAdd('MEDIA_DIR', mediaDirectory);
updateOrAdd('DISCORD_TOKEN', discordToken);
if (discordClientId) updateOrAdd('DISCORD_CLIENT_ID', discordClientId);
updateOrAdd('TMDB_API_KEY', tmdbKey);
updateOrAdd('DB_TYPE', dbType);
if (dbType === 'sqlite') {
updateOrAdd('DB_FILE', dbConfig.filename);
} else {
updateOrAdd('DB_HOST', dbConfig.host);
updateOrAdd('DB_USER', dbConfig.user);
updateOrAdd('DB_PASS', dbConfig.password);
}
updateOrAdd('DB_NAME', dbName);
updateOrAdd('PORT', port);
// database creation
try {
console.log('\nCreating database tables...');
let config = { dbType, dbConfig };
await createTables(config);
console.log('Database configured.');
} catch (err) {
res.status(500).send(`<pre>Database error:\n${err.stack}</pre>`);
return;
}
}
rl.close();
console.log('\nSetup complete.');
if (discordClientId) {
console.log(`\nInvite your bot with this link:\nhttps://discord.com/oauth2/authorize?client_id=${discordClientId}&scope=bot&permissions=274877975552`);
}
}
//main();
export { runSetup };