Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Feat/dependency #9

Merged
merged 6 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/api/controllers/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class HealthController extends BaseController {
lastStartup: await this.db.getRepo(Data).get('lastStartup'),
}

console.debug(body)

this.ok(ctx, body)
}

Expand All @@ -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')
Expand Down
4 changes: 3 additions & 1 deletion src/api/middlewares/botOnline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
9 changes: 4 additions & 5 deletions src/api/middlewares/log.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { container } from "tsyringe"
import chalk from "chalk"
import { Context, Next } from "koa"
import { container } from "tsyringe"

import { Logger } from "@services"

const logger = container.resolve(Logger)

export function globalLog(ctx: Context, next: Next) {
export async function globalLog(ctx: Context, next: Next) {

// don't log anything if the request has a `logIgnore` query params
if (!ctx.query.logIgnore) {

const { method, url } = ctx.request

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 {
} else {
delete ctx.query.logIgnore
}

Expand Down
6 changes: 3 additions & 3 deletions src/commands/General/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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({
Expand Down
4 changes: 2 additions & 2 deletions src/events/custom/guildAdmin.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/events/interactionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 5 additions & 5 deletions src/events/ready.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand Down Expand Up @@ -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()`)
Expand Down
17 changes: 10 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -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
Expand All @@ -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}")
Expand All @@ -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()
}
}

Expand Down
67 changes: 35 additions & 32 deletions src/services/Logger.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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(", "))
Expand All @@ -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 =======
Expand Down Expand Up @@ -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)
}
})
}

// =================================
Expand Down Expand Up @@ -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')
})
}

// =================================
Expand Down
4 changes: 2 additions & 2 deletions src/services/Stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => ({
Expand Down
8 changes: 5 additions & 3 deletions src/utils/classes/BaseError.ts
Original file line number Diff line number Diff line change
@@ -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() {}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/decorators/On.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions src/utils/decorators/Schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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<any>), args)
}

const job = new CronJob(
cronExpression,
descriptor.value,
Expand All @@ -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)
})
}
Expand Down
14 changes: 7 additions & 7 deletions src/utils/decorators/Slash.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -8,12 +8,12 @@ enum AdditionnalLocaleString {
type LocalizationMap = Partial<Record<`${Locale | AdditionnalLocaleString}`, string>>

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
}

/**
Expand Down
Loading