refactor: 🚸 refactor and improve ux in heplers and middlewares
This commit is contained in:
parent
d62baa0b9c
commit
193032e3ba
11 changed files with 140 additions and 111 deletions
|
@ -16,7 +16,7 @@ export default async (interaction: ChatInputCommandInteraction) => {
|
||||||
const { client, commandName } = interaction;
|
const { client, commandName } = interaction;
|
||||||
|
|
||||||
const currentCommand = client.commands.get(commandName);
|
const currentCommand = client.commands.get(commandName);
|
||||||
if (!currentCommand) throw new Error(`Unknown command ${commandName}`);
|
if (!currentCommand) throw new Error("Command unavailable");
|
||||||
|
|
||||||
await currentCommand.execute(interaction).catch((error: Error) => {
|
await currentCommand.execute(interaction).catch((error: Error) => {
|
||||||
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||||
|
|
|
@ -12,7 +12,11 @@ export const options: IEventOptions = {
|
||||||
|
|
||||||
// Execute the event
|
// Execute the event
|
||||||
export const execute = async (client: Client) => {
|
export const execute = async (client: Client) => {
|
||||||
logger.info("Discord's API client is ready!");
|
if (!client.user) throw new Error("Client user unavailable");
|
||||||
|
|
||||||
|
logger.info({
|
||||||
|
message: `Connected to Discord!`,
|
||||||
|
});
|
||||||
|
|
||||||
updatePresence(client);
|
updatePresence(client);
|
||||||
await deployCommands(client);
|
await deployCommands(client);
|
||||||
|
|
|
@ -6,32 +6,30 @@ import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
// Register the commands.
|
// Register the commands.
|
||||||
export const register = async (client: Client) => {
|
export const register = async (client: Client) => {
|
||||||
logger.info("🔧 Started command management");
|
await checkDirectory("commands").then(async (commandNames) => {
|
||||||
|
for await (const commandName of commandNames) {
|
||||||
|
const commandProfiler = logger.startTimer();
|
||||||
|
|
||||||
const commandNames = await checkDirectory("commands");
|
await import(`../../commands/${commandName}`)
|
||||||
if (!commandNames) return logger.warn("No available commands found");
|
.then((command: ICommand) => {
|
||||||
|
client.commands.set(command.builder.name, command);
|
||||||
|
|
||||||
const totalCommands = commandNames.length;
|
commandProfiler.done({
|
||||||
let loadedCommands = 0;
|
commandName,
|
||||||
|
message: `Registered command '${commandName}'`,
|
||||||
|
level: "debug",
|
||||||
|
});
|
||||||
|
|
||||||
logger.info(`🔧 Loading ${totalCommands} commands`);
|
return command;
|
||||||
|
})
|
||||||
// Import an command.
|
.catch((error) => {
|
||||||
const importCommand = async (name: string) => {
|
commandProfiler.done({
|
||||||
const command: ICommand = await import(`../../commands/${name}`);
|
message: `Failed to register command '${commandName}'`,
|
||||||
|
commandName,
|
||||||
client.commands.set(command.builder.name, command);
|
error,
|
||||||
return loadedCommands++;
|
level: "error",
|
||||||
};
|
});
|
||||||
|
});
|
||||||
for await (const commandName of commandNames) {
|
|
||||||
await importCommand(commandName).then(() => {
|
|
||||||
return logger.verbose(`🔧 Loaded command "${commandName}"`);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loadedCommands === totalCommands) {
|
|
||||||
return logger.info("🔧 All commands loaded");
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,12 @@ prisma.$use(async (params, next) => {
|
||||||
`Query ${params.model}.${params.action} took ${after - before}ms`
|
`Query ${params.model}.${params.action} took ${after - before}ms`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (after - before >= 50) {
|
||||||
|
logger.warn(
|
||||||
|
`Query ${params.model}.${params.action} took ${after - before}ms`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BaseInteraction, EmbedBuilder } from "discord.js";
|
import { BaseInteraction, EmbedBuilder } from "discord.js";
|
||||||
import getEmbedConfig from "../../helpers/getEmbedData";
|
import getEmbedData from "../../helpers/getEmbedData";
|
||||||
|
|
||||||
export default async (interaction: BaseInteraction, ephemeral: boolean) => {
|
export default async (interaction: BaseInteraction, ephemeral: boolean) => {
|
||||||
if (!interaction.isRepliable())
|
if (!interaction.isRepliable())
|
||||||
|
@ -9,7 +9,7 @@ export default async (interaction: BaseInteraction, ephemeral: boolean) => {
|
||||||
ephemeral,
|
ephemeral,
|
||||||
});
|
});
|
||||||
|
|
||||||
const embedConfig = await getEmbedConfig(interaction.guild);
|
const embedConfig = await getEmbedData(interaction.guild);
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
embeds: [
|
embeds: [
|
||||||
|
|
|
@ -1,39 +1,29 @@
|
||||||
import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js";
|
import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js";
|
||||||
import { ICommand } from "../../interfaces/Command";
|
|
||||||
import logger from "../../middlewares/logger";
|
import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
export default async (client: Client) => {
|
export default async (client: Client) => {
|
||||||
// 1. Destructure the client.
|
|
||||||
const { application } = client;
|
const { application } = client;
|
||||||
if (!application) throw new Error("No application found");
|
if (!application) throw new Error("No application found");
|
||||||
|
|
||||||
// 2. Log that we are starting the command management.
|
const builders: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
|
||||||
logger.info("🔧 Started command deployment");
|
|
||||||
|
|
||||||
// 3. Get the commands.
|
client.commands.forEach((command) => {
|
||||||
const commands: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
|
builders.push(command.builder.toJSON());
|
||||||
client.commands.forEach((command: ICommand) => {
|
|
||||||
commands.push(command.builder.toJSON());
|
|
||||||
|
|
||||||
logger.verbose(`🔧 Loaded command "${command.builder.name}"`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. Set the commands.
|
await application.commands.set(builders).then(() => {
|
||||||
await application.commands.set(commands).then(() => {
|
logger.info({ builders, message: "Registered commands to users!" });
|
||||||
logger.info("🔧 Deployed commands globally");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 5. Tell the user that development mode is enabled.
|
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (process.env.NODE_ENV === "development") {
|
||||||
logger.info("🔧 Development mode enabled");
|
|
||||||
|
|
||||||
await application.commands
|
await application.commands
|
||||||
.set(commands, process.env.DISCORD_GUILD_ID)
|
.set(builders, process.env.DISCORD_GUILD_ID)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info(`🔧 Deployed commands to guild`);
|
logger.info({
|
||||||
|
builders,
|
||||||
|
devGuildId: process.env.DISCORD_GUILD_ID,
|
||||||
|
message: "Registered commands to development guild!",
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Log that we are done with the command management.
|
|
||||||
logger.info("🔧 Finished command deployment");
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,49 +6,51 @@ import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
// Registers all available events.
|
// Registers all available events.
|
||||||
export const register = async (client: Client) => {
|
export const register = async (client: Client) => {
|
||||||
logger.info("📡 Started event management");
|
const profiler = logger.startTimer();
|
||||||
|
|
||||||
const eventNames = await checkDirectory("events");
|
await checkDirectory("events").then(async (eventNames) => {
|
||||||
if (!eventNames) return logger.warn("No available events found");
|
const totalEvents = eventNames.length;
|
||||||
|
let loadedEvents = 0;
|
||||||
|
|
||||||
const totalEvents = eventNames.length;
|
// Import an event.
|
||||||
let loadedEvents = 0;
|
const importEvent = async (name: string) => {
|
||||||
|
await import(`../../events/${name}`).then((event: IEvent) => {
|
||||||
|
// Create a new event execute function.
|
||||||
|
const eventExecutor = async (...args: Promise<void>[]) => {
|
||||||
|
await event.execute(...args);
|
||||||
|
};
|
||||||
|
|
||||||
logger.info(`📡 Loading ${totalEvents} events`);
|
switch (event.options.type) {
|
||||||
|
case "once":
|
||||||
|
client.once(name, eventExecutor);
|
||||||
|
break;
|
||||||
|
|
||||||
// Import an event.
|
case "on":
|
||||||
const importEvent = async (name: string) => {
|
client.on(name, eventExecutor);
|
||||||
const event: IEvent = await import(`../../events/${name}`);
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown event type`);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new event execute function.
|
logger.debug({
|
||||||
const eventExecutor = async (...args: Promise<void>[]) => {
|
eventName: name,
|
||||||
await event.execute(...args);
|
type: event.options.type,
|
||||||
|
message: `Listening to event '${name}'`,
|
||||||
|
});
|
||||||
|
return loadedEvents++;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (event.options.type) {
|
for await (const eventName of eventNames) {
|
||||||
case "once":
|
await importEvent(eventName);
|
||||||
client.once(name, eventExecutor);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "on":
|
if (loadedEvents === totalEvents) {
|
||||||
client.on(name, eventExecutor);
|
return profiler.done({
|
||||||
break;
|
message: "Successfully listening to all events!",
|
||||||
default:
|
});
|
||||||
throw new Error(`📡 Invalid event type for event: ${name}`);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return loadedEvents++;
|
return true;
|
||||||
};
|
});
|
||||||
|
|
||||||
for await (const eventName of eventNames) {
|
|
||||||
await importEvent(eventName).then(() => {
|
|
||||||
return logger.verbose(`📡 Loaded event "${eventName}"`);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loadedEvents === totalEvents) {
|
|
||||||
return logger.info("📡 All events loaded");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,19 +6,25 @@ import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
// Start all jobs that are in the schedules directory
|
// Start all jobs that are in the schedules directory
|
||||||
export const start = async (client: Client) => {
|
export const start = async (client: Client) => {
|
||||||
logger.info("⏰ Started job management");
|
|
||||||
|
|
||||||
const jobNames = await checkDirectory("schedules");
|
const jobNames = await checkDirectory("schedules");
|
||||||
if (!jobNames) return logger.warn("⏰ No available jobs found");
|
if (!jobNames) return logger.warn("⏰ No available jobs found");
|
||||||
|
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
jobNames.map(async (jobName) => {
|
jobNames.map(async (jobName) => {
|
||||||
const job: IJob = await import(`../../schedules/${jobName}`);
|
await import(`../../schedules/${jobName}`)
|
||||||
|
.then((job: IJob) => {
|
||||||
return schedule.scheduleJob(job.options.schedule, async () => {
|
return schedule.scheduleJob(job.options.schedule, async () => {
|
||||||
logger.verbose(`⏰ Performed the job "${jobName}"`);
|
logger.verbose(`⏰ Performed the job "${jobName}"`);
|
||||||
await job.execute(client);
|
await job.execute(client);
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
logger.warn({
|
||||||
|
jobName,
|
||||||
|
message: `Failed to start job ${jobName}`,
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Dependencies
|
// Dependencies
|
||||||
import { ActivityType, Client } from "discord.js";
|
import { ActivitiesOptions, ActivityType, Client } from "discord.js";
|
||||||
import logger from "../../middlewares/logger";
|
import logger from "../../middlewares/logger";
|
||||||
|
|
||||||
// Function
|
// Function
|
||||||
|
@ -12,18 +12,27 @@ export default (client: Client) => {
|
||||||
const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0);
|
const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0);
|
||||||
const guildCount = guilds.cache.size;
|
const guildCount = guilds.cache.size;
|
||||||
|
|
||||||
|
const activities: ActivitiesOptions[] = [
|
||||||
|
{
|
||||||
|
name: `${guildCount} guilds`,
|
||||||
|
type: ActivityType.Watching,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${memberCount} members`,
|
||||||
|
type: ActivityType.Watching,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const activity = activities[Math.floor(Math.random() * activities.length)];
|
||||||
|
|
||||||
// 3. Set the presence.
|
// 3. Set the presence.
|
||||||
user.setPresence({
|
user.setActivity(activity);
|
||||||
activities: [
|
|
||||||
{
|
|
||||||
name: `${guildCount} guilds | ${memberCount} members`,
|
|
||||||
type: ActivityType.Watching,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// 4. Log the presence.
|
// 4. Log the presence.
|
||||||
return logger.info(
|
return logger.debug({
|
||||||
`👀 Presence set to "${guildCount} guilds | ${memberCount} members"`
|
guildCount,
|
||||||
);
|
memberCount,
|
||||||
|
message: `Presence updated`,
|
||||||
|
activity,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import logger from "../../middlewares/logger";
|
||||||
const fsPromises = fs.promises;
|
const fsPromises = fs.promises;
|
||||||
|
|
||||||
export default async (path: string) => {
|
export default async (path: string) => {
|
||||||
const result = await fsPromises.readdir(`${__dirname}/../../${path}`);
|
const directoryPath = `${process.cwd()}/dist/${path}`;
|
||||||
return result;
|
|
||||||
|
return await fsPromises.readdir(directoryPath).then((result) => {
|
||||||
|
logger.debug({
|
||||||
|
message: `Checked directory ${path}`,
|
||||||
|
directoryPath,
|
||||||
|
result,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import winston from "winston";
|
import winston from "winston";
|
||||||
import "winston-daily-rotate-file";
|
import "winston-daily-rotate-file";
|
||||||
|
|
||||||
const { combine, timestamp, printf, errors, colorize, align, json } =
|
const { combine, timestamp, json, errors, colorize, align, printf } =
|
||||||
winston.format;
|
winston.format;
|
||||||
|
const logger = winston.createLogger({
|
||||||
export default winston.createLogger({
|
|
||||||
level: process.env.LOG_LEVEL || "info",
|
level: process.env.LOG_LEVEL || "info",
|
||||||
|
format: combine(errors({ stack: true }), timestamp(), json()),
|
||||||
transports: [
|
transports: [
|
||||||
new winston.transports.DailyRotateFile({
|
new winston.transports.DailyRotateFile({
|
||||||
filename: "logs/combined-%DATE%.log",
|
filename: "logs/combined-%DATE%.log",
|
||||||
datePattern: "YYYY-MM-DD",
|
datePattern: "YYYY-MM-DD",
|
||||||
maxFiles: "14d",
|
maxFiles: "14d",
|
||||||
format: combine(timestamp(), json()),
|
format: combine(errors({ stack: true }), timestamp(), json()),
|
||||||
}),
|
}),
|
||||||
new winston.transports.Console({
|
new winston.transports.Console({
|
||||||
format: combine(
|
format: combine(
|
||||||
|
@ -21,8 +21,13 @@ export default winston.createLogger({
|
||||||
format: "YYYY-MM-DD HH:MM:ss",
|
format: "YYYY-MM-DD HH:MM:ss",
|
||||||
}),
|
}),
|
||||||
align(),
|
align(),
|
||||||
printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`)
|
printf(
|
||||||
|
(info) =>
|
||||||
|
`[${info.timestamp}] ${info.level}: ${info.stack || info.message}`
|
||||||
|
)
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default logger;
|
||||||
|
|
Loading…
Add table
Reference in a new issue