From ef5dd38aaa0dca2c0d1d6a16c493abad9107dedd Mon Sep 17 00:00:00 2001 From: Artemus <31190188+Mr-Artemus@users.noreply.github.com> Date: Mon, 25 Jul 2022 22:14:45 +0000 Subject: [PATCH 1/4] feat(function): waitForDependency and waitForAllDependency functions --- src/utils/functions/dependency.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/utils/functions/dependency.ts diff --git a/src/utils/functions/dependency.ts b/src/utils/functions/dependency.ts new file mode 100644 index 00000000..cb72a078 --- /dev/null +++ b/src/utils/functions/dependency.ts @@ -0,0 +1,10 @@ +import { container, InjectionToken } from 'tsyringe' + +export async function waitForDependency(token: InjectionToken, interval: number = 500): Promise { + while(!container.isRegistered(token, true)) await new Promise(resolve => setTimeout(resolve, interval)); + return container.resolve(token); +} + +export async function waitForAllDependency(tokens: any[], interval: number = 500): Promise { + return Promise.all(tokens.map(token => waitForDependency(token, interval))); +} \ No newline at end of file From 32d65970e7ad205992a0e19c4db49faba4876f04 Mon Sep 17 00:00:00 2001 From: Artemus <31190188+Mr-Artemus@users.noreply.github.com> Date: Mon, 25 Jul 2022 22:15:43 +0000 Subject: [PATCH 2/4] feat(dependency): replace all `container.resolve` --- src/api/middlewares/authenticated.ts | 5 +-- src/api/middlewares/log.ts | 25 ++++++----- src/events/ready.ts | 10 ++--- src/main.ts | 17 ++++---- src/services/Logger.ts | 63 +++++++++++++++------------- src/utils/classes/BaseError.ts | 8 ++-- src/utils/decorators/Schedule.ts | 8 ++-- src/utils/decorators/WSOn.ts | 26 ++++-------- src/utils/errors/NoBotToken.ts | 7 ---- src/utils/functions/database.ts | 6 +-- src/utils/functions/image.ts | 5 ++- src/utils/functions/index.ts | 3 +- src/utils/functions/maintenance.ts | 10 ++--- src/utils/functions/prefix.ts | 6 +-- src/utils/functions/synchronizer.ts | 18 ++++---- 15 files changed, 104 insertions(+), 113 deletions(-) diff --git a/src/api/middlewares/authenticated.ts b/src/api/middlewares/authenticated.ts index b099fb8c..ab995c07 100644 --- a/src/api/middlewares/authenticated.ts +++ b/src/api/middlewares/authenticated.ts @@ -1,18 +1,17 @@ -import { container } from "tsyringe" import { Context, Next } from "koa" import DiscordOauth2 from "discord-oauth2" -import { isDev } from "@utils/functions" +import { isDev, waitForDependency } from "@utils/functions" import { Store } from "@services" const discordOauth2 = new DiscordOauth2() -const store = container.resolve(Store) const timeout = 10 * 60 * 1000 const fmaTokenRegex = /mfa\.[\w-]{84}/ const nonFmaTokenRegex = /[\w-]{24}\.[\w-]{6}\.[\w-]{27}/ export async function authenticated(ctx: Context, next: Next) { + const store = await waitForDependency(Store) // if we are in development mode, we don't need to check the token // if (process.env['NODE_ENV'] === 'development') return next() diff --git a/src/api/middlewares/log.ts b/src/api/middlewares/log.ts index 005745c1..1a37e854 100644 --- a/src/api/middlewares/log.ts +++ b/src/api/middlewares/log.ts @@ -1,24 +1,23 @@ import chalk from "chalk" import { Context, Next } from "koa" -import { container } from "tsyringe" import { Logger } from "@services" - -const logger = container.resolve(Logger) +import { waitForDependency } from "@utils/functions" export function globalLog(ctx: Context, next: Next) { + waitForDependency(Logger).then(logger => { + // don't log anything if the request has a `logIgnore` query params + if (!ctx.query.logIgnore) { - // don't log anything if the request has a `logIgnore` query params - if (!ctx.query.logIgnore) { - - const { method, url } = ctx.request + const { method, url } = ctx.request - const message = `(API) ${method} - ${url}` - const chalkedMessage = `(${chalk.bold.white('API')}) ${chalk.bold.green(method)} - ${chalk.bold.blue(url)}` + const message = `(API) ${method} - ${url}` + const chalkedMessage = `(${chalk.bold.white('API')}) ${chalk.bold.green(method)} - ${chalk.bold.blue(url)}` - logger.console('info', chalkedMessage) - logger.file('info', message) - } + logger.console('info', chalkedMessage) + logger.file('info', message) + } - return next() + return next() + }); } \ No newline at end of file diff --git a/src/events/ready.ts b/src/events/ready.ts index 48e8f20d..f7eebf04 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,13 +1,13 @@ import { Client } from 'discordx' +import { injectable } from 'tsyringe' import { ActivityType } from 'discord.js' -import { container, injectable } from 'tsyringe' +import { Data } from '@entities' +import { generalConfig, logsConfig } from '@config' import { Once, Discord, Schedule } from '@decorators' import { Database, Logger, Scheduler } from '@services' -import { Data } from '@entities' -import { syncAllGuilds } from '@utils/functions' +import { syncAllGuilds, waitForDependency } from '@utils/functions' -import { generalConfig, logsConfig } from '@config' @Discord() @injectable() @@ -69,7 +69,7 @@ export default class ReadyEvent { async changeActivity() { const ActivityTypeEnumString = ["PLAYING", "STREAMING", "LISTENING", "WATCHING", "CUSTOM", "COMPETING"] // DO NOT CHANGE THE ORDER - const client = container.resolve(Client) + const client = await waitForDependency(Client) const activity = generalConfig.activities[this.activityIndex] activity.text = eval(`new String(\`${activity.text}\`).toString()`) diff --git a/src/main.ts b/src/main.ts index 8c9005f3..6bf3d7d2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,7 @@ import { DIService, Client } from 'discordx' import { importx } from '@discordx/importer' import { Database, ImagesUpload, ErrorHandler, Logger, WebSocket } from '@services' -import { initDataTable } from '@utils/functions' +import { initDataTable, waitForDependency } from '@utils/functions' import { Server } from '@api/server' import { clientConfig } from './client' @@ -16,12 +16,12 @@ import { NoBotTokenError } from '@errors' async function run() { // start loading - const logger = container.resolve(Logger) + const logger = await waitForDependency(Logger) console.log('\n') logger.startSpinner('Starting...') // init the sqlite database - const db = container.resolve(Database) + const db = await waitForDependency(Database) await db.initialize() // init the client @@ -30,7 +30,7 @@ async function run() { container.registerInstance(Client, client) // init the error handler - container.resolve(ErrorHandler) + await waitForDependency(ErrorHandler) // import all the commands and events await importx(__dirname + "/{events,commands,api}/**/*.{ts,js}") @@ -43,14 +43,17 @@ async function run() { await client.login(process.env.BOT_TOKEN) // start the api server - await container.resolve(Server).start() + const server = await waitForDependency(Server) + await server.start() // connect to the dashboard websocket - await container.resolve(WebSocket).init(client.user?.id || null) + const webSocket = await waitForDependency(WebSocket) + await webSocket.init(client.user?.id || null) // upload images to imgur if configured if (process.env.IMGUR_CLIENT_ID && generalConfig.automaticUploadImagesToImgur) { - container.resolve(ImagesUpload).syncWithDatabase() + const imagesUpload = await waitForDependency(ImagesUpload) + await imagesUpload.syncWithDatabase() } } diff --git a/src/services/Logger.ts b/src/services/Logger.ts index 79ecb8cc..6e39ea41 100644 --- a/src/services/Logger.ts +++ b/src/services/Logger.ts @@ -1,14 +1,14 @@ -import { Guild, TextChannel, ThreadChannel, User } from 'discord.js' -import { Client, MetadataStorage, SimpleCommandMessage } from 'discordx' +import { TextChannel, ThreadChannel, User } from 'discord.js' +import { Client, MetadataStorage } from 'discordx' import { MetadataStorage as KoaMetadataStorage } from '@discordx/koa' -import { container, delay, inject, singleton } from 'tsyringe' +import { delay, inject, singleton } from 'tsyringe' import { constant } from 'case' import fs from 'fs' import chalk from 'chalk' import boxen from 'boxen' import ora from 'ora' -import { formatDate, getTypeOfInteraction, numberAlign, oneLine, resolveAction, resolveChannel, resolveGuild, resolveUser, validString } from '@utils/functions' +import { formatDate, getTypeOfInteraction, numberAlign, oneLine, resolveAction, resolveChannel, resolveGuild, resolveUser, validString, waitForDependency } from '@utils/functions' import { Scheduler, WebSocket } from '@services' import { apiConfig, logsConfig } from '@config' @@ -79,17 +79,18 @@ export class Logger { discordChannel(channelId: string, message: string = '', level?: typeof this.levels[number]) { - const client = container.resolve(Client) - const channel = client.channels.cache.get(channelId) + waitForDependency(Client).then(client => { + const channel = client.channels.cache.get(channelId) - if ( - channel instanceof TextChannel - || channel instanceof ThreadChannel - ) { - - // TODO: add support for embeds depending on the level - channel.send(message) - } + if ( + channel instanceof TextChannel + || channel instanceof ThreadChannel + ) { + + // TODO: add support for embeds depending on the level + channel.send(message) + } + }) } // ================================= @@ -196,22 +197,24 @@ export class Logger { type === 'DELETE_GUILD' ? 'has been deleted' : type === 'RECOVER_GUILD' ? 'has been recovered' : '' - const guild = container.resolve(Client).guilds.cache.get(guildId) - - const message = `(${type}) Guild ${guild ? `${guild.name} (${guildId})` : guildId} ${additionalMessage}` - const chalkedMessage = oneLine` - (${chalk.bold.white(type)}) - ${chalk.dim.italic.gray('Guild')} - ${guild ? - `${chalk.bold.green(guild.name)} (${chalk.bold.blue(guildId)})` - : guildId - } - ${chalk.dim.italic.gray(additionalMessage)} - ` - - if (logsConfig.guild.console) this.console('info', chalkedMessage) - if (logsConfig.guild.file) this.file('info', message) - if (logsConfig.guild.channel) this.discordChannel(logsConfig.guild.channel, message, 'info') + waitForDependency(Client).then(client => { + const guild = client.guilds.cache.get(guildId) + + const message = `(${type}) Guild ${guild ? `${guild.name} (${guildId})` : guildId} ${additionalMessage}` + const chalkedMessage = oneLine` + (${chalk.bold.white(type)}) + ${chalk.dim.italic.gray('Guild')} + ${guild ? + `${chalk.bold.green(guild.name)} (${chalk.bold.blue(guildId)})` + : guildId + } + ${chalk.dim.italic.gray(additionalMessage)} + ` + + if (logsConfig.guild.console) this.console('info', chalkedMessage) + if (logsConfig.guild.file) this.file('info', message) + if (logsConfig.guild.channel) this.discordChannel(logsConfig.guild.channel, message, 'info') + }) } // ================================= diff --git a/src/utils/classes/BaseError.ts b/src/utils/classes/BaseError.ts index 331519d1..171074fa 100644 --- a/src/utils/classes/BaseError.ts +++ b/src/utils/classes/BaseError.ts @@ -1,14 +1,16 @@ import { Logger } from "@services" -import { container } from "tsyringe" +import { waitForDependency } from "@utils/functions" + export abstract class BaseError extends Error { protected logger: Logger constructor(message?: string) { - super(message) - this.logger = container.resolve(Logger) + waitForDependency(Logger).then(logger => { + this.logger = logger + }) } handle() {} diff --git a/src/utils/decorators/Schedule.ts b/src/utils/decorators/Schedule.ts index c6c6b249..7ce27254 100644 --- a/src/utils/decorators/Schedule.ts +++ b/src/utils/decorators/Schedule.ts @@ -3,6 +3,7 @@ import { isValidCron } from "cron-validator" import { CronJob } from 'cron' import { generalConfig } from '@config' +import { waitForDependency } from "@utils/functions" /** * Schedule a job to be executed at a specific time (cron) @@ -18,13 +19,12 @@ export const Schedule = (cronExpression: string, jobName?: string) => { propertyKey: string, descriptor: PropertyDescriptor ) => { - // associate the context to the function, with the injected dependencies defined const oldDescriptor = descriptor.value descriptor.value = function(...args: any[]) { return oldDescriptor.apply(container.resolve(this.constructor as InjectionToken), args) } - + const job = new CronJob( cronExpression, descriptor.value, @@ -34,8 +34,8 @@ export const Schedule = (cronExpression: string, jobName?: string) => { target ) - import('@services').then(services => { - const scheduler = container.resolve(services.Scheduler) + import('@services').then(async services => { + const scheduler = await waitForDependency(services.Scheduler) scheduler.addJob(jobName ?? propertyKey, job) }) } diff --git a/src/utils/decorators/WSOn.ts b/src/utils/decorators/WSOn.ts index aa404f7f..1e0e1cd3 100644 --- a/src/utils/decorators/WSOn.ts +++ b/src/utils/decorators/WSOn.ts @@ -1,4 +1,4 @@ -import { container, InjectionToken } from 'tsyringe' +import { waitForDependency } from '@utils/functions' /** * Handle websocket events @@ -16,22 +16,14 @@ export const WSOn = (event: string) => { propertyKey: string, descriptor: PropertyDescriptor ) { - - // associate the context to the function, with the injected dependencies defined - const oldDescriptor = descriptor.value - descriptor.value = function(...args: any[]) { - return oldDescriptor.apply(container.resolve(target.constructor as InjectionToken), args) - } - import('@services').then(services => { - - const webSocket = container.resolve(services.WebSocket) - - webSocket.addEvent(event, async (socketId, ...args) => { - descriptor.value((eventName: string, ...args: any) => { - webSocket.emit(socketId, eventName, ...args) - }, ...args) - }) - }) + waitForDependency(services.WebSocket).then(webSocket => { + webSocket.addEvent(event, async (socketId, ...args) => { + descriptor.value((eventName: string, ...args: any) => { + webSocket.emit(socketId, eventName, ...args) + }, ...args); + }); + }); + }); } } \ No newline at end of file diff --git a/src/utils/errors/NoBotToken.ts b/src/utils/errors/NoBotToken.ts index 98b8a5ee..3fc42b0b 100644 --- a/src/utils/errors/NoBotToken.ts +++ b/src/utils/errors/NoBotToken.ts @@ -1,15 +1,8 @@ -import { CommandInteraction } from "discord.js" - -import { getLocaleFromInteraction, L } from '@i18n' -import { simpleErrorEmbed } from '@utils/functions/embeds' import { BaseError } from "@utils/classes" -import { container, inject, injectable } from "tsyringe" -import { Logger } from "@services" export class NoBotTokenError extends BaseError { constructor() { - super('Could not find BOT_TOKEN in your environment') } diff --git a/src/utils/functions/database.ts b/src/utils/functions/database.ts index 740547032..3b623391 100644 --- a/src/utils/functions/database.ts +++ b/src/utils/functions/database.ts @@ -1,7 +1,7 @@ -import { container } from 'tsyringe' - import { Database } from '@services' import { Data } from '@entities' +import { waitForDependency } from '@utils/functions' + import { defaultData } from 'src/entities/Data' type DataType = keyof typeof defaultData @@ -11,7 +11,7 @@ type DataType = keyof typeof defaultData */ export const initDataTable = async () => { - const db = container.resolve(Database) + const db = await waitForDependency(Database) for (const key of Object.keys(defaultData)) { diff --git a/src/utils/functions/image.ts b/src/utils/functions/image.ts index 93d8db70..a4dd9626 100644 --- a/src/utils/functions/image.ts +++ b/src/utils/functions/image.ts @@ -1,6 +1,6 @@ +import { waitForDependency } from "@utils/functions" import { Database } from "@services" import { Image } from "@entities" -import { container } from "tsyringe" /** * Abstraction level for the image repository that will find an image by its name (with or withouth extension). @@ -9,7 +9,8 @@ import { container } from "tsyringe" */ export const getImage = async (imageName: string): Promise => { - const imageRepo = container.resolve(Database).getRepo(Image) + const db = await waitForDependency(Database) + const imageRepo = db.getRepo(Image) let image = await imageRepo.findOne({ $or: [ diff --git a/src/utils/functions/index.ts b/src/utils/functions/index.ts index 7c1fb6e6..a1546357 100644 --- a/src/utils/functions/index.ts +++ b/src/utils/functions/index.ts @@ -12,4 +12,5 @@ export * from './array' export * from './image' export * from './colors' export * from './date' -export * from './devs' \ No newline at end of file +export * from './devs' +export * from './dependency' \ No newline at end of file diff --git a/src/utils/functions/maintenance.ts b/src/utils/functions/maintenance.ts index 7a75d6d1..bdedfd68 100644 --- a/src/utils/functions/maintenance.ts +++ b/src/utils/functions/maintenance.ts @@ -1,5 +1,4 @@ -import { container } from "tsyringe" - +import { waitForDependency } from "@utils/functions" import { Database } from "@services" import { Data } from "@entities" @@ -8,7 +7,8 @@ import { Data } from "@entities" */ export const isInMaintenance = async (): Promise => { - const dataRepository = container.resolve(Database).getRepo(Data) + const db = await waitForDependency(Database) + const dataRepository = db.getRepo(Data) const maintenance = await dataRepository.get('maintenance') return maintenance @@ -18,7 +18,7 @@ export const isInMaintenance = async (): Promise => { * Set the maintenance state of the bot. */ export const setMaintenance = async (maintenance: boolean) => { - - const dataRepository = container.resolve(Database).getRepo(Data) + const db = await waitForDependency(Database) + const dataRepository = db.getRepo(Data) await dataRepository.set('maintenance', maintenance) } \ No newline at end of file diff --git a/src/utils/functions/prefix.ts b/src/utils/functions/prefix.ts index a06184b2..ff92b386 100644 --- a/src/utils/functions/prefix.ts +++ b/src/utils/functions/prefix.ts @@ -1,7 +1,7 @@ import { Message } from 'discord.js' +import { waitForDependency } from "@utils/functions" import { generalConfig } from '@config' -import { container } from 'tsyringe' import { Database } from '@services' import { Guild } from '@entities' @@ -10,8 +10,8 @@ import { Guild } from '@entities' * @param message */ export const getPrefixFromMessage = async (message: Message) => { - - const guildRepo = container.resolve(Database).getRepo(Guild) + const db = await waitForDependency(Database) + const guildRepo = db.getRepo(Guild) const guildId = message.guild?.id const guildData = await guildRepo.findOne({ id: guildId }) diff --git a/src/utils/functions/synchronizer.ts b/src/utils/functions/synchronizer.ts index fa66c025..8e4045aa 100644 --- a/src/utils/functions/synchronizer.ts +++ b/src/utils/functions/synchronizer.ts @@ -1,17 +1,16 @@ -import { container } from "tsyringe" -import { User as DUser, Guild as DGuild } from "discord.js" +import { Client } from "discordx" +import { User as DUser} from "discord.js" import { User, Guild } from "@entities" import { Database, Logger, Stats } from "@services" -import { Client } from "discordx" - -const db = container.resolve(Database) +import { waitForAllDependency, waitForDependency } from "@utils/functions" /** * Add a active user to the database if doesn't exist. * @param user */ export const syncUser = async (user: DUser) => { + const [ db, stats, logger ] = await waitForAllDependency([Database, Stats, Logger]) const userRepo = db.getRepo(User) @@ -27,8 +26,8 @@ export const syncUser = async (user: DUser) => { await userRepo.persistAndFlush(newUser) // record new user both in logs and stats - container.resolve(Stats).register('NEW_USER', user.id) - container.resolve(Logger).logNewUser(user) + stats.register('NEW_USER', user.id) + logger.logNewUser(user) } } @@ -38,9 +37,7 @@ export const syncUser = async (user: DUser) => { * @param client */ export const syncGuild = async (guildId: string, client: Client) => { - - const stats = container.resolve(Stats), - logger = container.resolve(Logger) + const [ db, stats, logger ] = await waitForAllDependency([Database, Stats, Logger]) const guildRepo = db.getRepo(Guild), guildData = await guildRepo.findOne({ id: guildId, deleted: false }) @@ -89,6 +86,7 @@ export const syncGuild = async (guildId: string, client: Client) => { * @param client */ export const syncAllGuilds = async (client: Client) => { + const db = await waitForDependency(Database) // add missing guilds const guilds = client.guilds.cache From e05d241a5d1af7f5ba11a7f721d1a611a6eb97fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartholom=C3=A9?= Date: Tue, 9 Aug 2022 21:49:43 +0200 Subject: [PATCH 3/4] refactor: code style --- src/api/controllers/health.ts | 4 +++- src/api/middlewares/authenticated.ts | 5 +++-- src/api/middlewares/botOnline.ts | 4 +++- src/commands/General/help.ts | 6 +++--- src/events/custom/guildAdmin.ts | 4 ++-- src/events/interactionCreate.ts | 2 +- src/services/Logger.ts | 4 ++-- src/services/Stats.ts | 4 ++-- src/utils/decorators/On.ts | 2 +- src/utils/decorators/Slash.ts | 14 +++++++------- src/utils/decorators/WSOn.ts | 8 ++++---- src/utils/functions/converter.ts | 2 +- src/utils/functions/dependency.ts | 15 +++++++++++---- src/utils/functions/interactions.ts | 4 ++-- src/utils/functions/request.ts | 4 ++++ src/utils/functions/synchronizer.ts | 7 ++++--- 16 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/api/controllers/health.ts b/src/api/controllers/health.ts index 8bffb4de..3abc0880 100644 --- a/src/api/controllers/health.ts +++ b/src/api/controllers/health.ts @@ -28,6 +28,8 @@ export class HealthController extends BaseController { lastStartup: await this.db.getRepo(Data).get('lastStartup'), } + console.debug(body) + this.ok(ctx, body) } @@ -36,7 +38,7 @@ export class HealthController extends BaseController { const body = this.stats.getLatency() - this.ok(ctx, body) + return this.ok(ctx, body) } @Get('/usage') diff --git a/src/api/middlewares/authenticated.ts b/src/api/middlewares/authenticated.ts index 079dbe6e..e14d80d5 100644 --- a/src/api/middlewares/authenticated.ts +++ b/src/api/middlewares/authenticated.ts @@ -1,17 +1,18 @@ +import { container } from "tsyringe" import { Context, Next } from "koa" import DiscordOauth2 from "discord-oauth2" -import { isDev, error, waitForDependency } from "@utils/functions" +import { isDev, error } from "@utils/functions" import { Store } from "@services" const discordOauth2 = new DiscordOauth2() +const store = container.resolve(Store) const timeout = 10 * 60 * 1000 const fmaTokenRegex = /mfa\.[\w-]{84}/ const nonFmaTokenRegex = /[\w-]{24}\.[\w-]{6}\.[\w-]{27}/ export async function authenticated(ctx: Context, next: Next) { - const store = await waitForDependency(Store) // if we are in development mode, we don't need to check the token // if (process.env['NODE_ENV'] === 'development') return next() diff --git a/src/api/middlewares/botOnline.ts b/src/api/middlewares/botOnline.ts index 2266563c..061a42b9 100644 --- a/src/api/middlewares/botOnline.ts +++ b/src/api/middlewares/botOnline.ts @@ -3,9 +3,11 @@ import { Context, Next } from "koa" import { apiConfig } from "@config" +const baseUrl = `http://localhost:${apiConfig.port}` + export async function botOnline(ctx: Context, next: Next) { - const { data } = await axios.get(`http://localhost:${apiConfig.port}/health/check`, { + const { data } = await axios.get(`${baseUrl}/health/check`, { params: { logIgnore: true } diff --git a/src/commands/General/help.ts b/src/commands/General/help.ts index 4e2429a2..d2942a97 100644 --- a/src/commands/General/help.ts +++ b/src/commands/General/help.ts @@ -21,9 +21,9 @@ export default class HelpCommand { }) help(interaction: CommandInteraction, client: Client, { sanitizedLocale }: InteractionData): void { - const embed = this.getEmbed({ client, interaction, locale: sanitizedLocale }); + const embed = this.getEmbed({ client, interaction, locale: sanitizedLocale }) - let components: any[] = []; + let components: any[] = [] components.push(this.getSelectDropdown("categories", sanitizedLocale).toJSON()) interaction.followUp({ @@ -38,7 +38,7 @@ export default class HelpCommand { const category = interaction.values[0] const embed = await this.getEmbed({ client, interaction, category, locale: sanitizedLocale }) - let components: any[] = []; + let components: any[] = [] components.push(this.getSelectDropdown("categories", sanitizedLocale).toJSON()) interaction.update({ diff --git a/src/events/custom/guildAdmin.ts b/src/events/custom/guildAdmin.ts index c4ab36f8..9101897f 100644 --- a/src/events/custom/guildAdmin.ts +++ b/src/events/custom/guildAdmin.ts @@ -1,10 +1,10 @@ -import { Collection, GuildMember, PermissionFlagsBits, Role } from 'discord.js'; +import { Collection, GuildMember, PermissionFlagsBits, Role } from 'discord.js' import { Client, ArgsOf } from 'discordx' import { injectable } from 'tsyringe' import { Logger } from '@services' import { Maintenance } from '@guards' -import { On, Discord, Guard } from '@decorators'; +import { On, Discord, Guard } from '@decorators' @Discord() @injectable() diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts index 71d73d63..3e2a4622 100644 --- a/src/events/interactionCreate.ts +++ b/src/events/interactionCreate.ts @@ -31,7 +31,7 @@ export default class InteractionCreateEvent { if( interaction instanceof MessageComponentInteraction || interaction instanceof DCommandInteraction - ) await interaction.deferReply(); + ) await interaction.deferReply() // insert user in db if not exists await syncUser(interaction.user) diff --git a/src/services/Logger.ts b/src/services/Logger.ts index 13cffefb..d568b8bb 100644 --- a/src/services/Logger.ts +++ b/src/services/Logger.ts @@ -21,7 +21,7 @@ export class Logger { @inject(delay(() => Scheduler)) private scheduler: Scheduler, @inject(delay(() => WebSocket)) private ws: WebSocket ) { - this.defaultConsole = { ...console }; + this.defaultConsole = { ...console } console.log = (...args) => this.log("info", args.join(", ")) console.info = (...args) => this.log("info", args.join(", ")) console.warn = (...args) => this.log("warn", args.join(", ")) @@ -32,7 +32,7 @@ export class Logger { private readonly logPath: string = `${__dirname.includes('build') ? `${__dirname}/..` : __dirname}/../../logs` private readonly levels = ['debug', 'info', 'warn', 'error'] as const private spinner = ora() - private defaultConsole: typeof console; + private defaultConsole: typeof console // ================================= // ======== Output Providers ======= diff --git a/src/services/Stats.ts b/src/services/Stats.ts index b7d01d7c..e5909138 100644 --- a/src/services/Stats.ts +++ b/src/services/Stats.ts @@ -249,8 +249,8 @@ export class Stats { const allDays = [...new Set(stats1.concat(stats2).map(stat => stat.date))] .sort((a, b) => { var aa = a.split('/').reverse().join(), - bb = b.split('/').reverse().join(); - return aa < bb ? -1 : (aa > bb ? 1 : 0); + bb = b.split('/').reverse().join() + return aa < bb ? -1 : (aa > bb ? 1 : 0) }) const sumStats = allDays.map(day => ({ diff --git a/src/utils/decorators/On.ts b/src/utils/decorators/On.ts index 1030abca..6c987e6f 100644 --- a/src/utils/decorators/On.ts +++ b/src/utils/decorators/On.ts @@ -23,7 +23,7 @@ export const On = (event: string, options?: EventOptions): MethodDecoratorEx => botIds: options?.botIds, event: event as DiscordEvents, once: false, - }).decorate(clazz.constructor, key, descriptor?.value); + }).decorate(clazz.constructor, key, descriptor?.value) MetadataStorage.instance.addOn(on) } diff --git a/src/utils/decorators/Slash.ts b/src/utils/decorators/Slash.ts index 63e4de0e..89ff27e8 100644 --- a/src/utils/decorators/Slash.ts +++ b/src/utils/decorators/Slash.ts @@ -1,4 +1,4 @@ -import { Locale } from 'discord-api-types/v9'; +import { Locale } from 'discord-api-types/v9' import { IGuild, Slash as SlashX, VerifyName } from 'discordx' enum AdditionnalLocaleString { @@ -8,12 +8,12 @@ enum AdditionnalLocaleString { type LocalizationMap = Partial> type ApplicationCommandOptions = { - botIds?: string[]; - defaultPermission?: boolean; - description?: string; - descriptionLocalizations?: LocalizationMap; - guilds?: IGuild[]; - nameLocalizations?: LocalizationMap; + botIds?: string[] + defaultPermission?: boolean + description?: string + descriptionLocalizations?: LocalizationMap + guilds?: IGuild[] + nameLocalizations?: LocalizationMap } /** diff --git a/src/utils/decorators/WSOn.ts b/src/utils/decorators/WSOn.ts index 1e0e1cd3..31cc4afd 100644 --- a/src/utils/decorators/WSOn.ts +++ b/src/utils/decorators/WSOn.ts @@ -21,9 +21,9 @@ export const WSOn = (event: string) => { webSocket.addEvent(event, async (socketId, ...args) => { descriptor.value((eventName: string, ...args: any) => { webSocket.emit(socketId, eventName, ...args) - }, ...args); - }); - }); - }); + }, ...args) + }) + }) + }) } } \ No newline at end of file diff --git a/src/utils/functions/converter.ts b/src/utils/functions/converter.ts index aafbff6b..99dd44e8 100644 --- a/src/utils/functions/converter.ts +++ b/src/utils/functions/converter.ts @@ -7,7 +7,7 @@ import fs from "fs" */ export const convertTZ = (date: Date, tzString: string): Date => { - return new Date((typeof date === "string" ? new Date(date) : date).toLocaleString("en-US", {timeZone: tzString})); + return new Date((typeof date === "string" ? new Date(date) : date).toLocaleString("en-US", {timeZone: tzString})) } /** diff --git a/src/utils/functions/dependency.ts b/src/utils/functions/dependency.ts index cb72a078..bccd0470 100644 --- a/src/utils/functions/dependency.ts +++ b/src/utils/functions/dependency.ts @@ -1,10 +1,17 @@ import { container, InjectionToken } from 'tsyringe' export async function waitForDependency(token: InjectionToken, interval: number = 500): Promise { - while(!container.isRegistered(token, true)) await new Promise(resolve => setTimeout(resolve, interval)); - return container.resolve(token); + + while(!container.isRegistered(token, true)) { + await new Promise(resolve => setTimeout(resolve, interval)) + } + + return container.resolve(token) } -export async function waitForAllDependency(tokens: any[], interval: number = 500): Promise { - return Promise.all(tokens.map(token => waitForDependency(token, interval))); +export async function waitForDependencies(tokens: any[], interval: number = 500): Promise { + + return Promise.all(tokens.map(token => + waitForDependency(token, interval) + )) } \ No newline at end of file diff --git a/src/utils/functions/interactions.ts b/src/utils/functions/interactions.ts index 6e3e80c7..a1d4d0a0 100644 --- a/src/utils/functions/interactions.ts +++ b/src/utils/functions/interactions.ts @@ -1,5 +1,5 @@ -import { CommandInteraction } from "discord.js"; -import { SimpleCommandMessage } from "discordx"; +import { CommandInteraction } from "discord.js" +import { SimpleCommandMessage } from "discordx" /** * Abstraction level to reply to either a slash command or a simple command message. diff --git a/src/utils/functions/request.ts b/src/utils/functions/request.ts index c1f74f22..7fd7a1a6 100644 --- a/src/utils/functions/request.ts +++ b/src/utils/functions/request.ts @@ -13,7 +13,11 @@ export const error = async (ctx: Context, message: string, status: StatusCodes) export const ok = async (ctx: Context, json: any) => { + console.debug('ok function started') + ctx.headers['content-type'] = 'application/json' ctx.status = StatusCodes.OK ctx.body = json + + console.debug('ok function finished') } \ No newline at end of file diff --git a/src/utils/functions/synchronizer.ts b/src/utils/functions/synchronizer.ts index 8e4045aa..493f3d20 100644 --- a/src/utils/functions/synchronizer.ts +++ b/src/utils/functions/synchronizer.ts @@ -3,14 +3,15 @@ import { User as DUser} from "discord.js" import { User, Guild } from "@entities" import { Database, Logger, Stats } from "@services" -import { waitForAllDependency, waitForDependency } from "@utils/functions" +import { waitForDependencies, waitForDependency } from "@utils/functions" /** * Add a active user to the database if doesn't exist. * @param user */ export const syncUser = async (user: DUser) => { - const [ db, stats, logger ] = await waitForAllDependency([Database, Stats, Logger]) + + const [ db, stats, logger ] = await waitForDependencies([Database, Stats, Logger]) const userRepo = db.getRepo(User) @@ -37,7 +38,7 @@ export const syncUser = async (user: DUser) => { * @param client */ export const syncGuild = async (guildId: string, client: Client) => { - const [ db, stats, logger ] = await waitForAllDependency([Database, Stats, Logger]) + const [ db, stats, logger ] = await waitForDependencies([Database, Stats, Logger]) const guildRepo = db.getRepo(Guild), guildData = await guildRepo.findOne({ id: guildId, deleted: false }) From 583b6eade72972c926d2d820cca8137096f73d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartholom=C3=A9?= Date: Tue, 9 Aug 2022 21:50:15 +0200 Subject: [PATCH 4/4] fix(api): koa not handling wait in middleware --- src/api/middlewares/log.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/api/middlewares/log.ts b/src/api/middlewares/log.ts index 30837603..e9fc49e5 100644 --- a/src/api/middlewares/log.ts +++ b/src/api/middlewares/log.ts @@ -1,25 +1,26 @@ +import { container } from "tsyringe" import chalk from "chalk" import { Context, Next } from "koa" import { Logger } from "@services" -import { waitForDependency } from "@utils/functions" -export function globalLog(ctx: Context, next: Next) { - waitForDependency(Logger).then(logger => { - // don't log anything if the request has a `logIgnore` query params - if (!ctx.query.logIgnore) { - const { method, url } = ctx.request +const logger = container.resolve(Logger) - const message = `(API) ${method} - ${url}` - const chalkedMessage = `(${chalk.bold.white('API')}) ${chalk.bold.green(method)} - ${chalk.bold.blue(url)}` +export async function globalLog(ctx: Context, next: Next) { - logger.console('info', chalkedMessage) - logger.file('info', message) - - } else { - delete ctx.query.logIgnore - } + // don't log anything if the request has a `logIgnore` query params + if (!ctx.query.logIgnore) { + const { method, url } = ctx.request - return next() - }); + const message = `(API) ${method} - ${url}` + const chalkedMessage = `(${chalk.bold.white('API')}) ${chalk.bold.green(method)} - ${chalk.bold.blue(url)}` + + logger.console('info', chalkedMessage) + logger.file('info', message) + + } else { + delete ctx.query.logIgnore + } + + return next() } \ No newline at end of file