2023-11-12 21:32:14 +01:00
|
|
|
import { Client, GatewayIntentBits, Events, Collection, CommandInteraction, CommandInteractionOption, ApplicationCommandOptionType } from 'discord.js';
|
2022-06-08 02:57:15 +02:00
|
|
|
import * as fs from 'fs';
|
2023-11-19 21:28:31 +01:00
|
|
|
const { token, sitePort, siteURL, clientId, clientSecret } = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
|
2022-06-08 02:57:15 +02:00
|
|
|
import * as path from 'path';
|
2023-11-10 22:41:42 +01:00
|
|
|
import { initializeAnnouncements } from './lib/subscriptions';
|
2023-11-11 01:54:11 +01:00
|
|
|
import * as log from './lib/log';
|
|
|
|
import chalk from 'chalk';
|
|
|
|
import prettyBytes from 'pretty-bytes';
|
2023-11-16 11:33:11 +01:00
|
|
|
import { Command } from './types/index';
|
2023-11-20 02:56:18 +01:00
|
|
|
import { startServer } from './web/web';
|
2023-11-21 20:34:32 +01:00
|
|
|
import { init as initPVP } from './lib/rpg/pvp';
|
2023-11-22 14:45:55 +01:00
|
|
|
import { autocomplete } from './lib/autocomplete';
|
2024-03-18 13:09:49 +01:00
|
|
|
import { setupListeners } from './lib/events';
|
2022-06-08 01:28:20 +02:00
|
|
|
|
2023-06-11 17:23:57 +02:00
|
|
|
const bot = new Client({
|
2022-06-08 03:46:00 +02:00
|
|
|
intents: [
|
2023-06-11 17:23:57 +02:00
|
|
|
GatewayIntentBits.Guilds,
|
2024-03-25 02:13:32 +01:00
|
|
|
GatewayIntentBits.GuildInvites,
|
|
|
|
GatewayIntentBits.GuildMembers,
|
|
|
|
GatewayIntentBits.GuildMessageReactions,
|
2023-06-11 17:23:57 +02:00
|
|
|
GatewayIntentBits.GuildMessages,
|
2024-03-25 02:13:32 +01:00
|
|
|
GatewayIntentBits.GuildModeration,
|
|
|
|
GatewayIntentBits.GuildScheduledEvents,
|
2023-06-11 17:23:57 +02:00
|
|
|
GatewayIntentBits.GuildVoiceStates,
|
|
|
|
GatewayIntentBits.MessageContent,
|
2024-03-17 22:22:03 +01:00
|
|
|
GatewayIntentBits.DirectMessages,
|
2022-06-08 03:46:00 +02:00
|
|
|
],
|
2022-06-08 01:28:20 +02:00
|
|
|
});
|
|
|
|
|
2023-11-17 19:23:35 +01:00
|
|
|
bot.config = {
|
2023-11-19 21:28:31 +01:00
|
|
|
token, sitePort, siteURL, clientId, clientSecret
|
2023-11-17 19:23:35 +01:00
|
|
|
};
|
|
|
|
|
2023-11-11 01:54:11 +01:00
|
|
|
async function init() {
|
|
|
|
log.nonsense('booting chip...');
|
|
|
|
|
2023-11-17 21:11:50 +01:00
|
|
|
log.nonsense('starting up web interface...');
|
2023-11-18 13:49:50 +01:00
|
|
|
await startServer(bot, sitePort);
|
2023-11-17 21:11:50 +01:00
|
|
|
|
2023-11-11 01:54:11 +01:00
|
|
|
log.nonsense('setting up connection...');
|
|
|
|
|
|
|
|
try {
|
|
|
|
await bot.login(token);
|
|
|
|
} catch (err) {
|
|
|
|
log.error('error: network hardware broken?', err);
|
|
|
|
log.error(`${chalk.bold('emergency mode could not be established.')} shutting down.`);
|
2023-11-12 20:51:08 +01:00
|
|
|
process.exit(1);
|
2023-11-11 01:54:11 +01:00
|
|
|
}
|
2023-11-21 20:34:32 +01:00
|
|
|
|
|
|
|
initPVP(bot);
|
2023-11-11 01:54:11 +01:00
|
|
|
}
|
|
|
|
|
2023-06-11 17:23:57 +02:00
|
|
|
bot.on(Events.ClientReady, async () => {
|
2023-11-11 01:54:11 +01:00
|
|
|
log.info('jillo online');
|
|
|
|
|
|
|
|
log.nonsense('finishing launch');
|
|
|
|
|
2023-11-10 22:41:42 +01:00
|
|
|
initializeAnnouncements(bot);
|
2022-06-08 03:46:00 +02:00
|
|
|
|
2023-06-11 17:23:57 +02:00
|
|
|
bot.commands = new Collection();
|
2022-06-08 03:46:00 +02:00
|
|
|
const cmdFiles = fs.readdirSync(path.join(__dirname, './commands')).filter((file) => file.endsWith('.js'));
|
2022-06-08 01:28:20 +02:00
|
|
|
for (const file of cmdFiles) {
|
2023-11-17 21:11:50 +01:00
|
|
|
const cmd = (await import(`./commands/${file}`)).default as Command;
|
2022-06-08 01:28:20 +02:00
|
|
|
bot.commands.set(cmd.data.name, cmd);
|
2022-06-08 03:46:00 +02:00
|
|
|
if (cmd.onClientReady) cmd.onClientReady(bot);
|
2022-06-08 01:28:20 +02:00
|
|
|
}
|
|
|
|
|
2023-11-11 01:54:11 +01:00
|
|
|
log.info('jillo firmware up and running');
|
|
|
|
log.nonsense(`| running on ${process.platform} ${process.config.variables.host_arch}`);
|
|
|
|
log.nonsense(`| node ${process.version} V8 v${process.versions.v8}`);
|
|
|
|
const memory = process.memoryUsage();
|
|
|
|
log.nonsense(`| ${prettyBytes(memory.rss)} memory usage, ${prettyBytes(memory.heapUsed)} / ${prettyBytes(memory.heapTotal)} heap usage`);
|
2022-06-08 01:28:20 +02:00
|
|
|
});
|
|
|
|
|
2024-03-18 13:09:49 +01:00
|
|
|
setupListeners(bot);
|
|
|
|
|
2023-11-12 21:32:14 +01:00
|
|
|
function stringifyArg(arg: CommandInteractionOption): string {
|
|
|
|
switch (arg.type) {
|
|
|
|
case ApplicationCommandOptionType.Boolean:
|
|
|
|
case ApplicationCommandOptionType.Integer:
|
|
|
|
case ApplicationCommandOptionType.Number:
|
|
|
|
case ApplicationCommandOptionType.String:
|
|
|
|
return `${arg.name}:${arg.value}`;
|
|
|
|
case ApplicationCommandOptionType.Channel:
|
2023-11-12 21:34:57 +01:00
|
|
|
return `${arg.name}:#${arg.channel?.name}`;
|
2023-11-12 21:32:14 +01:00
|
|
|
case ApplicationCommandOptionType.Role:
|
2023-11-12 21:34:57 +01:00
|
|
|
return `${arg.name}:@${arg.role?.name}`;
|
2023-11-12 21:32:14 +01:00
|
|
|
case ApplicationCommandOptionType.User:
|
2023-11-12 21:34:57 +01:00
|
|
|
return `${arg.name}:@${arg.user?.displayName}`;
|
2023-11-12 21:32:14 +01:00
|
|
|
case ApplicationCommandOptionType.Mentionable:
|
|
|
|
return `${arg.name}:${arg.channel?.id || arg.user?.id || arg.role?.id}`;
|
|
|
|
case ApplicationCommandOptionType.Attachment:
|
|
|
|
return `${arg.name}:<attachment>`;
|
|
|
|
case ApplicationCommandOptionType.Subcommand:
|
|
|
|
case ApplicationCommandOptionType.SubcommandGroup:
|
2023-11-12 21:34:57 +01:00
|
|
|
return `${arg.name} ${arg.options?.map(stringifyArg).join(' ')}`;
|
2023-11-12 21:32:14 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function stringifyCommand(cmd: CommandInteraction) {
|
2023-11-12 21:34:57 +01:00
|
|
|
return `/${cmd.commandName} ${cmd.options.data.map(stringifyArg).join(' ')}`;
|
2023-11-12 21:32:14 +01:00
|
|
|
}
|
|
|
|
|
2023-06-11 17:23:57 +02:00
|
|
|
bot.on(Events.InteractionCreate, async (interaction) => {
|
2023-11-11 00:01:38 +01:00
|
|
|
if (interaction.isCommand()) {
|
|
|
|
const command = interaction.client.commands.get(interaction.commandName);
|
|
|
|
if (!command) return;
|
2023-11-12 20:51:08 +01:00
|
|
|
|
2023-11-12 21:32:14 +01:00
|
|
|
log.nonsense(stringifyCommand(interaction));
|
2023-11-11 00:01:38 +01:00
|
|
|
|
|
|
|
try {
|
2023-11-16 11:33:11 +01:00
|
|
|
await command.execute(interaction);
|
2023-11-11 00:01:38 +01:00
|
|
|
} catch (error) {
|
2023-11-13 17:41:07 +01:00
|
|
|
if (interaction.isRepliable() && !interaction.replied && !interaction.deferred) interaction.reply({ content: `\`ERROR\`\n\`\`\`\n${error}\n\`\`\``, ephemeral: true });
|
|
|
|
if (interaction.deferred) interaction.followUp(`\`ERROR\`\n\`\`\`\n${error}\n\`\`\``);
|
2023-11-11 01:54:11 +01:00
|
|
|
log.error(error);
|
2023-11-11 00:01:38 +01:00
|
|
|
}
|
|
|
|
} else if (interaction.isAutocomplete()) {
|
|
|
|
const command = interaction.client.commands.get(interaction.commandName);
|
|
|
|
if (!command) return;
|
2022-06-08 01:28:20 +02:00
|
|
|
|
2023-11-11 00:01:38 +01:00
|
|
|
try {
|
2023-11-16 11:33:11 +01:00
|
|
|
if (!command.autocomplete) throw `Trying to invoke autocomplete for command ${interaction.commandName} which does not have it defined`;
|
2023-11-22 14:45:55 +01:00
|
|
|
await autocomplete(command.autocomplete)(interaction);
|
2023-11-11 00:01:38 +01:00
|
|
|
} catch (error) {
|
2023-11-11 01:54:11 +01:00
|
|
|
log.error(error);
|
2023-11-11 00:01:38 +01:00
|
|
|
}
|
2022-06-08 03:46:00 +02:00
|
|
|
}
|
2022-06-08 01:28:20 +02:00
|
|
|
});
|
|
|
|
|
2023-10-29 11:22:21 +01:00
|
|
|
process.on('uncaughtException', err => {
|
2023-11-11 01:54:11 +01:00
|
|
|
log.error(err);
|
2023-10-29 11:22:21 +01:00
|
|
|
});
|
|
|
|
|
2023-11-11 01:54:11 +01:00
|
|
|
init();
|