Nix Krystik
2026-05-30 16:38:48 +08:00
parent 8c6d535f97
commit 0985712a1d
6 changed files with 171 additions and 171 deletions
+161 -161
View File
@@ -1,161 +1,161 @@
import { Client as DiscordClient, GatewayIntentBits, MessageFlags, Partials } from 'discord.js';
import { config } from './config';
import { handleAuditLogCreate, handleBanRemove, handleBulkMessageDelete, handleGuildCreate, handleMemberJoin, handleMessageCreate, handleMessageDelete, handleMessageUpdate, handleThreadCreate, handleVoiceStateUpdate } from './events';
import { ScheduledTasks, Scheduler } from './scheduler';
import { Database } from './shared/Database';
import { openRedisClient } from './shared/RedisClient';
import { Handler } from './types';
import { initIfNecessary, loadHandlersFrom, refreshCommands } from './utils';
import { initializeWebserver } from './webserver';
let ready = false;
console.log('Starting...');
const client = new DiscordClient({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildModeration,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.MessageContent
],
partials: [Partials.Message, Partials.GuildMember, Partials.User, Partials.Channel],
rest: { timeout: 30000 },
allowedMentions: {
parse: [],
repliedUser: false
}
});
const scheduler: Scheduler = new Scheduler(client);
const commands: Handler[] = [];
const contextMenus: Handler[] = [];
const buttons: Handler[] = [];
const modals: Handler[] = [];
const menus: Handler[] = [];
loadHandlersFrom('commands', commands);
loadHandlersFrom('context-menus', contextMenus);
loadHandlersFrom('buttons', buttons);
loadHandlersFrom('modals', modals);
loadHandlersFrom('menus', menus);
// Due to their reliance on each other, these two events (interactionCreate, and ready) have to stay here.
// Alternatively, they can move to another single file. Or use static classes.
client.on('interactionCreate', async (interaction) => {
if (!ready) {
if (
interaction.isChatInputCommand()
|| interaction.isContextMenuCommand()
|| interaction.isButton()
|| interaction.isModalSubmit()
|| interaction.isAnySelectMenu()
)
interaction.reply({
content: 'Bot is still starting up. Please wait a few seconds.',
flags: [MessageFlags.Ephemeral],
});
return;
}
if (interaction.isChatInputCommand()) {
// Handle chat
for (const command of commands) {
if (interaction.commandName == command.name) {
command.handler(client, interaction);
return;
}
}
} else if (interaction.isContextMenuCommand()) {
// Handle context menu commands.
for (const command of contextMenus) {
if (interaction.commandName == command.name) {
command.handler(client, interaction);
return;
}
}
} else if (interaction.isAutocomplete()) {
// Handle autocomplete requests.
for (const command of commands) {
if (interaction.commandName == command.name) {
if (command.autoComplete) {
command
.autoComplete(client, interaction)
.catch(e => console.error(e));
}
return;
}
}
} else if (interaction.isButton()) {
// Handle button presses.
const id = interaction.customId.split('_')[0];
for (const button of buttons) {
if (id == button.name) {
button.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
} else if (interaction.isModalSubmit()) {
// Handle modal submissions.
const id = interaction.customId.split('_')[0];
for (const modal of modals) {
if (id == modal.name) {
modal.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
} else if (interaction.isAnySelectMenu()) {
// Handle menu selections.
const id = interaction.customId.split('_')[0];
for (const menu of menus) {
if (id == menu.name) {
menu.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
}
});
client.on('clientReady', async () => {
console.log(`Logged in as ${client.user!.tag}!`);
await refreshCommands(client);
await initIfNecessary(client, commands);
await initIfNecessary(client, buttons);
await initIfNecessary(client, modals);
await initIfNecessary(client, menus);
await Database.open('./data/discord-main.db');
await openRedisClient(config.REDIS_URL!, client);
await initializeWebserver(client);
ScheduledTasks.forEach((task) => scheduler.add(task));
ready = true;
console.log('Ready');
});
client.on('guildAuditLogEntryCreate', handleAuditLogCreate);
client.on('guildBanRemove', handleBanRemove);
client.on('guildCreate', handleGuildCreate);
client.on('guildMemberAdd', handleMemberJoin);
client.on('messageCreate', handleMessageCreate);
client.on('messageDelete', handleMessageDelete);
client.on('messageDeleteBulk', handleBulkMessageDelete);
client.on('messageUpdate', handleMessageUpdate);
client.on('threadCreate', handleThreadCreate);
client.on('voiceStateUpdate', handleVoiceStateUpdate);
client.on('error', console.error);
process.on('uncaughtException', console.error);
client.login(config.DISCORD_TOKEN);
import { Client as DiscordClient, GatewayIntentBits, MessageFlags, Partials } from 'discord.js';
import { config } from './config';
import { handleAuditLogCreate, handleBanRemove, handleBulkMessageDelete, handleGuildCreate, handleMemberJoin, handleMessageCreate, handleMessageDelete, handleMessageUpdate, handleThreadCreate, handleVoiceStateUpdate } from './events';
import { ScheduledTasks, Scheduler } from './scheduler';
import { Database } from './shared/Database';
import { openRedisClient } from './shared/RedisClient';
import { Handler } from './types';
import { initIfNecessary, loadHandlersFrom, refreshCommands } from './utils';
import { initializeWebserver } from './webserver';
let ready = false;
console.log('Starting...');
const client = new DiscordClient({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildModeration,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.MessageContent
],
partials: [Partials.Message, Partials.GuildMember, Partials.User, Partials.Channel],
rest: { timeout: 30000 },
allowedMentions: {
parse: [],
repliedUser: false
}
});
const scheduler: Scheduler = new Scheduler(client);
const commands: Handler[] = [];
const contextMenus: Handler[] = [];
const buttons: Handler[] = [];
const modals: Handler[] = [];
const menus: Handler[] = [];
loadHandlersFrom('commands', commands);
loadHandlersFrom('context-menus', contextMenus);
loadHandlersFrom('buttons', buttons);
loadHandlersFrom('modals', modals);
loadHandlersFrom('menus', menus);
// Due to their reliance on each other, these two events (interactionCreate, and ready) have to stay here.
// Alternatively, they can move to another single file. Or use static classes.
client.on('interactionCreate', async (interaction) => {
if (!ready) {
if (
interaction.isChatInputCommand()
|| interaction.isContextMenuCommand()
|| interaction.isButton()
|| interaction.isModalSubmit()
|| interaction.isAnySelectMenu()
)
interaction.reply({
content: 'Bot is still starting up. Please wait a few seconds.',
flags: [MessageFlags.Ephemeral],
});
return;
}
if (interaction.isChatInputCommand()) {
// Handle chat
for (const command of commands) {
if (interaction.commandName == command.name) {
command.handler(client, interaction);
return;
}
}
} else if (interaction.isContextMenuCommand()) {
// Handle context menu commands.
for (const command of contextMenus) {
if (interaction.commandName == command.name) {
command.handler(client, interaction);
return;
}
}
} else if (interaction.isAutocomplete()) {
// Handle autocomplete requests.
for (const command of commands) {
if (interaction.commandName == command.name) {
if (command.autoComplete) {
command
.autoComplete(client, interaction)
.catch(e => console.error(e));
}
return;
}
}
} else if (interaction.isButton()) {
// Handle button presses.
const id = interaction.customId.split('_')[0];
for (const button of buttons) {
if (id == button.name) {
button.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
} else if (interaction.isModalSubmit()) {
// Handle modal submissions.
const id = interaction.customId.split('_')[0];
for (const modal of modals) {
if (id == modal.name) {
modal.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
} else if (interaction.isAnySelectMenu()) {
// Handle menu selections.
const id = interaction.customId.split('_')[0];
for (const menu of menus) {
if (id == menu.name) {
menu.handler(client, interaction, ...interaction.customId.split('_').slice(1));
return;
}
}
}
});
client.on('clientReady', async () => {
console.log(`Logged in as ${client.user!.tag}!`);
await refreshCommands(client);
await initIfNecessary(client, commands);
await initIfNecessary(client, buttons);
await initIfNecessary(client, modals);
await initIfNecessary(client, menus);
await Database.open('./data/discord-main.db');
await openRedisClient(config.REDIS_URL!, client);
await initializeWebserver(client);
ScheduledTasks.forEach((task) => scheduler.add(task));
ready = true;
console.log('Ready');
});
client.on('guildAuditLogEntryCreate', handleAuditLogCreate);
client.on('guildBanRemove', handleBanRemove);
client.on('guildCreate', handleGuildCreate);
client.on('guildMemberAdd', handleMemberJoin);
client.on('messageCreate', handleMessageCreate);
client.on('messageDelete', handleMessageDelete);
client.on('messageDeleteBulk', handleBulkMessageDelete);
client.on('messageUpdate', handleMessageUpdate);
client.on('threadCreate', handleThreadCreate);
client.on('voiceStateUpdate', handleVoiceStateUpdate);
client.on('error', console.error);
process.on('uncaughtException', console.error);
client.login(config.DISCORD_TOKEN);
@@ -11,4 +11,4 @@ class CheckExpiredBansTask implements Task {
}
}
export default new CheckExpiredBansTask();
export default new CheckExpiredBansTask();
@@ -11,4 +11,4 @@ class CloseStaleTicketsTask implements Task {
}
}
export default new CloseStaleTicketsTask();
export default new CloseStaleTicketsTask();
+1 -1
View File
@@ -4,4 +4,4 @@ import closeStaleTicketsTask from './close-stale-tickets-task';
export default [
closeStaleTicketsTask,
checkExpiredBansTask,
];
];
+6 -6
View File
@@ -1,6 +1,6 @@
export * from './command.d';
export * from './database-types.d';
export * from './e621-types.d';
export * from './handler.d';
export * from './helper-types.d';
export * from './scheduler.d';
export * from './command.d';
export * from './database-types.d';
export * from './e621-types.d';
export * from './handler.d';
export * from './helper-types.d';
export * from './scheduler.d';
+1 -1
View File
@@ -5,4 +5,4 @@ export interface Task {
firstRun: boolean;
handle(context: Client): Promise<void>;
};
};