Files
ECS-FullStack/discord-bot/index.js

99 lines
3.9 KiB
JavaScript

const { Client, GatewayIntentBits, Collection } = require('discord.js');
const fs = require('fs');
const path = require('path');
const deployCommands = require('./deploy-commands');
const { readDb } = require('../backend/db');
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] });
client.commands = new Collection();
const commandHandler = require('./handlers/command-handler');
const eventHandler = require('./handlers/event-handler');
commandHandler(client);
eventHandler(client);
client.on('interactionCreate', async interaction => {
// Handle button/component interactions for invites
if (interaction.isButton && interaction.isButton()) {
const id = interaction.customId || '';
if (id.startsWith('copy_inv_')) {
const code = id.replace('copy_inv_', '');
const db = readDb();
const invites = (db[interaction.guildId] && db[interaction.guildId].invites) ? db[interaction.guildId].invites : [];
const inv = invites.find(i => i.code === code);
if (inv) {
await interaction.reply({ content: `Invite: ${inv.url}`, ephemeral: true });
} else {
await interaction.reply({ content: 'Invite not found.', ephemeral: true });
}
} else if (id.startsWith('delete_inv_')) {
const code = id.replace('delete_inv_', '');
// permission check: admin only
const member = interaction.member;
if (!member.permissions.has('Administrator')) {
await interaction.reply({ content: 'You must be an administrator to delete invites.', ephemeral: true });
return;
}
try {
// call backend delete endpoint
const fetch = require('node-fetch');
const url = `http://localhost:${process.env.PORT || 3002}/api/servers/${interaction.guildId}/invites/${code}`;
await fetch(url, { method: 'DELETE' });
await interaction.reply({ content: 'Invite deleted.', ephemeral: true });
} catch (e) {
console.error('Error deleting invite via API:', e);
await interaction.reply({ content: 'Failed to delete invite.', ephemeral: true });
}
}
return;
}
if (!interaction.isCommand()) return;
const command = client.commands.get(interaction.commandName);
if (!command) return;
// Check per-guild toggles
try {
const db = readDb();
const guildSettings = db[interaction.guildId] || {};
const toggles = guildSettings.commandToggles || {};
const protectedCommands = ['manage-commands', 'help'];
// If command is protected, always allow
if (!protectedCommands.includes(command.name)) {
if (toggles[command.name] === false) {
await interaction.reply({ content: 'This command has been disabled on this server.', flags: 64 });
return;
}
// If the module-level enabled flag is false, treat as disabled too
if (command.enabled === false) {
await interaction.reply({ content: 'This command is currently disabled globally.', flags: 64 });
return;
}
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'There was an error while executing this command!', flags: 64 });
}
} catch (error) {
console.error('Error checking command toggles:', error);
await interaction.reply({ content: 'Internal error occurred.', flags: 64 });
}
});
client.on('guildCreate', guild => {
deployCommands(guild.id);
});
const login = () => {
client.login(process.env.DISCORD_BOT_TOKEN);
}
module.exports = { login, client };