refactor: 🚸 refactor and improve ux in heplers and middlewares

This commit is contained in:
Axel Olausson Holtenäs 2022-12-25 02:39:32 +01:00
parent d62baa0b9c
commit 193032e3ba
11 changed files with 140 additions and 111 deletions

View file

@ -16,7 +16,7 @@ export default async (interaction: ChatInputCommandInteraction) => {
const { client, commandName } = interaction;
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) => {
const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(

View file

@ -12,7 +12,11 @@ export const options: IEventOptions = {
// Execute the event
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);
await deployCommands(client);

View file

@ -6,32 +6,30 @@ import logger from "../../middlewares/logger";
// Register the commands.
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");
if (!commandNames) return logger.warn("No available commands found");
await import(`../../commands/${commandName}`)
.then((command: ICommand) => {
client.commands.set(command.builder.name, command);
const totalCommands = commandNames.length;
let loadedCommands = 0;
commandProfiler.done({
commandName,
message: `Registered command '${commandName}'`,
level: "debug",
});
logger.info(`🔧 Loading ${totalCommands} commands`);
// Import an command.
const importCommand = async (name: string) => {
const command: ICommand = await import(`../../commands/${name}`);
client.commands.set(command.builder.name, command);
return loadedCommands++;
};
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 command;
})
.catch((error) => {
commandProfiler.done({
message: `Failed to register command '${commandName}'`,
commandName,
error,
level: "error",
});
});
}
}
return true;
});
};

View file

@ -14,6 +14,12 @@ prisma.$use(async (params, next) => {
`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;
});

View file

@ -1,5 +1,5 @@
import { BaseInteraction, EmbedBuilder } from "discord.js";
import getEmbedConfig from "../../helpers/getEmbedData";
import getEmbedData from "../../helpers/getEmbedData";
export default async (interaction: BaseInteraction, ephemeral: boolean) => {
if (!interaction.isRepliable())
@ -9,7 +9,7 @@ export default async (interaction: BaseInteraction, ephemeral: boolean) => {
ephemeral,
});
const embedConfig = await getEmbedConfig(interaction.guild);
const embedConfig = await getEmbedData(interaction.guild);
await interaction.editReply({
embeds: [

View file

@ -1,39 +1,29 @@
import { Client, RESTPostAPIApplicationCommandsJSONBody } from "discord.js";
import { ICommand } from "../../interfaces/Command";
import logger from "../../middlewares/logger";
export default async (client: Client) => {
// 1. Destructure the client.
const { application } = client;
if (!application) throw new Error("No application found");
// 2. Log that we are starting the command management.
logger.info("🔧 Started command deployment");
const builders: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
// 3. Get the commands.
const commands: Array<RESTPostAPIApplicationCommandsJSONBody> = [];
client.commands.forEach((command: ICommand) => {
commands.push(command.builder.toJSON());
logger.verbose(`🔧 Loaded command "${command.builder.name}"`);
client.commands.forEach((command) => {
builders.push(command.builder.toJSON());
});
// 4. Set the commands.
await application.commands.set(commands).then(() => {
logger.info("🔧 Deployed commands globally");
await application.commands.set(builders).then(() => {
logger.info({ builders, message: "Registered commands to users!" });
});
// 5. Tell the user that development mode is enabled.
if (process.env.NODE_ENV === "development") {
logger.info("🔧 Development mode enabled");
await application.commands
.set(commands, process.env.DISCORD_GUILD_ID)
.set(builders, process.env.DISCORD_GUILD_ID)
.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");
};

View file

@ -6,49 +6,51 @@ import logger from "../../middlewares/logger";
// Registers all available events.
export const register = async (client: Client) => {
logger.info("📡 Started event management");
const profiler = logger.startTimer();
const eventNames = await checkDirectory("events");
if (!eventNames) return logger.warn("No available events found");
await checkDirectory("events").then(async (eventNames) => {
const totalEvents = eventNames.length;
let loadedEvents = 0;
const totalEvents = eventNames.length;
let loadedEvents = 0;
// Import an event.
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.
const importEvent = async (name: string) => {
const event: IEvent = await import(`../../events/${name}`);
case "on":
client.on(name, eventExecutor);
break;
default:
throw new Error(`Unknown event type`);
}
// Create a new event execute function.
const eventExecutor = async (...args: Promise<void>[]) => {
await event.execute(...args);
logger.debug({
eventName: name,
type: event.options.type,
message: `Listening to event '${name}'`,
});
return loadedEvents++;
});
};
switch (event.options.type) {
case "once":
client.once(name, eventExecutor);
break;
for await (const eventName of eventNames) {
await importEvent(eventName);
case "on":
client.on(name, eventExecutor);
break;
default:
throw new Error(`📡 Invalid event type for event: ${name}`);
if (loadedEvents === totalEvents) {
return profiler.done({
message: "Successfully listening to all events!",
});
}
}
return loadedEvents++;
};
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;
return true;
});
};

View file

@ -6,19 +6,25 @@ import logger from "../../middlewares/logger";
// Start all jobs that are in the schedules directory
export const start = async (client: Client) => {
logger.info("⏰ Started job management");
const jobNames = await checkDirectory("schedules");
if (!jobNames) return logger.warn("⏰ No available jobs found");
return await Promise.all(
jobNames.map(async (jobName) => {
const job: IJob = await import(`../../schedules/${jobName}`);
return schedule.scheduleJob(job.options.schedule, async () => {
logger.verbose(`⏰ Performed the job "${jobName}"`);
await job.execute(client);
});
await import(`../../schedules/${jobName}`)
.then((job: IJob) => {
return schedule.scheduleJob(job.options.schedule, async () => {
logger.verbose(`⏰ Performed the job "${jobName}"`);
await job.execute(client);
});
})
.catch((error) => {
logger.warn({
jobName,
message: `Failed to start job ${jobName}`,
error,
});
});
})
);
};

View file

@ -1,5 +1,5 @@
// Dependencies
import { ActivityType, Client } from "discord.js";
import { ActivitiesOptions, ActivityType, Client } from "discord.js";
import logger from "../../middlewares/logger";
// Function
@ -12,18 +12,27 @@ export default (client: Client) => {
const memberCount = guilds.cache.reduce((a, g) => a + g.memberCount, 0);
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.
user.setPresence({
activities: [
{
name: `${guildCount} guilds | ${memberCount} members`,
type: ActivityType.Watching,
},
],
});
user.setActivity(activity);
// 4. Log the presence.
return logger.info(
`👀 Presence set to "${guildCount} guilds | ${memberCount} members"`
);
return logger.debug({
guildCount,
memberCount,
message: `Presence updated`,
activity,
});
};

View file

@ -1,7 +1,16 @@
import fs from "fs";
import logger from "../../middlewares/logger";
const fsPromises = fs.promises;
export default async (path: string) => {
const result = await fsPromises.readdir(`${__dirname}/../../${path}`);
return result;
const directoryPath = `${process.cwd()}/dist/${path}`;
return await fsPromises.readdir(directoryPath).then((result) => {
logger.debug({
message: `Checked directory ${path}`,
directoryPath,
result,
});
return result;
});
};

View file

@ -1,17 +1,17 @@
import winston from "winston";
import "winston-daily-rotate-file";
const { combine, timestamp, printf, errors, colorize, align, json } =
const { combine, timestamp, json, errors, colorize, align, printf } =
winston.format;
export default winston.createLogger({
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || "info",
format: combine(errors({ stack: true }), timestamp(), json()),
transports: [
new winston.transports.DailyRotateFile({
filename: "logs/combined-%DATE%.log",
datePattern: "YYYY-MM-DD",
maxFiles: "14d",
format: combine(timestamp(), json()),
format: combine(errors({ stack: true }), timestamp(), json()),
}),
new winston.transports.Console({
format: combine(
@ -21,8 +21,13 @@ export default winston.createLogger({
format: "YYYY-MM-DD HH:MM:ss",
}),
align(),
printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`)
printf(
(info) =>
`[${info.timestamp}] ${info.level}: ${info.stack || info.message}`
)
),
}),
],
});
export default logger;