require("dotenv").config({ quiet: true }); const colors = require('colors'); const fs = require('fs').promises; const path = require('path'); const sqlite3 = require('sqlite3').verbose(); const dbPath = path.join(__dirname, process.env.DB_PATH || 'bansync.db'); const cron = require('node-cron'); const { Client, REST, DiscordAPIError, InteractionType, Routes } = require('discord.js'); // const s3 = require("./s3"); // This *was* for S3 backups and file uploads for images and whatnot. But i figured it was overkill and cut it. s3.js still exists because it's a good base. // Initialize SQLite database const db = new sqlite3.Database(dbPath, (sqlErr) => { if (sqlErr) { console.error(`${colors.red('[ERROR]')} Failed to connect to the database:`, sqlErr); process.exit(1); // Can't proceed without DB connection } else { console.log(`${colors.green('[INFO]')} Connected to the SQLite database at ${dbPath}`); } }); const init = () => { require('./migrations')(db).then(async () => { // if (process.env.S3_DB_BACKUP == true) { // s3.uploadFile('db_backup.db', await fs.readFile(dbPath)).then(() => { // console.log(`${colors.cyan('[INFO]')} Initial DB backup uploaded to S3.`); // let schedule = process.env.S3_DB_BACKUP_SCHEDULE || '0 0 * * *'; // Default to every day // if (!cron.validate(schedule)) { // console.log(`${colors.red('[ERROR]')} Invalid cron schedule for S3_DB_BACKUP_SCHEDULE. Using default '0 0 * * *'.`); // schedule = '0 0 * * *'; // } // cron.schedule(schedule, async () => { // try { // const data = await fs.readFile(dbPath); // await s3.uploadFile('db_backup.db', data); // console.log(`${colors.cyan('[INFO]')} Backed up DB to S3.`); // } catch (err) { // console.log(`${colors.red('[ERROR]')} Failed to back up DB to S3:`, err); // } // }); // console.log(`${colors.cyan('[INFO]')} Scheduled DB backups to S3.`); // }); // } // Cut feature. Overkill lol discord_setup(); }); }; const discord_setup = () => { const client = new Client({ intents: ["GuildBans", "Guilds", "GuildModeration"] }); const banHandler = require('./banHandler'); const unbanHandler = require('./unbanHandler'); client.on('guildBanRemove', (ban) => { unbanHandler(ban, db, client); }); client.on('guildBanAdd', (ban) => { banHandler(ban, db, client); }); client.on('interactionCreate', async interaction => { try { switch (interaction.type) { case InteractionType.ApplicationCommand: require(path.join(__dirname, 'interactions', 'commands', interaction.commandName))(interaction, db, client); break; case InteractionType.MessageComponent: require(path.join(__dirname, 'interactions', 'components', interaction.customId))(interaction, db, client); break; case InteractionType.ApplicationCommandAutocomplete: require(path.join(__dirname, 'interactions', 'autocomplete', interaction.commandName))(interaction, db, client); break; default: console.log(`${colors.yellow('[WARN]')} Unknown interaction type: ${interaction.type}`); interaction.reply({ content: 'Unknown interaction type.', ephemeral: true }); break; } } catch (error) { console.error(`${colors.red('[ERROR]')} Error handling interaction:`, error); interaction.reply({ content: 'An error occurred while processing your request.', ephemeral: true }); } }); client.once('clientReady', () => { console.log(`${colors.green('[DISCORD]')} Bot is online as ${client.user.displayName}`); // Init application commands (global) const rest = new REST().setToken(process.env.DISCORD_TOKEN); (async () => { try { console.log(`${colors.cyan('[DISCORD]')} Refreshing application (/) commands.`); await rest.put(Routes.applicationCommands(client.user.id), { body: require('./commands') }); console.log(`${colors.green('[DISCORD]')} Successfully reloaded application (/) commands.`); } catch (error) { console.error(`${colors.red('[DISCORD]')} Error reloading application (/) commands:`, error); } })(); // Sync bans on startup const sync = require('./sync'); sync(client, db); // Sync every 10 minutes cron.schedule(process.env.SYNC_SCHEDULE, () => { sync(client, db); }); }); client.login(process.env.DISCORD_TOKEN).catch(err => { console.log(`${colors.red('[DISCORD]')} Failed to log in:`, err); process.exit(1); // Can't proceed without Discord connection }); }; init();