mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
feat: reset
This commit is contained in:
1 parent
d769b852a9
commit
f7c356de1e
111 files changed
-11745
No files matched your search
@@ -1,83 +0,0 @@
|
||||
import { ButtonInteraction } from 'discord.js';
|
||||
import { RateLimiter } from 'discord.js-rate-limiter';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventHandler } from './index.js';
|
||||
import { Button, ButtonDeferType } from '../buttons/index.js';
|
||||
import { EventDataService } from '../services/index.js';
|
||||
import { InteractionUtils } from '../utils/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Config = require('../../config/config.json');
|
||||
|
||||
export class ButtonHandler implements EventHandler {
|
||||
private rateLimiter = new RateLimiter(
|
||||
Config.rateLimiting.buttons.amount,
|
||||
Config.rateLimiting.buttons.interval * 1000
|
||||
);
|
||||
|
||||
constructor(private buttons: Button[], private eventDataService: EventDataService) {}
|
||||
|
||||
public async process(intr: ButtonInteraction): Promise<void> {
|
||||
// Don't respond to self, or other bots
|
||||
if (intr.user.id === intr.client.user?.id || intr.user.bot) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is rate limited
|
||||
let limited = this.rateLimiter.take(intr.user.id);
|
||||
if (limited) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the button the user wants
|
||||
let button = this.findButton(intr.customId);
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (button.requireGuild && !intr.guild) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the embeds author equals the users tag
|
||||
if (
|
||||
button.requireEmbedAuthorTag &&
|
||||
intr.message.embeds[0]?.author?.name !== intr.user.tag
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Defer interaction
|
||||
// NOTE: Anything after this point we should be responding to the interaction
|
||||
switch (button.deferType) {
|
||||
case ButtonDeferType.REPLY: {
|
||||
await InteractionUtils.deferReply(intr);
|
||||
break;
|
||||
}
|
||||
case ButtonDeferType.UPDATE: {
|
||||
await InteractionUtils.deferUpdate(intr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return if defer was unsuccessful
|
||||
if (button.deferType !== ButtonDeferType.NONE && !intr.deferred) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data from database
|
||||
let data = await this.eventDataService.create({
|
||||
user: intr.user,
|
||||
channel: intr.channel,
|
||||
guild: intr.guild,
|
||||
});
|
||||
|
||||
// Execute the button
|
||||
await button.execute(intr, data);
|
||||
}
|
||||
|
||||
private findButton(id: string): Button {
|
||||
return this.buttons.find(button => button.ids.includes(id));
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
import {
|
||||
AutocompleteInteraction,
|
||||
ChatInputCommandInteraction,
|
||||
CommandInteraction,
|
||||
NewsChannel,
|
||||
TextChannel,
|
||||
ThreadChannel,
|
||||
} from 'discord.js';
|
||||
import { RateLimiter } from 'discord.js-rate-limiter';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventHandler } from './index.js';
|
||||
import { Command, CommandDeferType } from '../commands/index.js';
|
||||
import { DiscordLimits } from '../constants/index.js';
|
||||
import { EventData } from '../models/internal-models.js';
|
||||
import { EventDataService, Lang, Logger } from '../services/index.js';
|
||||
import { CommandUtils, InteractionUtils } from '../utils/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Config = require('../../config/config.json');
|
||||
let Logs = require('../../lang/logs.json');
|
||||
|
||||
export class CommandHandler implements EventHandler {
|
||||
private rateLimiter = new RateLimiter(
|
||||
Config.rateLimiting.commands.amount,
|
||||
Config.rateLimiting.commands.interval * 1000
|
||||
);
|
||||
|
||||
constructor(public commands: Command[], private eventDataService: EventDataService) {}
|
||||
|
||||
public async process(intr: CommandInteraction | AutocompleteInteraction): Promise<void> {
|
||||
// Don't respond to self, or other bots
|
||||
if (intr.user.id === intr.client.user?.id || intr.user.bot) {
|
||||
return;
|
||||
}
|
||||
|
||||
let commandParts =
|
||||
intr instanceof ChatInputCommandInteraction || intr instanceof AutocompleteInteraction
|
||||
? [
|
||||
intr.commandName,
|
||||
intr.options.getSubcommandGroup(false),
|
||||
intr.options.getSubcommand(false),
|
||||
].filter(Boolean)
|
||||
: [intr.commandName];
|
||||
let commandName = commandParts.join(' ');
|
||||
|
||||
// Try to find the command the user wants
|
||||
let command = CommandUtils.findCommand(this.commands, commandParts);
|
||||
if (!command) {
|
||||
Logger.error(
|
||||
Logs.error.commandNotFound
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (intr instanceof AutocompleteInteraction) {
|
||||
if (!command.autocomplete) {
|
||||
Logger.error(
|
||||
Logs.error.autocompleteNotFound
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let option = intr.options.getFocused(true);
|
||||
let choices = await command.autocomplete(intr, option);
|
||||
await InteractionUtils.respond(
|
||||
intr,
|
||||
choices?.slice(0, DiscordLimits.CHOICES_PER_AUTOCOMPLETE)
|
||||
);
|
||||
} catch (error) {
|
||||
Logger.error(
|
||||
intr.channel instanceof TextChannel ||
|
||||
intr.channel instanceof NewsChannel ||
|
||||
intr.channel instanceof ThreadChannel
|
||||
? Logs.error.autocompleteGuild
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{OPTION_NAME}', commandName)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
.replaceAll('{USER_TAG}', intr.user.tag)
|
||||
.replaceAll('{USER_ID}', intr.user.id)
|
||||
.replaceAll('{CHANNEL_NAME}', intr.channel.name)
|
||||
.replaceAll('{CHANNEL_ID}', intr.channel.id)
|
||||
.replaceAll('{GUILD_NAME}', intr.guild?.name)
|
||||
.replaceAll('{GUILD_ID}', intr.guild?.id)
|
||||
: Logs.error.autocompleteOther
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{OPTION_NAME}', commandName)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
.replaceAll('{USER_TAG}', intr.user.tag)
|
||||
.replaceAll('{USER_ID}', intr.user.id),
|
||||
error
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is rate limited
|
||||
let limited = this.rateLimiter.take(intr.user.id);
|
||||
if (limited) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Defer interaction
|
||||
// NOTE: Anything after this point we should be responding to the interaction
|
||||
switch (command.deferType) {
|
||||
case CommandDeferType.PUBLIC: {
|
||||
await InteractionUtils.deferReply(intr, false);
|
||||
break;
|
||||
}
|
||||
case CommandDeferType.HIDDEN: {
|
||||
await InteractionUtils.deferReply(intr, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return if defer was unsuccessful
|
||||
if (command.deferType !== CommandDeferType.NONE && !intr.deferred) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data from database
|
||||
let data = await this.eventDataService.create({
|
||||
user: intr.user,
|
||||
channel: intr.channel,
|
||||
guild: intr.guild,
|
||||
args: intr instanceof ChatInputCommandInteraction ? intr.options : undefined,
|
||||
});
|
||||
|
||||
try {
|
||||
// Check if interaction passes command checks
|
||||
let passesChecks = await CommandUtils.runChecks(command, intr, data);
|
||||
if (passesChecks) {
|
||||
// Execute the command
|
||||
await command.execute(intr, data);
|
||||
}
|
||||
} catch (error) {
|
||||
await this.sendError(intr, data);
|
||||
|
||||
// Log command error
|
||||
Logger.error(
|
||||
intr.channel instanceof TextChannel ||
|
||||
intr.channel instanceof NewsChannel ||
|
||||
intr.channel instanceof ThreadChannel
|
||||
? Logs.error.commandGuild
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
.replaceAll('{USER_TAG}', intr.user.tag)
|
||||
.replaceAll('{USER_ID}', intr.user.id)
|
||||
.replaceAll('{CHANNEL_NAME}', intr.channel.name)
|
||||
.replaceAll('{CHANNEL_ID}', intr.channel.id)
|
||||
.replaceAll('{GUILD_NAME}', intr.guild?.name)
|
||||
.replaceAll('{GUILD_ID}', intr.guild?.id)
|
||||
: Logs.error.commandOther
|
||||
.replaceAll('{INTERACTION_ID}', intr.id)
|
||||
.replaceAll('{COMMAND_NAME}', commandName)
|
||||
.replaceAll('{USER_TAG}', intr.user.tag)
|
||||
.replaceAll('{USER_ID}', intr.user.id),
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async sendError(intr: CommandInteraction, data: EventData): Promise<void> {
|
||||
try {
|
||||
await InteractionUtils.send(
|
||||
intr,
|
||||
Lang.getEmbed('errorEmbeds.command', data.lang, {
|
||||
ERROR_CODE: intr.id,
|
||||
GUILD_ID: intr.guild?.id ?? Lang.getRef('other.na', data.lang),
|
||||
SHARD_ID: (intr.guild?.shardId ?? 0).toString(),
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export interface EventHandler {
|
||||
process(...args: any[]): Promise<void>;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Guild } from 'discord.js';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventHandler } from './index.js';
|
||||
import { Language } from '../models/enum-helpers/index.js';
|
||||
import { EventDataService, Lang, Logger } from '../services/index.js';
|
||||
import { ClientUtils, FormatUtils, MessageUtils } from '../utils/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Logs = require('../../lang/logs.json');
|
||||
|
||||
export class GuildJoinHandler implements EventHandler {
|
||||
constructor(private eventDataService: EventDataService) {}
|
||||
|
||||
public async process(guild: Guild): Promise<void> {
|
||||
Logger.info(
|
||||
Logs.info.guildJoined
|
||||
.replaceAll('{GUILD_NAME}', guild.name)
|
||||
.replaceAll('{GUILD_ID}', guild.id)
|
||||
);
|
||||
|
||||
let owner = await guild.fetchOwner();
|
||||
|
||||
// Get data from database
|
||||
let data = await this.eventDataService.create({
|
||||
user: owner?.user,
|
||||
guild,
|
||||
});
|
||||
|
||||
// Send welcome message to the server's notify channel
|
||||
let notifyChannel = await ClientUtils.findNotifyChannel(guild, data.langGuild);
|
||||
if (notifyChannel) {
|
||||
await MessageUtils.send(
|
||||
notifyChannel,
|
||||
Lang.getEmbed('displayEmbeds.welcome', data.langGuild, {
|
||||
CMD_LINK_HELP: FormatUtils.commandMention(
|
||||
await ClientUtils.findAppCommand(
|
||||
guild.client,
|
||||
Lang.getRef('chatCommands.help', Language.Default)
|
||||
)
|
||||
),
|
||||
}).setAuthor({
|
||||
name: guild.name,
|
||||
iconURL: guild.iconURL(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Send welcome message to owner
|
||||
if (owner) {
|
||||
await MessageUtils.send(
|
||||
owner.user,
|
||||
Lang.getEmbed('displayEmbeds.welcome', data.lang, {
|
||||
CMD_LINK_HELP: FormatUtils.commandMention(
|
||||
await ClientUtils.findAppCommand(
|
||||
guild.client,
|
||||
Lang.getRef('chatCommands.help', Language.Default)
|
||||
)
|
||||
),
|
||||
}).setAuthor({
|
||||
name: guild.name,
|
||||
iconURL: guild.iconURL(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Guild } from 'discord.js';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventHandler } from './index.js';
|
||||
import { Logger } from '../services/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Logs = require('../../lang/logs.json');
|
||||
|
||||
export class GuildLeaveHandler implements EventHandler {
|
||||
public async process(guild: Guild): Promise<void> {
|
||||
Logger.info(
|
||||
Logs.info.guildLeft
|
||||
.replaceAll('{GUILD_NAME}', guild.name)
|
||||
.replaceAll('{GUILD_ID}', guild.id)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export { ButtonHandler } from './button-handler.js';
|
||||
export { CommandHandler } from './command-handler.js';
|
||||
export { EventHandler } from './event-handler.js';
|
||||
export { GuildJoinHandler } from './guild-join-handler.js';
|
||||
export { GuildLeaveHandler } from './guild-leave-handler.js';
|
||||
export { ReactionHandler } from './reaction-handler.js';
|
||||
export { MessageHandler } from './message-handler.js';
|
||||
export { TriggerHandler } from './trigger-handler.js';
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Message } from 'discord.js';
|
||||
|
||||
import { EventHandler, TriggerHandler } from './index.js';
|
||||
|
||||
export class MessageHandler implements EventHandler {
|
||||
constructor(private triggerHandler: TriggerHandler) {}
|
||||
|
||||
public async process(msg: Message): Promise<void> {
|
||||
// Don't respond to system messages or self
|
||||
if (msg.system || msg.author.id === msg.client.user?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process trigger
|
||||
await this.triggerHandler.process(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Message, MessageReaction, User } from 'discord.js';
|
||||
import { RateLimiter } from 'discord.js-rate-limiter';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventHandler } from './index.js';
|
||||
import { Reaction } from '../reactions/index.js';
|
||||
import { EventDataService } from '../services/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Config = require('../../config/config.json');
|
||||
|
||||
export class ReactionHandler implements EventHandler {
|
||||
private rateLimiter = new RateLimiter(
|
||||
Config.rateLimiting.reactions.amount,
|
||||
Config.rateLimiting.reactions.interval * 1000
|
||||
);
|
||||
|
||||
constructor(private reactions: Reaction[], private eventDataService: EventDataService) {}
|
||||
|
||||
public async process(msgReaction: MessageReaction, msg: Message, reactor: User): Promise<void> {
|
||||
// Don't respond to self, or other bots
|
||||
if (reactor.id === msgReaction.client.user?.id || reactor.bot) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is rate limited
|
||||
let limited = this.rateLimiter.take(msg.author.id);
|
||||
if (limited) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the reaction the user wants
|
||||
let reaction = this.findReaction(msgReaction.emoji.name);
|
||||
if (!reaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reaction.requireGuild && !msg.guild) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reaction.requireSentByClient && msg.author.id !== msg.client.user?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the embeds author equals the reactors tag
|
||||
if (reaction.requireEmbedAuthorTag && msg.embeds[0]?.author?.name !== reactor.tag) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data from database
|
||||
let data = await this.eventDataService.create({
|
||||
user: reactor,
|
||||
channel: msg.channel,
|
||||
guild: msg.guild,
|
||||
});
|
||||
|
||||
// Execute the reaction
|
||||
await reaction.execute(msgReaction, msg, reactor, data);
|
||||
}
|
||||
|
||||
private findReaction(emoji: string): Reaction {
|
||||
return this.reactions.find(reaction => reaction.emoji === emoji);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import { Message } from 'discord.js';
|
||||
import { RateLimiter } from 'discord.js-rate-limiter';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
import { EventDataService } from '../services/index.js';
|
||||
import { Trigger } from '../triggers/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
let Config = require('../../config/config.json');
|
||||
|
||||
export class TriggerHandler {
|
||||
private rateLimiter = new RateLimiter(
|
||||
Config.rateLimiting.triggers.amount,
|
||||
Config.rateLimiting.triggers.interval * 1000
|
||||
);
|
||||
|
||||
constructor(private triggers: Trigger[], private eventDataService: EventDataService) {}
|
||||
|
||||
public async process(msg: Message): Promise<void> {
|
||||
// Check if user is rate limited
|
||||
let limited = this.rateLimiter.take(msg.author.id);
|
||||
if (limited) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find triggers caused by this message
|
||||
let triggers = this.triggers.filter(trigger => {
|
||||
if (trigger.requireGuild && !msg.guild) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!trigger.triggered(msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// If this message causes no triggers then return
|
||||
if (triggers.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get data from database
|
||||
let data = await this.eventDataService.create({
|
||||
user: msg.author,
|
||||
channel: msg.channel,
|
||||
guild: msg.guild,
|
||||
});
|
||||
|
||||
// Execute triggers
|
||||
for (let trigger of triggers) {
|
||||
await trigger.execute(msg, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user