diff --git a/Database b/Database index 60d6b79c3..b25457cba 160000 --- a/Database +++ b/Database @@ -1 +1 @@ -Subproject commit 60d6b79c33eab7901039618ecb730c48a89f4b26 +Subproject commit b25457cbac0973e1821d9f34f4eff84ade64d662 diff --git a/docker-compose.yml b/docker-compose.yml index d4df89cee..e7f79a8c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.8" include: - - path: ./Lavalink/docker-compose.yml - env_file: .env + # - path: ./Lavalink/docker-compose.yml + # env_file: .env - path: ./Database/docker-compose.yml env_file: .env diff --git a/package.json b/package.json index cfadee7a8..c34ec3a2a 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@nestjs/config": "^3.2.0", "@nestjs/core": "^10.3.3", "@nestjs/event-emitter": "^2.0.4", + "@nestjs/platform-express": "^10.3.8", "@prisma/client": "5.11.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", @@ -76,5 +77,8 @@ "typescript": "^5.4.2", "vite-tsconfig-paths": "^4.3.2", "vitest": "^1.4.0" + }, + "prisma": { + "schema": "Database/prisma/schema.prisma" } } diff --git a/src/app.module.ts b/src/app.module.ts index f67d7f177..6d3acaebc 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,12 +1,13 @@ import { Module } from "@nestjs/common"; import { ConfigModule } from "@nestjs/config"; +import { config } from "./modules/config"; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, cache: true, - load: [], + load: [config], }), ], }) diff --git a/src/common/guards/CommandConfig.guard.ts b/src/common/guards/CommandConfig.guard.ts index b973d6b14..21f0696dd 100644 --- a/src/common/guards/CommandConfig.guard.ts +++ b/src/common/guards/CommandConfig.guard.ts @@ -1,14 +1,6 @@ -import { - LOCALIZATION_ADAPTER, - type NestedLocalizationAdapter, -} from "@necord/localization"; -import { - Inject, - Injectable, - type CanActivate, - type ExecutionContext, -} from "@nestjs/common"; -import type { Reflector } from "@nestjs/core"; +import { LOCALIZATION_ADAPTER, type NestedLocalizationAdapter } from "@necord/localization"; +import { type CanActivate, type ExecutionContext, Inject, Injectable } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; import type { ChatInputCommandInteraction } from "discord.js"; import { NecordExecutionContext } from "necord"; import { CommandConfig } from "../decorators"; @@ -20,24 +12,14 @@ export class CommandConfigGuard implements CanActivate { private readonly reflector: Reflector, ) {} - public async canActivate( - executionContext: ExecutionContext, - ): Promise { - const commandConfig = this.reflector.get( - CommandConfig.KEY, - executionContext.getHandler(), - ); + public async canActivate(executionContext: ExecutionContext): Promise { + const commandConfig = this.reflector.get(CommandConfig.KEY, executionContext.getHandler()); const context = NecordExecutionContext.create(executionContext); const args = context.getArgByIndex(0); const interaction = args[0] as ChatInputCommandInteraction; if (commandConfig.disable) { - interaction.reply( - this.translate.getTranslation( - "Tools.Command.Checker.Disable", - interaction.guildLocale, - ), - ); + interaction.reply(this.translate.getTranslation("Tools.Command.Checker.Disable", interaction.guildLocale)); return false; } diff --git a/src/common/guards/CommandPermissions.guard.ts b/src/common/guards/CommandPermissions.guard.ts index da9304ecf..476d24c54 100644 --- a/src/common/guards/CommandPermissions.guard.ts +++ b/src/common/guards/CommandPermissions.guard.ts @@ -1,10 +1,10 @@ import { CommandPermissions } from "@/common/decorators"; -import type { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; import { formatArray } from "@/utils/Tools"; -import { LOCALIZATION_ADAPTER, type NestedLocalizationAdapter } from "@necord/localization"; +import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; import { type CanActivate, type ExecutionContext, Inject, Injectable } from "@nestjs/common"; -import type { ConfigService } from "@nestjs/config"; -import type { Reflector } from "@nestjs/core"; +import { ConfigService } from "@nestjs/config"; +import { Reflector } from "@nestjs/core"; import type { ChatInputCommandInteraction } from "discord.js"; import { NecordExecutionContext } from "necord"; diff --git a/src/lib/sharding.ts b/src/lib/sharding.ts index 1b4df6ace..d0f9c3e6a 100644 --- a/src/lib/sharding.ts +++ b/src/lib/sharding.ts @@ -1,8 +1,7 @@ -import path from "node:path"; import { Logger } from "@nestjs/common"; import type { ConfigService } from "@nestjs/config"; import { ShardingManager as _ShardingManager } from "discord.js"; -import type { Config } from "../modules/shared/config/types"; +import path from "node:path"; export class ShardingManager extends _ShardingManager { public constructor(private readonly config: ConfigService) { diff --git a/src/main.ts b/src/main.ts index 85e87088b..e14ff0516 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,12 +1,12 @@ import { Logger } from "@nestjs/common"; -import { ShardingManager, TopGGAutoPoster } from "./lib"; -import {NestFactory } from "@nestjs/core"; -import { AppModule } from "./app.module"; import { ConfigService } from "@nestjs/config"; +import { NestFactory } from "@nestjs/core"; +import { AppModule } from "./app.module"; +import { ShardingManager, TopGGAutoPoster } from "./lib"; async function bootstrap() { - const app = await NestFactory.create(AppModule); - const configService = app.get(ConfigService); + const app = await NestFactory.create(AppModule); + const configService = app.get(ConfigService); const logger = new Logger("Main"); const ShardManager = new ShardingManager(configService); const TopGGPoster = new TopGGAutoPoster(configService.getOrThrow("TopGGToken"), ShardManager); @@ -15,6 +15,7 @@ async function bootstrap() { await ShardManager.init(); await TopGGPoster.init(); } catch (error) { + await app.listen(configService.get("PORT")); logger.error("An error occurred when starting: ", (error as Error).message); } } diff --git "a/src/modules/commands/\360\237\233\240\357\270\217 Developer Tools/commands/eval/eval.command.ts" "b/src/modules/commands/\360\237\233\240\357\270\217 Developer Tools/commands/eval/eval.command.ts" index 02f8ab66a..fcb6113eb 100644 --- "a/src/modules/commands/\360\237\233\240\357\270\217 Developer Tools/commands/eval/eval.command.ts" +++ "b/src/modules/commands/\360\237\233\240\357\270\217 Developer Tools/commands/eval/eval.command.ts" @@ -1,14 +1,14 @@ import { inspect } from "node:util"; import { CommandConfig, CommandPermissions } from "@/common/decorators"; import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; -import { Config } from "@/modules/shared/config/types"; -import { CurrentTranslate, TranslationFn, localizationMapByKey } from "@necord/localization"; +import type { Config } from "@/modules/config/types"; +import { CurrentTranslate, type TranslationFn, localizationMapByKey } from "@necord/localization"; import { UseGuards } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { EmbedBuilder, codeBlock } from "discord.js"; -import { Ctx, Options, SlashCommandContext, Subcommand } from "necord"; +import { Ctx, Options, type SlashCommandContext, Subcommand } from "necord"; import { DeveloperToolsCommand } from "../../DeveloperTools.decorator"; -import { EvalDTO } from "./eval.dto"; +import type { EvalDTO } from "./eval.dto"; @DeveloperToolsCommand() export class EvalCommand { diff --git a/src/modules/config/Config.ts b/src/modules/config/Config.ts new file mode 100644 index 000000000..9568691d6 --- /dev/null +++ b/src/modules/config/Config.ts @@ -0,0 +1,112 @@ +import { Config, ENVIRONMENT } from "./types"; + +export const config = (): Config => ({ + ENVIRONMENT: process.env.ENVIRONMENT as ENVIRONMENT, + Database: { + Version: "Music", + URL: process.env.DATABASE_URL, + Name: process.env.DatabaseName, + Password: process.env.DatabasePassword, + Redis: { + Port: process.env.RedisPort, + Host: process.env.RedisHost, + }, + }, + API: { + JwtSecret: process.env.JWT_SECRET, + JwtExpire: "1d", + CookieSecret: process.env.COOKIE_SECRET, + MaxAge: 86400, // 1 day in seconds + }, + TopGGToken: process.env.TopGGToken, + FallbackLocale: "pt-BR", + Discord: { + Token: process.env.Token, + DevToken: process.env.DevToken, + Client: { + Owners: ["330047048009252864"], + Secret: process.env.ClientSecret, + ID: "708822043420000366", + CallbackURL: process.env.CallbackURL, + }, + Servers: { + NDCommunity: "679066351456878633", + TestGuild: "717094267243462688", + }, + }, + Debug: { + Client: true, + Translations: false, + Lavalink: false, + PremiumMusicPlayer: false, + }, + Music: { + Lavalink: true, + Volumes: { + Lavalink: 0.75, + Player: 50, + }, + Player: { + AutoLeaveEmpty: { + Channel: { + Enable: true, + Delay: 60000, + }, + Queue: { + Enable: true, + Delay: 30000, + }, + }, + }, + Client: { + selfDeaf: true, + serverDeaf: true, + }, + }, + Emojis: { + logo: "<:NDB:763741625079300117>", + fail: "<:NotixDeny:719560576015138830>", + accept: "<:NotixAllow:719560623960096789>", + success: "<:NotixAllow:719560623960096789>", + thing: "", + loading: "", + loading2: "", + delayping: "<:DelayPing:718196166399098901>", + Music: { + Youtube: "<:youtube:730741995416453150>", + Spotify: "<:Spotify:775154334832001044>", + SoundCloud: "<:soundcloud:932065538014842950>", + Deezer: "<:deezer:932065971336802334>", + Facebook: "<:facebook:932066080996864070>", + Apple: "<:Apple:852677662983716884>", + Twitch: "<:twitch:998725252098052197>", + }, + }, + URLList: { + Music: { + Youtube: "https://www.youtube.com", + ShortYoutube: "https://youtu.be", + SoundCloud: "https://soundcloud.com", + Spotify: "https://open.spotify.com", + Deezer: "https://www.deezer", + Facebook: "https://facebook.com", + Apple: "https://music.apple.com/", + Twitch: "https://www.twitch.tv/", + }, + }, + EvalBadKeys: [ + "client.token", + "client.destroy", + "process.env.Token", + "process.env.DevToken", + "process.env.DATABASE_URL", + "process.env.DatabaseName", + "process.env.DatabasePassword", + "process.env.RedisPort", + "process.env.RedisHost", + "process.env.LavalinkHOST", + "process.env.LavalinkPassword", + "process.env.SpotifyClientId", + "process.env.SpotifyClientSecret", + ], +}); diff --git a/src/modules/config/JSONLocale.loader.ts b/src/modules/config/JSONLocale.loader.ts new file mode 100644 index 000000000..485e539d8 --- /dev/null +++ b/src/modules/config/JSONLocale.loader.ts @@ -0,0 +1,35 @@ +import fs from "node:fs"; +import path from "node:path"; + +export class JSONLocaleLoader { + public constructor(private readonly path: string) {} + + public async loadTranslations() { + const locales: Record> = {}; + const folders = fs.readdirSync(this.path); + + for (const langFolder of folders) { + const langPath = path.join(this.path, langFolder); + const namespaces = fs.readdirSync(langPath); + const langData = {}; + + for (const namespace of namespaces) { + const namespacePath = path.join(langPath, namespace); + const files = fs.readdirSync(namespacePath); + const namespaceData = {}; + + for (const file of files) { + const filePath = path.join(namespacePath, file); + const jsonContent = fs.readFileSync(filePath, "utf-8"); + const jsonData = JSON.parse(jsonContent); + namespaceData[file.replace(".json", "")] = jsonData; + } + + langData[namespace] = namespaceData; + } + + locales[langFolder] = langData; + } + return locales; + } +} diff --git a/src/modules/config/NecordConfig.service.ts b/src/modules/config/NecordConfig.service.ts new file mode 100644 index 000000000..54fbe2648 --- /dev/null +++ b/src/modules/config/NecordConfig.service.ts @@ -0,0 +1,60 @@ +import { Injectable } from "@nestjs/common"; +import type { ConfigService } from "@nestjs/config"; +import { GatewayIntentBits, GatewayVersion, Options, Partials } from "discord.js"; +import type { NecordModuleOptions } from "necord"; +import { Config } from "./types"; + +@Injectable() +export class NecordConfigService { + public constructor(private readonly config: ConfigService) {} + + createNecordOptions(): NecordModuleOptions { + return { + token: this.config.getOrThrow("Discord").Token, + skipRegistration: false, + shards: "auto", + rest: { + version: GatewayVersion, + offset: 0, + api: "https://discord.com/api/", + cdn: "https://cdn.discordapp.com", + }, + failIfNotExists: true, + allowedMentions: { + parse: ["roles", "users"], + repliedUser: false, + }, + makeCache: Options.cacheEverything(), + partials: [ + Partials.Channel, + Partials.GuildMember, + Partials.GuildScheduledEvent, + Partials.Message, + Partials.Reaction, + Partials.ThreadMember, + Partials.User, + ], + intents: [ + GatewayIntentBits.DirectMessageReactions, + GatewayIntentBits.DirectMessageTyping, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildModeration, + GatewayIntentBits.GuildEmojisAndStickers, + GatewayIntentBits.GuildIntegrations, + GatewayIntentBits.GuildInvites, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildMessageTyping, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.GuildPresences, + GatewayIntentBits.GuildScheduledEvents, + GatewayIntentBits.GuildVoiceStates, + GatewayIntentBits.GuildWebhooks, + GatewayIntentBits.Guilds, + GatewayIntentBits.MessageContent, + GatewayIntentBits.AutoModerationConfiguration, + GatewayIntentBits.AutoModerationExecution, + ], + } as never; + } +} diff --git a/src/modules/config/index.ts b/src/modules/config/index.ts new file mode 100644 index 000000000..f47a10cd2 --- /dev/null +++ b/src/modules/config/index.ts @@ -0,0 +1,3 @@ +export * from "./Config"; +export * from "./JSONLocale.loader"; +export * from "./NecordConfig.service"; diff --git a/src/modules/config/types/index.d.ts b/src/modules/config/types/index.d.ts new file mode 100644 index 000000000..656cb7447 --- /dev/null +++ b/src/modules/config/types/index.d.ts @@ -0,0 +1,98 @@ +export type ENVIRONMENT = "DEVELOPMENT" | "PRODUCTION"; + +export interface Config { + ENVIRONMENT: ENVIRONMENT; + Database: { + Version: string; + URL: string; + Name: string; + Password: string; + Redis: { + Port: string; + Host: string; + }; + }; + API: { + JwtSecret: string; + JwtExpire: string; + CookieSecret: string; + MaxAge: number; + }; + TopGGToken: string; + FallbackLocale: string; + Discord: { + Token: string; + DevToken: string; + Client: { + Owners: string[]; + Secret: string; + ID: string; + CallbackURL: string; + }; + Servers: { + NDCommunity: string; + TestGuild: string; + }; + }; + Debug: { + Client: boolean; + Translations: boolean; + Lavalink: boolean; + PremiumMusicPlayer: boolean; + }; + Music: { + Lavalink: boolean; + Volumes: { + Lavalink: number; + Player: number; + }; + Player: { + AutoLeaveEmpty: { + Channel: { + Enable: boolean; + Delay: number; + }; + Queue: { + Enable: boolean; + Delay: number; + }; + }; + }; + Client: { + selfDeaf: boolean; + serverDeaf: boolean; + }; + }; + Emojis: { + logo: string; + fail: string; + accept: string; + success: string; + thing: string; + loading: string; + loading2: string; + delayping: string; + Music: { + Youtube: string; + Spotify: string; + SoundCloud: string; + Deezer: string; + Facebook: string; + Apple: string; + Twitch: string; + }; + }; + URLList: { + Music: { + Youtube: string; + ShortYoutube: string; + SoundCloud: string; + Spotify: string; + Deezer: string; + Facebook: string; + Apple: string; + Twitch: string; + }; + }; + EvalBadKeys: string[]; +} diff --git a/src/modules/core/NDB.module.ts b/src/modules/core/NDB.module.ts index 758f7b640..6a5a2e595 100644 --- a/src/modules/core/NDB.module.ts +++ b/src/modules/core/NDB.module.ts @@ -1,14 +1,15 @@ import { GuildResolver, NecordLocalizationModule, NestedLocalizationAdapter } from "@necord/localization"; import { NecordPaginationModule } from "@necord/pagination"; import { Module } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; +import { ConfigModule, ConfigService } from "@nestjs/config"; import { NecordModule } from "necord"; import { CommandsModule } from "../commands/Commands.module"; import { ComponentsModule } from "../components/Components.module"; +import { JSONLocaleLoader, NecordConfigService, config } from "../config"; +import type { Config } from "../config/types"; +import { DatabaseModule } from "../database/database.module"; import { EventsModule } from "../events/Events.module"; import { ReactionRolesModule } from "../reactionRoles/ReactionRoles.module"; -import { JSONLocaleLoader, NecordConfigService, SharedModule } from "../shared"; -import { Config } from "../shared/config/types"; import { NDBServiceProvider } from "./provider/NDBService.provider"; @Module({ @@ -33,8 +34,13 @@ import { NDBServiceProvider } from "./provider/NDBService.provider"; resolvers: GuildResolver, }), }), + ConfigModule.forRoot({ + isGlobal: true, + cache: true, + load: [config], + }), + DatabaseModule, CommandsModule, - SharedModule, ComponentsModule, EventsModule, ReactionRolesModule, diff --git a/src/modules/core/NDB.service.ts b/src/modules/core/NDB.service.ts index 6b260b45d..2de1b1962 100644 --- a/src/modules/core/NDB.service.ts +++ b/src/modules/core/NDB.service.ts @@ -1,19 +1,8 @@ import type { Content } from "@/types"; -import { - LOCALIZATION_ADAPTER, - type NestedLocalizationAdapter, -} from "@necord/localization"; -import { - PageBuilder, - type ButtonsAppearance, - type NecordPaginationService, -} from "@necord/pagination"; +import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; +import { type ButtonsAppearance, NecordPaginationService, PageBuilder } from "@necord/pagination"; import { Inject, Injectable } from "@nestjs/common"; -import { - ButtonStyle, - type CommandInteraction, - type EmbedBuilder, -} from "discord.js"; +import { ButtonStyle, type CommandInteraction, type EmbedBuilder } from "discord.js"; import type { INDBService } from "./interfaces/INDBService"; @Injectable() @@ -23,26 +12,16 @@ export class NDBService implements INDBService { private readonly paginator: NecordPaginationService, ) {} - public async buildPaginator( - interaction: CommandInteraction, - embeds: EmbedBuilder[], - id: string, - ): Promise { + public async buildPaginator(interaction: CommandInteraction, embeds: EmbedBuilder[], id: string): Promise { const buttons: ButtonsAppearance = { back: { emoji: "⬅️", - label: this.translate.getTranslation( - "Tools.Paginator.Labels.Previous", - interaction.guildLocale, - ), + label: this.translate.getTranslation("Tools.Paginator.Labels.Previous", interaction.guildLocale), style: ButtonStyle.Secondary, }, next: { emoji: "➡️", - label: this.translate.getTranslation( - "Tools.Paginator.Labels.Next", - interaction.guildLocale, - ), + label: this.translate.getTranslation("Tools.Paginator.Labels.Next", interaction.guildLocale), style: ButtonStyle.Secondary, }, }; @@ -57,15 +36,11 @@ export class NDBService implements INDBService { Current: String(i + 1), Total: String(embeds.length), }, - )}` - : this.translate.getTranslation( - "Tools.Paginator.Embed.Footer", - interaction.guildLocale, - { - Current: String(i + 1), - Total: String(embeds.length), - }, - ), + )}` + : this.translate.getTranslation("Tools.Paginator.Embed.Footer", interaction.guildLocale, { + Current: String(i + 1), + Total: String(embeds.length), + }), }); } @@ -75,9 +50,7 @@ export class NDBService implements INDBService { } return this.paginator - .register((builder) => - builder.setCustomId(id).setPages(pages).setMaxPages(embeds.length), - ) + .register((builder) => builder.setCustomId(id).setPages(pages).setMaxPages(embeds.length)) .setButtonsAppearance(buttons) .build(); } diff --git a/src/modules/database/als/als.module.ts b/src/modules/database/als/als.module.ts new file mode 100644 index 000000000..82f7e9f94 --- /dev/null +++ b/src/modules/database/als/als.module.ts @@ -0,0 +1,17 @@ +import { AsyncLocalStorage } from "node:async_hooks"; +import { Global, Module, Provider } from "@nestjs/common"; +import { Repositories } from "../types/constants"; +import { AlsService } from "./als.service"; +import { AlsStore } from "./types"; + +export const AlsProvider: Provider> = { + provide: Repositories.ALS, + useValue: new AsyncLocalStorage(), +}; + +@Global() +@Module({ + providers: [AlsService, AlsProvider], + exports: [AlsProvider], +}) +export class AlsModule {} diff --git a/src/modules/database/als/als.service.ts b/src/modules/database/als/als.service.ts new file mode 100644 index 000000000..352e93e37 --- /dev/null +++ b/src/modules/database/als/als.service.ts @@ -0,0 +1,15 @@ +import { AsyncLocalStorage } from "node:async_hooks"; +import { Inject, Injectable, OnModuleInit } from "@nestjs/common"; +import { Repositories } from "../types/constants"; +import { AlsStore } from "./types"; + +@Injectable() +export class AlsService implements OnModuleInit { + public constructor(@Inject(Repositories.ALS) private readonly als: AsyncLocalStorage) {} + + public async onModuleInit() { + this.als.enterWith({ + PrismaConnected: false, + }); + } +} diff --git a/src/modules/database/als/interfaces/IAsyncLocalStorage.ts b/src/modules/database/als/interfaces/IAsyncLocalStorage.ts new file mode 100644 index 000000000..b858dbb0d --- /dev/null +++ b/src/modules/database/als/interfaces/IAsyncLocalStorage.ts @@ -0,0 +1,4 @@ +import type { AsyncLocalStorage } from "node:async_hooks"; +import type { AlsStore } from "../types"; + +export interface IAsyncLocalStorage extends AsyncLocalStorage {} diff --git a/src/modules/database/als/types/index.ts b/src/modules/database/als/types/index.ts new file mode 100644 index 000000000..349eecbbc --- /dev/null +++ b/src/modules/database/als/types/index.ts @@ -0,0 +1,3 @@ +export interface AlsStore { + PrismaConnected: boolean; +} diff --git a/src/modules/database/database.module.ts b/src/modules/database/database.module.ts new file mode 100644 index 000000000..d1578e258 --- /dev/null +++ b/src/modules/database/database.module.ts @@ -0,0 +1,19 @@ +import { Services } from "@/types/Constants"; +import { Global, Module, Provider } from "@nestjs/common"; +import { AlsModule } from "./als/als.module"; +import { DatabaseService } from "./database.service"; +import { PrismaModule } from "./prisma/Prisma.module"; +import { RepositoriesModule } from "./repositories/Repositories.module"; + +const provider: Provider = { + provide: Services.Database, + useClass: DatabaseService, +}; + +@Global() +@Module({ + imports: [AlsModule, RepositoriesModule, PrismaModule], + providers: [provider], + exports: [provider], +}) +export class DatabaseModule {} diff --git a/src/modules/database/database.service.ts b/src/modules/database/database.service.ts new file mode 100644 index 000000000..9bf727ff9 --- /dev/null +++ b/src/modules/database/database.service.ts @@ -0,0 +1,33 @@ +import type { IReactionRolesRepository } from "@/modules/reactionRoles/interfaces/IReactionRoleRepository"; +import { ReactionRoles } from "@/modules/reactionRoles/types/constants"; +import { Inject, Injectable } from "@nestjs/common"; +import type { IAsyncLocalStorage } from "./als/interfaces/IAsyncLocalStorage"; +import type { IDatabaseService } from "./interfaces/IDatabaseService"; +import type { IGuildRepository, IUserRepository } from "./repositories/interfaces"; +import { Repositories } from "./types/constants"; + +@Injectable() +export class DatabaseService implements IDatabaseService { + public constructor( + @Inject(Repositories.ALS) private readonly als: IAsyncLocalStorage, + @Inject(Repositories.Guild) private readonly guild: IGuildRepository, + @Inject(Repositories.User) private readonly user: IUserRepository, + @Inject(ReactionRoles.Repository) private readonly reactionRoles: IReactionRolesRepository, + ) {} + + public AlsRepo(): IAsyncLocalStorage { + return this.als; + } + + public GuildRepo(): IGuildRepository { + return this.guild; + } + + public UserRepo(): IUserRepository { + return this.user; + } + + public ReactionRolesRepo(): IReactionRolesRepository { + return this.reactionRoles; + } +} diff --git a/src/modules/database/entities/Guild.entity.ts b/src/modules/database/entities/Guild.entity.ts new file mode 100644 index 000000000..7d222fdfb --- /dev/null +++ b/src/modules/database/entities/Guild.entity.ts @@ -0,0 +1,5 @@ +import type { Guild, GuildSettings } from "@prisma/client"; + +export type GuildEntity = Guild & { + Settings: GuildSettings; +}; diff --git a/src/modules/database/entities/User.entity.ts b/src/modules/database/entities/User.entity.ts new file mode 100644 index 000000000..ffe4ca9d1 --- /dev/null +++ b/src/modules/database/entities/User.entity.ts @@ -0,0 +1,6 @@ +import type { APIUser, User, UserSettings } from "@prisma/client"; + +export type UserEntity = User & { + Settings: UserSettings; + APIUser?: APIUser; +}; diff --git a/src/modules/database/entities/index.ts b/src/modules/database/entities/index.ts new file mode 100644 index 000000000..b055950cf --- /dev/null +++ b/src/modules/database/entities/index.ts @@ -0,0 +1,2 @@ +export * from "./Guild.entity" +export * from "./User.entity" diff --git a/src/modules/database/interfaces/IDatabaseService.ts b/src/modules/database/interfaces/IDatabaseService.ts new file mode 100644 index 000000000..64981dd9a --- /dev/null +++ b/src/modules/database/interfaces/IDatabaseService.ts @@ -0,0 +1,11 @@ +import type { IReactionRolesRepository } from "@/modules/reactionRoles/interfaces"; +import type { IAsyncLocalStorage } from "../als/interfaces/IAsyncLocalStorage"; +import type { IGuildRepository } from "../repositories/interfaces/IGuildRepository"; +import type { IUserRepository } from "../repositories/interfaces/IUserRepository"; + +export interface IDatabaseService { + AlsRepo(): IAsyncLocalStorage; + GuildRepo(): IGuildRepository; + UserRepo(): IUserRepository; + ReactionRolesRepo(): IReactionRolesRepository; +} diff --git a/src/modules/database/prisma/Prisma.module.ts b/src/modules/database/prisma/Prisma.module.ts new file mode 100644 index 000000000..f4947d74a --- /dev/null +++ b/src/modules/database/prisma/Prisma.module.ts @@ -0,0 +1,15 @@ +import { Services } from "@/types/Constants"; +import { Global, Module, Provider } from "@nestjs/common"; +import { PrismaService } from "./Prisma.service"; + +const provider: Provider = { + provide: Services.Prisma, + useClass: PrismaService, +}; + +@Global() +@Module({ + providers: [provider], + exports: [provider], +}) +export class PrismaModule {} diff --git a/src/modules/database/prisma/Prisma.service.ts b/src/modules/database/prisma/Prisma.service.ts new file mode 100644 index 000000000..64b380e3b --- /dev/null +++ b/src/modules/database/prisma/Prisma.service.ts @@ -0,0 +1,29 @@ +import { AsyncLocalStorage } from "node:async_hooks"; +import { Inject, Injectable, Logger, OnApplicationShutdown, OnModuleInit } from "@nestjs/common"; +import { PrismaClient } from "@prisma/client"; +import { AlsStore } from "../als/types"; +import { Repositories } from "../types/constants"; + +@Injectable() +export class PrismaService extends PrismaClient implements OnModuleInit, OnApplicationShutdown { + public constructor(@Inject(Repositories.ALS) private readonly als: AsyncLocalStorage) { + super(); + } + + private readonly logger = new Logger(PrismaService.name); + + public async onModuleInit() { + const state = this.als.getStore()["PrismaConnected"]; + if (!state) { + await this.$connect(); + this.logger.log("PostgreSQL connected via Prisma"); + this.als.getStore()["PrismaConnected"] = true; + } + } + + public async onApplicationShutdown(signal?: string) { + await this.$disconnect(); + this.logger.log(`PostgreSQL disconnected from Prisma reason: ${signal}`); + this.als.getStore()["PrismaConnected"] = false; + } +} diff --git a/src/modules/database/repositories/Guild.repository.ts b/src/modules/database/repositories/Guild.repository.ts new file mode 100644 index 000000000..a7ac39ed2 --- /dev/null +++ b/src/modules/database/repositories/Guild.repository.ts @@ -0,0 +1,80 @@ +import { Services } from "@/types/Constants"; +import { Inject, Injectable, Logger } from "@nestjs/common"; +import { Guild } from "discord.js"; +import { GuildEntity } from "../entities"; +import { PrismaService } from "../prisma/Prisma.service"; +import { DatabaseStatus } from "../types"; +import type { IGuildRepository } from "./interfaces"; + +@Injectable() +export class GuildRepository implements IGuildRepository { + public constructor(@Inject(Services.Prisma) private readonly prisma: PrismaService) {} + + private readonly logger = new Logger(GuildRepository.name); + + public async get(guildId: string): Promise { + return await this.prisma.guild.findUnique({ + where: { id: guildId }, + include: { + Settings: true, + }, + }); + } + + public async create(guild: Guild): Promise<{ callback: void | GuildEntity; status: DatabaseStatus }> { + let status = DatabaseStatus.Created; + const callback = await this.prisma.guild + .create({ + data: { + id: guild.id, + Name: guild.name, + Settings: { + create: {}, + }, + }, + include: { + Settings: true, + }, + }) + .catch((err) => { + this.logger.error(err); + status = DatabaseStatus.Error; + }); + this.logger.log(`${guild.name} Configuration Created on Database`); + return { + callback, + status, + }; + } + + public async update(oldGuild: Guild, newGuild: Guild): Promise { + return await this.prisma.guild.update({ + where: { id: oldGuild.id }, + data: { + Name: newGuild.name, + updatedAt: new Date(), + }, + include: { + Settings: true, + }, + }); + } + + public async delete(guild: Guild): Promise { + return await this.prisma.guild.delete({ + where: { id: guild.id }, + include: { + Settings: true, + }, + }); + } + + public async getCreated(guild: Guild): Promise { + await this.create(guild).then(({ status }) => { + if (status === DatabaseStatus.Created) { + this.logger.log(`${guild.name} Configuration Crated on Database`); + } + }); + return await this.get(guild.id); + } +} diff --git a/src/modules/database/repositories/Repositories.module.ts b/src/modules/database/repositories/Repositories.module.ts new file mode 100644 index 000000000..11cc8341c --- /dev/null +++ b/src/modules/database/repositories/Repositories.module.ts @@ -0,0 +1,25 @@ +import { ReactionRolesRepoProvider } from "@/modules/reactionRoles/types/providers"; +import { Global, Module, type Provider } from "@nestjs/common"; +import { Repositories } from "../types/constants"; +import { GuildRepository } from "./Guild.repository"; +import { UserRepository } from "./User.repository"; + +const providers: Provider< + GuildRepository | UserRepository +>[] = [ + { + provide: Repositories.Guild, + useClass: GuildRepository, + }, + { + provide: Repositories.User, + useClass: UserRepository, + }, +]; + +@Global() +@Module({ + providers: [...providers, ReactionRolesRepoProvider], + exports: [...providers, ReactionRolesRepoProvider], +}) +export class RepositoriesModule {} diff --git a/src/modules/database/repositories/User.repository.ts b/src/modules/database/repositories/User.repository.ts new file mode 100644 index 000000000..528a5a94d --- /dev/null +++ b/src/modules/database/repositories/User.repository.ts @@ -0,0 +1,75 @@ +import { Services } from "@/types/Constants"; +import { Inject, Logger } from "@nestjs/common"; +import { User } from "discord.js"; +import { UserEntity } from "../entities"; +import { PrismaService } from "../prisma/Prisma.service"; +import { DatabaseStatus } from "../types"; +import type { IUserRepository } from "./interfaces"; + +export class UserRepository implements IUserRepository { + public constructor(@Inject(Services.Prisma) private readonly prisma: PrismaService) {} + + private readonly logger = new Logger(UserRepository.name); + + public async get(userId: string): Promise { + return await this.prisma.user.findUnique({ + where: { id: userId }, + include: { + Settings: true, + APIUser: true, + }, + }); + } + + public async create(user: User): Promise<{ callback: UserEntity | void; status: DatabaseStatus }> { + let status = DatabaseStatus.Created; + const callback = await this.prisma.user + .create({ + data: { + id: user.id, + Settings: { + create: {}, + }, + APIUser: { + create: { + accessToken: "", + email: "", + }, + }, + }, + include: { + Settings: true, + }, + }) + .catch((err) => { + this.logger.error(err); + status = DatabaseStatus.Error; + }); + this.logger.log(`${user.username} Configuration Created on Database`); + return { + callback, + status, + }; + } + + public async update(user: User): Promise { + return await this.prisma.user.update({ + where: { id: user.id }, + data: {}, + include: { + Settings: true, + APIUser: true, + }, + }); + } + + public async delete(user: User): Promise { + return await this.prisma.user.delete({ + where: { id: user.id }, + include: { + Settings: true, + APIUser: true, + }, + }); + } +} diff --git a/src/modules/database/repositories/interfaces/IGuildRepository.ts b/src/modules/database/repositories/interfaces/IGuildRepository.ts new file mode 100644 index 000000000..eaa7732fa --- /dev/null +++ b/src/modules/database/repositories/interfaces/IGuildRepository.ts @@ -0,0 +1,10 @@ +import type { Guild } from "discord.js" +import type { GuildEntity } from "../../entities"; +import type { DatabaseStatus } from "../../types"; + +export interface IGuildRepository { + get(guildId: string): Promise; + create(guild: Guild): Promise<{ callback: GuildEntity | void; status: DatabaseStatus }>; + update(oldGuild: Guild, newGuild: Guild): Promise; + delete(guild: Guild): Promise; +} diff --git a/src/modules/database/repositories/interfaces/IUserRepository.ts b/src/modules/database/repositories/interfaces/IUserRepository.ts new file mode 100644 index 000000000..5d3dfad22 --- /dev/null +++ b/src/modules/database/repositories/interfaces/IUserRepository.ts @@ -0,0 +1,10 @@ +import type { User } from "discord.js"; +import type { UserEntity } from "../../entities"; +import type { DatabaseStatus } from "../../types"; + +export interface IUserRepository { + get(userId: string): Promise; + create(user: User): Promise<{ callback: UserEntity | void; status: DatabaseStatus }>; + update(user: User): Promise; + delete(user: User): Promise; +} diff --git a/src/modules/database/repositories/interfaces/index.ts b/src/modules/database/repositories/interfaces/index.ts new file mode 100644 index 000000000..18be53b87 --- /dev/null +++ b/src/modules/database/repositories/interfaces/index.ts @@ -0,0 +1,2 @@ +export * from "./IGuildRepository"; +export * from "./IUserRepository"; diff --git a/src/modules/database/types/constants.ts b/src/modules/database/types/constants.ts new file mode 100644 index 000000000..d51369fc1 --- /dev/null +++ b/src/modules/database/types/constants.ts @@ -0,0 +1,5 @@ +export enum Repositories { + Guild = "GUILD_REPOSITORY", + User = "USER_REPOSITORY", + ALS = "ALS_REPOSITORY", +} diff --git a/src/modules/database/types/index.ts b/src/modules/database/types/index.ts new file mode 100644 index 000000000..f71d20eb7 --- /dev/null +++ b/src/modules/database/types/index.ts @@ -0,0 +1,4 @@ +export enum DatabaseStatus { + Created = 0, + Error = 1, +} diff --git a/src/modules/events/Events.module.ts b/src/modules/events/Events.module.ts index 992ead303..5d6ace135 100644 --- a/src/modules/events/Events.module.ts +++ b/src/modules/events/Events.module.ts @@ -1,6 +1,6 @@ import { Module, type OnApplicationBootstrap } from "@nestjs/common"; -import { EventEmitterModule, type EventEmitter2 } from "@nestjs/event-emitter"; -import type { REST } from "discord.js"; +import { EventEmitter2, EventEmitterModule } from "@nestjs/event-emitter"; +import { REST } from "discord.js"; import { GatewayEvents } from "./Gateway"; import { GuildEvents } from "./Guild"; import { ThreadEvents } from "./Thread"; @@ -10,6 +10,7 @@ import { ThreadEvents } from "./Thread"; EventEmitterModule.forRoot({ delimiter: ".", maxListeners: 10, + global: true, }), ], providers: [GatewayEvents, GuildEvents, ThreadEvents], diff --git a/src/modules/events/Gateway.ts b/src/modules/events/Gateway.ts index 48619fc8f..72f9ddd63 100644 --- a/src/modules/events/Gateway.ts +++ b/src/modules/events/Gateway.ts @@ -1,12 +1,19 @@ -import { Config } from "@/modules/shared/config/types"; -import { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { Config } from "@/modules/config/types"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { Inject, Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { OnEvent } from "@nestjs/event-emitter"; import { RESTJSONErrorCodes } from "discord-api-types/v10"; -import { ActivityType, Client, DiscordAPIError, PresenceData, REST, RateLimitData } from "discord.js"; -import { Context, ContextOf, On, Once } from "necord"; +import { + ActivityType, + type Client, + DiscordAPIError, + type PresenceData, + type REST, + type RateLimitData, +} from "discord.js"; +import { Context, type ContextOf, On, Once } from "necord"; @Injectable() export class GatewayEvents { diff --git a/src/modules/events/Guild.ts b/src/modules/events/Guild.ts index 6f4b7b13b..2a9d2db7e 100644 --- a/src/modules/events/Guild.ts +++ b/src/modules/events/Guild.ts @@ -1,8 +1,8 @@ -import type { IDatabaseService } from "@/modules/shared"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { Inject, Injectable } from "@nestjs/common"; import { Client } from "discord.js"; -import { Context, ContextOf, On } from "necord"; +import { Context, type ContextOf, On } from "necord"; @Injectable() export class GuildEvents { diff --git a/src/modules/music/Music.embeds.ts b/src/modules/music/Music.embeds.ts index 1dc3bdce1..0dd805d82 100644 --- a/src/modules/music/Music.embeds.ts +++ b/src/modules/music/Music.embeds.ts @@ -1,21 +1,27 @@ -import { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; import { Timer } from "@/utils/Tools"; -import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; +import { + LOCALIZATION_ADAPTER, + type NestedLocalizationAdapter, +} from "@necord/localization"; import { Inject, Injectable } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; +import type { ConfigService } from "@nestjs/config"; import { - Client, - ColorResolvable, - CommandInteraction, - EmbedBuilder, - Guild, - TextChannel, - User, - VoiceChannel, - channelMention, - codeBlock, + EmbedBuilder, + channelMention, + type Client, + type ColorResolvable, + type CommandInteraction, + type Guild, + type TextChannel, + type User, + type VoiceChannel } from "discord.js"; -import { Player, SearchResult, Track, TrackExceptionEvent } from "lavalink-client"; +import { + type Player, + type SearchResult, + type Track +} from "lavalink-client"; import type { IMusicEmbeds } from "./interfaces"; @Injectable() @@ -26,7 +32,10 @@ export class MusicEmbeds implements IMusicEmbeds { private readonly client: Client, ) {} - private async createBaseEmbed(interaction: CommandInteraction, color: "Error" | "Success"): Promise { + private async createBaseEmbed( + interaction: CommandInteraction, + color: "Error" | "Success", + ): Promise { const hex = color === "Error" ? "#c20e00" : "#00c26f"; return new EmbedBuilder() @@ -38,27 +47,56 @@ export class MusicEmbeds implements IMusicEmbeds { .setColor(hex as ColorResolvable); } - public async NoPlayer(interaction: CommandInteraction): Promise { + public async NoPlayer( + interaction: CommandInteraction, + ): Promise { const baseEmbed = await this.createBaseEmbed(interaction, "Error"); return baseEmbed - .setTitle(this.translate.getTranslation("Tools.Music.NoPlayerEmbed.Title", interaction.guildLocale)) + .setTitle( + this.translate.getTranslation( + "Tools.Music.NoPlayerEmbed.Title", + interaction.guildLocale, + ), + ) .addFields([ { - name: this.translate.getTranslation("Tools.Music.NoPlayerEmbed.Fields.1", interaction.guildLocale), - value: this.translate.getTranslation("Tools.Music.NoPlayerEmbed.Fields.Content.1", interaction.guildLocale, { - GuildName: interaction.guild.name, - }), + name: this.translate.getTranslation( + "Tools.Music.NoPlayerEmbed.Fields.1", + interaction.guildLocale, + ), + value: this.translate.getTranslation( + "Tools.Music.NoPlayerEmbed.Fields.Content.1", + interaction.guildLocale, + { + GuildName: interaction.guild.name, + }, + ), }, ]); } - public async NoChannel(interaction: CommandInteraction): Promise { + public async NoChannel( + interaction: CommandInteraction, + ): Promise { const baseEmbed = await this.createBaseEmbed(interaction, "Error"); return baseEmbed - .setTitle(this.translate.getTranslation("Tools.Music.NoChannelEmbed.Title", interaction.guildLocale)) - .setDescription(this.translate.getTranslation("Tools.Music.NoChannelEmbed.Description", interaction.guildLocale)) + .setTitle( + this.translate.getTranslation( + "Tools.Music.NoChannelEmbed.Title", + interaction.guildLocale, + ), + ) + .setDescription( + this.translate.getTranslation( + "Tools.Music.NoChannelEmbed.Description", + interaction.guildLocale, + ), + ) .setFooter({ - text: this.translate.getTranslation("Tools.Music.NoChannelEmbed.Footer", interaction.guildLocale), + text: this.translate.getTranslation( + "Tools.Music.NoChannelEmbed.Footer", + interaction.guildLocale, + ), iconURL: this.client.user.displayAvatarURL(), }); } @@ -77,7 +115,10 @@ export class MusicEmbeds implements IMusicEmbeds { case "Fail": baseEmbed .setTitle( - this.translate.getTranslation("Tools.Music.loadType.LOAD_FAILED.Embed.Title", interaction.guildLocale), + this.translate.getTranslation( + "Tools.Music.loadType.LOAD_FAILED.Embed.Title", + interaction.guildLocale, + ), ) .setDescription( this.translate.getTranslation( @@ -97,10 +138,16 @@ export class MusicEmbeds implements IMusicEmbeds { case "NoMatches": baseEmbed .setTitle( - this.translate.getTranslation("Tools.Music.loadType.NO_MATCHES.Embed.Title", interaction.guildLocale), + this.translate.getTranslation( + "Tools.Music.loadType.NO_MATCHES.Embed.Title", + interaction.guildLocale, + ), ) .setDescription( - this.translate.getTranslation("Tools.Music.loadType.NO_MATCHES.Embed.Description", interaction.guildLocale), + this.translate.getTranslation( + "Tools.Music.loadType.NO_MATCHES.Embed.Description", + interaction.guildLocale, + ), ) .setFooter({ text: this.translate.getTranslation( @@ -114,7 +161,12 @@ export class MusicEmbeds implements IMusicEmbeds { case "Success": baseEmbed .setColor("#00c26f") - .setTitle(this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Title", interaction.guildLocale)) + .setTitle( + this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Title", + interaction.guildLocale, + ), + ) .addFields([ { name: this.translate.getTranslation( @@ -158,7 +210,12 @@ export class MusicEmbeds implements IMusicEmbeds { "Tools.Music.loadType.SUCCESS.Embed.Fields.Content.3", interaction.guildLocale, { - TIMER: await Timer(this.translate, "normal", track.info.duration, interaction.guildLocale), + TIMER: await Timer( + this.translate, + "normal", + track.info.duration, + interaction.guildLocale, + ), }, ), inline: true, @@ -166,7 +223,10 @@ export class MusicEmbeds implements IMusicEmbeds { ]) .setThumbnail(track.info.artworkUrl) .setFooter({ - text: this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Footer", interaction.guildLocale), + text: this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Footer", + interaction.guildLocale, + ), iconURL: this.client.user.displayAvatarURL(), }); @@ -187,17 +247,25 @@ export class MusicEmbeds implements IMusicEmbeds { const baseEmbed = await this.createBaseEmbed(interaction, "Success"); return baseEmbed .setTitle( - this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.PlaylistTitle", interaction.guildLocale, { - Quantity: String(res.tracks.length), - }), + this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.PlaylistTitle", + interaction.guildLocale, + { + Quantity: String(res.tracks.length), + }, + ), ) .setThumbnail(res.playlist.thumbnail) .addFields([ { - name: this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Fields.1", interaction.guildLocale, { - EMOJI: Checker.Emoji, - NAME: Checker.Name, - }), + name: this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Fields.1", + interaction.guildLocale, + { + EMOJI: Checker.Emoji, + NAME: Checker.Name, + }, + ), value: this.translate.getTranslation( "Tools.Music.loadType.SUCCESS.Embed.Fields.Content.1", interaction.guildLocale, @@ -209,7 +277,10 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Fields.2", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Fields.2", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.loadType.SUCCESS.Embed.Fields.Content.2", interaction.guildLocale, @@ -220,52 +291,87 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Fields.3", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Fields.3", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.loadType.SUCCESS.Embed.Fields.Content.3", interaction.guildLocale, { - TIMER: await Timer(this.translate, "normal", res.playlist.duration, interaction.guildLocale), + TIMER: await Timer( + this.translate, + "normal", + res.playlist.duration, + interaction.guildLocale, + ), }, ), inline: true, }, ]) .setFooter({ - text: this.translate.getTranslation("Tools.Music.loadType.SUCCESS.Embed.Footer", interaction.guildLocale), + text: this.translate.getTranslation( + "Tools.Music.loadType.SUCCESS.Embed.Footer", + interaction.guildLocale, + ), iconURL: this.client.user.displayAvatarURL(), }); } - public async NowPlaying(interaction: CommandInteraction, player: Player, progressBar: string): Promise { + public async NowPlaying( + interaction: CommandInteraction, + player: Player, + progressBar: string, + ): Promise { const baseEmbed = await this.createBaseEmbed(interaction, "Success"); const music = player.queue.current; let IsLoop: string; switch (player.repeatMode) { case "off": - IsLoop = this.translate.getTranslation("Tools.Music.NowPlayingEmbed.NoLoop", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").fail, - }); + IsLoop = this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.NoLoop", + interaction.guildLocale, + { + Emoji: this.config.getOrThrow("Emojis").fail, + }, + ); break; case "queue": - IsLoop = this.translate.getTranslation("Tools.Music.NowPlayingEmbed.QueueLoop", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").success, - }); + IsLoop = this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.QueueLoop", + interaction.guildLocale, + { + Emoji: this.config.getOrThrow("Emojis").success, + }, + ); break; case "track": - IsLoop = this.translate.getTranslation("Tools.Music.NowPlayingEmbed.MusicLoop", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").success, - }); + IsLoop = this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.MusicLoop", + interaction.guildLocale, + { + Emoji: this.config.getOrThrow("Emojis").success, + }, + ); break; } return baseEmbed .setThumbnail(music.info.artworkUrl) - .setTitle(this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Title", interaction.guildLocale)) + .setTitle( + this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Title", + interaction.guildLocale, + ), + ) .setDescription(`[${music.info.title}](${music.info.uri})`) .setFields([ { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields:1", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields:1", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.1", interaction.guildLocale, @@ -276,41 +382,72 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields.2", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields.2", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.2", interaction.guildLocale, { IsPlaying: player.paused - ? this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Paused", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").fail, - }) - : this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Playing", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").success, - }), + ? this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Paused", + interaction.guildLocale, + { + Emoji: + this.config.getOrThrow("Emojis").fail, + }, + ) + : this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Playing", + interaction.guildLocale, + { + Emoji: + this.config.getOrThrow("Emojis") + .success, + }, + ), }, ), inline: true, }, { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields.3", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields.3", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.3", interaction.guildLocale, { IsBassBoosted: player.filterManager.equalizerBands - ? this.translate.getTranslation("Tools.Music.NowPlayingEmbed.ActiveBass", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").success, - }) - : this.translate.getTranslation("Tools/Music:NowPlayingEmbed:NoBass", interaction.guildLocale, { - Emoji: this.config.getOrThrow("Emojis").fail, - }), + ? this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.ActiveBass", + interaction.guildLocale, + { + Emoji: + this.config.getOrThrow("Emojis") + .success, + }, + ) + : this.translate.getTranslation( + "Tools/Music:NowPlayingEmbed:NoBass", + interaction.guildLocale, + { + Emoji: + this.config.getOrThrow("Emojis").fail, + }, + ), }, ), inline: true, }, { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields.4", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields.4", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.4", interaction.guildLocale, @@ -321,7 +458,10 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields.5", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields.5", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.5", interaction.guildLocale, @@ -332,7 +472,10 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Tools.Music.NowPlayingEmbed.Fields.6", interaction.guildLocale), + name: this.translate.getTranslation( + "Tools.Music.NowPlayingEmbed.Fields.6", + interaction.guildLocale, + ), value: this.translate.getTranslation( "Tools.Music.NowPlayingEmbed.Fields.Content.6", interaction.guildLocale, @@ -361,10 +504,18 @@ export class MusicEmbeds implements IMusicEmbeds { iconURL: guild.iconURL(), }) .setColor("#00c26f") - .setTitle(this.translate.getTranslation("Events.PlayerEvents.playerCreate.Embed.Title", guild.preferredLocale)) + .setTitle( + this.translate.getTranslation( + "Events.PlayerEvents.playerCreate.Embed.Title", + guild.preferredLocale, + ), + ) .setFields([ { - name: this.translate.getTranslation("Events.PlayerEvents.playerCreate.Embed.Fields.1", guild.preferredLocale), + name: this.translate.getTranslation( + "Events.PlayerEvents.playerCreate.Embed.Fields.1", + guild.preferredLocale, + ), value: this.translate.getTranslation( "Events.PlayerEvents.playerCreate.Embed.Fields.Content.1", guild.preferredLocale, @@ -375,7 +526,10 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Events.PlayerEvents.playerCreate.Embed.Fields.2", guild.preferredLocale), + name: this.translate.getTranslation( + "Events.PlayerEvents.playerCreate.Embed.Fields.2", + guild.preferredLocale, + ), value: this.translate.getTranslation( "Events.PlayerEvents.playerCreate.Embed.Fields.Content.2", guild.preferredLocale, @@ -388,7 +542,10 @@ export class MusicEmbeds implements IMusicEmbeds { inline: true, }, { - name: this.translate.getTranslation("Events.PlayerEvents.playerCreate.Embed.Fields.3", guild.preferredLocale), + name: this.translate.getTranslation( + "Events.PlayerEvents.playerCreate.Embed.Fields.3", + guild.preferredLocale, + ), value: this.translate.getTranslation( "Events.PlayerEvents.playerCreate.Embed.Fields.Content.3", guild.preferredLocale, @@ -399,13 +556,19 @@ export class MusicEmbeds implements IMusicEmbeds { }, ]) .setFooter({ - text: this.translate.getTranslation("Events.PlayerEvents.playerCreate.Embed.Footer", guild.preferredLocale), + text: this.translate.getTranslation( + "Events.PlayerEvents.playerCreate.Embed.Footer", + guild.preferredLocale, + ), iconURL: this.client.user.displayAvatarURL(), }) .setTimestamp(); } - public async PlayerMove(textChannel: TextChannel, voiceChannel: VoiceChannel): Promise { + public async PlayerMove( + textChannel: TextChannel, + voiceChannel: VoiceChannel, + ): Promise { return new EmbedBuilder() .setAuthor({ name: this.client.user.tag, @@ -453,9 +616,13 @@ export class MusicEmbeds implements IMusicEmbeds { iconURL: this.client.user.displayAvatarURL(), }) .setTitle( - this.translate.getTranslation("Events.PlayerEvents.trackStart.Embed.Title", textChannel.guild.preferredLocale, { - TITLE: track.info.title, - }), + this.translate.getTranslation( + "Events.PlayerEvents.trackStart.Embed.Title", + textChannel.guild.preferredLocale, + { + TITLE: track.info.title, + }, + ), ) .setThumbnail(track.info.artworkUrl) .addFields([ @@ -527,7 +694,11 @@ export class MusicEmbeds implements IMusicEmbeds { .setTimestamp(); } - public async TrackError(textChannel: TextChannel, track: Track, payload: string): Promise { + public async TrackError( + textChannel: TextChannel, + track: Track, + payload: string, + ): Promise { return new EmbedBuilder() .setAuthor({ name: this.client.user.tag, @@ -535,7 +706,10 @@ export class MusicEmbeds implements IMusicEmbeds { }) .setColor("#00c26f") .setTitle( - this.translate.getTranslation("Events.PlayerEvents.trackError.Embed.Title", textChannel.guild.preferredLocale), + this.translate.getTranslation( + "Events.PlayerEvents.trackError.Embed.Title", + textChannel.guild.preferredLocale, + ), ) .setDescription( this.translate.getTranslation( @@ -572,7 +746,10 @@ export class MusicEmbeds implements IMusicEmbeds { .setTimestamp(); } - public async TrackStuck(textChannel: TextChannel, track: Track): Promise { + public async TrackStuck( + textChannel: TextChannel, + track: Track, + ): Promise { return new EmbedBuilder() .setAuthor({ name: this.client.user.tag, @@ -580,9 +757,13 @@ export class MusicEmbeds implements IMusicEmbeds { }) .setColor("#00c26f") .setTitle( - this.translate.getTranslation("Events.PlayerEvents.trackStuck.Embed.Title", textChannel.guild.preferredLocale, { - EMOJI: this.config.getOrThrow("Emojis").fail, - }), + this.translate.getTranslation( + "Events.PlayerEvents.trackStuck.Embed.Title", + textChannel.guild.preferredLocale, + { + EMOJI: this.config.getOrThrow("Emojis").fail, + }, + ), ) .setDescription( this.translate.getTranslation( diff --git a/src/modules/music/Music.service.ts b/src/modules/music/Music.service.ts index 9436f15a3..9ab34d7c0 100644 --- a/src/modules/music/Music.service.ts +++ b/src/modules/music/Music.service.ts @@ -1,15 +1,23 @@ -import { Config } from "@/modules/shared/config/types"; -import { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { Config } from "@/modules/config/types"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; -import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; +import { + LOCALIZATION_ADAPTER, + type NestedLocalizationAdapter, +} from "@necord/localization"; import { Inject, Injectable } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; -import { CommandInteraction, GuildMember, VoiceChannel, channelMention } from "discord.js"; -import { Player, PlayerOptions, SourceNames } from "lavalink-client"; +import type { ConfigService } from "@nestjs/config"; +import { + channelMention, + type CommandInteraction, + type GuildMember, + type VoiceChannel, +} from "discord.js"; +import type { Player, PlayerOptions, SourceNames } from "lavalink-client"; import moment from "moment"; import ms from "parse-ms"; -import { MusicEmbeds } from "./Music.embeds"; -import { MusicManager } from "./Music.manager"; +import type { MusicEmbeds } from "./Music.embeds"; +import type { MusicManager } from "./Music.manager"; import type { IMusicService } from "./interfaces"; import { Music } from "./types/constants"; @@ -31,7 +39,10 @@ export class MusicService implements IMusicService { return this.MusicManager.common.getPlayer(interaction.guildId); } - public async getPlayerEvent(guildId: string, isPremium: boolean): Promise { + public async getPlayerEvent( + guildId: string, + isPremium: boolean, + ): Promise { if (isPremium) { return this.MusicManager.premium.getPlayer(guildId); } @@ -48,7 +59,8 @@ export class MusicService implements IMusicService { guildId: voiceChannel.guildId, textChannelId: textChannelId, voiceChannelId: voiceChannel.id, - selfDeaf: this.config.getOrThrow("Music").Client.selfDeaf, + selfDeaf: + this.config.getOrThrow("Music").Client.selfDeaf, instaUpdateFiltersFix: false, volume: this.config.getOrThrow("Music").Volumes.Player, // vcRegion: voiceChannel.rtcRegion! @@ -78,14 +90,23 @@ export class MusicService implements IMusicService { public async sameVoice(interaction: CommandInteraction): Promise { const player = await this.getPlayer(interaction); - const voiceChannel = await interaction.guild.channels.fetch(player.voiceChannelId); + const voiceChannel = await interaction.guild.channels.fetch( + player.voiceChannelId, + ); - if ((interaction.member as GuildMember).voice.channelId !== player.voiceChannelId) { + if ( + (interaction.member as GuildMember).voice.channelId !== + player.voiceChannelId + ) { await interaction.reply( - this.translate.getTranslation("Tools.Music.WrongChannel", interaction.guildLocale, { - TextChannel: channelMention(player.textChannelId), - VoiceChannel: channelMention(voiceChannel.id), - }), + this.translate.getTranslation( + "Tools.Music.WrongChannel", + interaction.guildLocale, + { + TextChannel: channelMention(player.textChannelId), + VoiceChannel: channelMention(voiceChannel.id), + }, + ), ); return false; } @@ -95,7 +116,9 @@ export class MusicService implements IMusicService { public async hasPlayer(interaction: CommandInteraction): Promise { const player = await this.getPlayer(interaction); if (!player) { - await interaction.reply({ embeds: [await this.embeds.NoPlayer(interaction)] }); + await interaction.reply({ + embeds: [await this.embeds.NoPlayer(interaction)], + }); return false; } return true; @@ -125,7 +148,8 @@ export class MusicService implements IMusicService { Name: string; }> { const URLs = this.config.getOrThrow("URLList").Music; - const MusicEmojis = this.config.getOrThrow("Emojis").Music; + const MusicEmojis = + this.config.getOrThrow("Emojis").Music; let Emoji: string; let Name: string; @@ -146,7 +170,11 @@ export class MusicService implements IMusicService { for (const value of Props) { if (isCommand) { - if (((query as CommandInteraction).options.get("query").value as string).includes(value.URL)) { + if ( + ( + (query as CommandInteraction).options.get("query").value as string + ).includes(value.URL) + ) { Emoji = value.Emoji; Name = value.Name; break; @@ -167,15 +195,56 @@ export class MusicService implements IMusicService { public async progressBar(player: Player): Promise { const time = ms(player.queue.current.info.duration); const done = ms(player.position); - const D1 = `[${done.hours ? (done.hours > 10 ? done.hours : `0${done.hours}`) : ""}${ - done.minutes ? (done.minutes >= 10 ? done.minutes : `0${done.minutes}`) : "00" - }:${done.seconds ? (done.seconds > 10 ? done.seconds : `0${done.seconds}`) : ""}] `; - const D2 = ` [${time.hours ? (time.hours > 10 ? time.hours : `0${time.hours}`) : ""}${time.hours ? ":" : ""}${ - time.minutes ? (time.minutes >= 10 ? time.minutes : `0${time.minutes}`) : "00" - }:${time.seconds ? (time.seconds > 10 ? time.seconds : `0${time.seconds}`) : ""}]`; + const D1 = `[${ + done.hours ? (done.hours > 10 ? done.hours : `0${done.hours}`) : "" + }${ + done.minutes + ? done.minutes >= 10 + ? done.minutes + : `0${done.minutes}` + : "00" + }:${ + done.seconds + ? done.seconds > 10 + ? done.seconds + : `0${done.seconds}` + : "" + }] `; + const D2 = ` [${ + time.hours ? (time.hours > 10 ? time.hours : `0${time.hours}`) : "" + }${time.hours ? ":" : ""}${ + time.minutes + ? time.minutes >= 10 + ? time.minutes + : `0${time.minutes}` + : "00" + }:${ + time.seconds + ? time.seconds > 10 + ? time.seconds + : `0${time.seconds}` + : "" + }]`; const D3 = moment.duration({ ms: player.position }).asMilliseconds(); - const progressBar = ["▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬", "▬"]; - const calcul = Math.round(progressBar.length * (D3 / player.queue.current.info.duration)); + const progressBar = [ + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + "▬", + ]; + const calcul = Math.round( + progressBar.length * (D3 / player.queue.current.info.duration), + ); progressBar[calcul] = "🔘"; return D1 + progressBar.join("") + D2; } diff --git a/src/modules/music/classes/BaseManager.ts b/src/modules/music/classes/BaseManager.ts index 5b749780e..7d6c29f86 100644 --- a/src/modules/music/classes/BaseManager.ts +++ b/src/modules/music/classes/BaseManager.ts @@ -1,10 +1,13 @@ -import { LavalinkManagerEvents, NodeManagerEvents } from "@/modules/music/types/lavalink-client"; -import { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; +import type { + LavalinkManagerEvents, + NodeManagerEvents, +} from "@/modules/music/types/lavalink-client"; import { Logger } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; -import { EventEmitter2 } from "@nestjs/event-emitter"; -import { Client } from "discord.js"; -import { LavalinkManager, ManagerQueueOptions } from "lavalink-client"; +import type { ConfigService } from "@nestjs/config"; +import type { EventEmitter2 } from "@nestjs/event-emitter"; +import type { Client } from "discord.js"; +import { LavalinkManager, type ManagerQueueOptions } from "lavalink-client"; export class BaseManager extends LavalinkManager { public constructor( @@ -35,7 +38,8 @@ export class BaseManager extends LavalinkManager { applyVolumeAsFilter: false, clientBasedPositionUpdateInterval: 100, defaultSearchPlatform: "ytmsearch", - volumeDecrementer: config.getOrThrow("Music").Volumes.Lavalink, + volumeDecrementer: + config.getOrThrow("Music").Volumes.Lavalink, useUnresolvedData: true, onDisconnect: { autoReconnect: false, @@ -49,7 +53,10 @@ export class BaseManager extends LavalinkManager { return logger.error("sendToShard - guild not found: ", id); } if (!guild.shard) { - return logger.error("sendToShard - guild has no shard not found: ", guild); + return logger.error( + "sendToShard - guild has no shard not found: ", + guild, + ); } return guild.shard.send(payload); }, @@ -62,17 +69,29 @@ export class BaseManager extends LavalinkManager { this.nodeManager.setMaxListeners(8); const LavalinkManagerEvents: Partial = { - trackStart: (player, track, payload) => this.eventEmitter.emit("track.start", player, track, payload), - trackEnd: (player, track, payload) => this.eventEmitter.emit("track.end", player, track, payload), - trackStuck: (player, track, payload) => this.eventEmitter.emit("track.stuck", player, track, payload), - trackError: (player, track, payload) => this.eventEmitter.emit("track.error", player, track, payload), - queueEnd: (player, track, payload) => this.eventEmitter.emit("queue.end", player, track, payload), + trackStart: (player, track, payload) => + this.eventEmitter.emit("track.start", player, track, payload), + trackEnd: (player, track, payload) => + this.eventEmitter.emit("track.end", player, track, payload), + trackStuck: (player, track, payload) => + this.eventEmitter.emit("track.stuck", player, track, payload), + trackError: (player, track, payload) => + this.eventEmitter.emit("track.error", player, track, payload), + queueEnd: (player, track, payload) => + this.eventEmitter.emit("queue.end", player, track, payload), playerCreate: (player) => this.eventEmitter.emit("player.create", player), playerMove: (player, oldVoiceChannelId, newVoiceChannelId) => - this.eventEmitter.emit("player.move", player, oldVoiceChannelId, newVoiceChannelId), - playerDisconnect: (player, voiceChannelId) => this.eventEmitter.emit("player.disconnect", player, voiceChannelId), + this.eventEmitter.emit( + "player.move", + player, + oldVoiceChannelId, + newVoiceChannelId, + ), + playerDisconnect: (player, voiceChannelId) => + this.eventEmitter.emit("player.disconnect", player, voiceChannelId), // playerSocketClosed: (player, payload) => this.eventEmitter.emit("player.socketClosed", player, payload), - playerDestroy: (player, destroyReason) => this.eventEmitter.emit("player.destroy", player, destroyReason), + playerDestroy: (player, destroyReason) => + this.eventEmitter.emit("player.destroy", player, destroyReason), // playerUpdate: (oldPlayerJson, newPlayer) => this.eventEmitter.emit("player.update", oldPlayerJson, newPlayer), // SegmentsLoaded: (player, track, payload) => this.eventEmitter.emit("segments.loaded", player, track, payload), // SegmentSkipped: (player, track, payload) => this.eventEmitter.emit("segments.skipped", player, track, payload), @@ -80,25 +99,61 @@ export class BaseManager extends LavalinkManager { // ChaptersLoaded: (player, track, payload) => this.eventEmitter.emit("chapter.loaded", player, track, payload), }; const NodeManagerEvents: Partial = { - create: (node) => this.eventEmitter.emit("node.create", node, clientOptions.username), + create: (node) => + this.eventEmitter.emit("node.create", node, clientOptions.username), destroy: (node, destroyReason) => - this.eventEmitter.emit("node.destroy", node, destroyReason, clientOptions.username), - connect: (node) => this.eventEmitter.emit("node.connect", node, clientOptions.username), - reconnecting: (node) => this.eventEmitter.emit("node.reconnecting", node, clientOptions.username), - disconnect: (node, reason) => this.eventEmitter.emit("node.disconnect", node, reason, clientOptions.username), + this.eventEmitter.emit( + "node.destroy", + node, + destroyReason, + clientOptions.username, + ), + connect: (node) => + this.eventEmitter.emit("node.connect", node, clientOptions.username), + reconnecting: (node) => + this.eventEmitter.emit( + "node.reconnecting", + node, + clientOptions.username, + ), + disconnect: (node, reason) => + this.eventEmitter.emit( + "node.disconnect", + node, + reason, + clientOptions.username, + ), error: (node, error, payload) => - this.eventEmitter.emit("node.error", node, error, payload, clientOptions.username), - raw: (node, payload) => this.eventEmitter.emit("node.raw", node, payload, clientOptions.username), + this.eventEmitter.emit( + "node.error", + node, + error, + payload, + clientOptions.username, + ), + raw: (node, payload) => + this.eventEmitter.emit( + "node.raw", + node, + payload, + clientOptions.username, + ), // resumed: (node, payload, players) => // this.eventEmitter.emit("node.resumed", node, payload, players, clientOptions.username), }; for (const event in LavalinkManagerEvents) { - this.on(event as keyof LavalinkManagerEvents, LavalinkManagerEvents[event]); + this.on( + event as keyof LavalinkManagerEvents, + LavalinkManagerEvents[event], + ); } for (const event in NodeManagerEvents) { - this.nodeManager.on(event as keyof NodeManagerEvents, NodeManagerEvents[event]); + this.nodeManager.on( + event as keyof NodeManagerEvents, + NodeManagerEvents[event], + ); } client.on("raw", (data) => { diff --git a/src/modules/music/events/Channel.ts b/src/modules/music/events/Channel.ts index 6765acd51..e8be0d2c1 100644 --- a/src/modules/music/events/Channel.ts +++ b/src/modules/music/events/Channel.ts @@ -1,9 +1,9 @@ -import type { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { LOCALIZATION_ADAPTER, type NestedLocalizationAdapter } from "@necord/localization"; import { Inject, Injectable, Logger } from "@nestjs/common"; import { ChannelType, type Client, type TextChannel } from "discord.js"; -import { Context, type ContextOf, On } from "necord"; +import { Context, On, type ContextOf } from "necord"; import { Music } from ".."; import { MessageTools } from "../../commands/Message"; import type { IMusicService } from "../interfaces"; diff --git a/src/modules/music/events/Guild.ts b/src/modules/music/events/Guild.ts index 2f23aa9a9..8fd99f05c 100644 --- a/src/modules/music/events/Guild.ts +++ b/src/modules/music/events/Guild.ts @@ -1,8 +1,8 @@ -import type { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { Inject, Injectable } from "@nestjs/common"; -import { Client } from "discord.js"; -import { Context, ContextOf, On } from "necord"; +import type { Client } from "discord.js"; +import { Context, On, type ContextOf } from "necord"; import type { IMusicService } from "../interfaces"; import { Music } from "../types/constants"; diff --git a/src/modules/music/events/Node.ts b/src/modules/music/events/Node.ts index c0ce72939..40774cb79 100644 --- a/src/modules/music/events/Node.ts +++ b/src/modules/music/events/Node.ts @@ -1,8 +1,8 @@ -import { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; import { Injectable, Logger } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; +import type { ConfigService } from "@nestjs/config"; import { OnEvent } from "@nestjs/event-emitter"; -import { LavalinkNode } from "lavalink-client"; +import type { LavalinkNode } from "lavalink-client"; @Injectable() export class NodeEvents { @@ -11,23 +11,42 @@ export class NodeEvents { private readonly logger = new Logger(NodeEvents.name); @OnEvent("node.create") - public async onNodeCreate(node: LavalinkNode, username: string): Promise { + public async onNodeCreate( + node: LavalinkNode, + username: string, + ): Promise { this.logger.log(`${username} | Lavalink Node: ${node.options.id} criado!`); } @OnEvent("node.destroy") - public async onNodeDestroy(node: LavalinkNode, destroyReason: string, username: string): Promise { - this.logger.fatal(`${username} | Lavalink Node: ${node.options.id} destruído pelo motivo: ${destroyReason}`); + public async onNodeDestroy( + node: LavalinkNode, + destroyReason: string, + username: string, + ): Promise { + this.logger.fatal( + `${username} | Lavalink Node: ${node.options.id} destruído pelo motivo: ${destroyReason}`, + ); } @OnEvent("node.connect") - public async onNodeConnect(node: LavalinkNode, username: string): Promise { - this.logger.log(`${username} | Lavalink Node: ${node.options.id} Conectado!`); + public async onNodeConnect( + node: LavalinkNode, + username: string, + ): Promise { + this.logger.log( + `${username} | Lavalink Node: ${node.options.id} Conectado!`, + ); } @OnEvent("node.reconnecting") - public async onNodeReconnecting(node: LavalinkNode, username: string): Promise { - this.logger.warn(`${username} | Lavalink Node: ${node.options.id} Reconectando...`); + public async onNodeReconnecting( + node: LavalinkNode, + username: string, + ): Promise { + this.logger.warn( + `${username} | Lavalink Node: ${node.options.id} Reconectando...`, + ); } @OnEvent("node.disconnect") @@ -42,14 +61,29 @@ export class NodeEvents { } @OnEvent("node.error") - public async onNodeError(node: LavalinkNode, error: Error, payload: unknown, username: string): Promise { - this.logger.error(`${username} | Lavalink Node: ${node.options.id} Error: ${error.message}`); + public async onNodeError( + node: LavalinkNode, + error: Error, + payload: unknown, + username: string, + ): Promise { + this.logger.error( + `${username} | Lavalink Node: ${node.options.id} Error: ${error.message}`, + ); } @OnEvent("node.raw") - public async onNodeRaw(node: LavalinkNode, payload: unknown, username: string): Promise { + public async onNodeRaw( + node: LavalinkNode, + payload: unknown, + username: string, + ): Promise { if (this.config.getOrThrow("Debug").Lavalink) { - this.logger.debug(`${username} | Lavalink Node: ${node.options.id} Raw: \n${JSON.stringify(payload, null, 2)}`); + this.logger.debug( + `${username} | Lavalink Node: ${ + node.options.id + } Raw: \n${JSON.stringify(payload, null, 2)}`, + ); } } } diff --git a/src/modules/music/events/Player.ts b/src/modules/music/events/Player.ts index 690a62f89..bbb44f7b3 100644 --- a/src/modules/music/events/Player.ts +++ b/src/modules/music/events/Player.ts @@ -1,4 +1,4 @@ -import type { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; import { Inject, Injectable, Logger } from "@nestjs/common"; import type { ConfigService } from "@nestjs/config"; import { OnEvent } from "@nestjs/event-emitter"; diff --git a/src/modules/music/events/Queue.ts b/src/modules/music/events/Queue.ts index 31a4bb67f..f452e3732 100644 --- a/src/modules/music/events/Queue.ts +++ b/src/modules/music/events/Queue.ts @@ -1,11 +1,24 @@ -import { Config } from "@/modules/shared/config/types"; -import { Extends } from "@/types/Constants"; -import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; +import type { Config } from "@/modules/config/types"; +import { + LOCALIZATION_ADAPTER, + type NestedLocalizationAdapter, +} from "@necord/localization"; import { Inject, Injectable, Logger } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; +import type { ConfigService } from "@nestjs/config"; import { OnEvent } from "@nestjs/event-emitter"; -import { Client, EmbedBuilder, TextChannel, VoiceChannel } from "discord.js"; -import { Player, Track, TrackEndEvent, TrackExceptionEvent, TrackStuckEvent } from "lavalink-client"; +import { + EmbedBuilder, + type Client, + type TextChannel, + type VoiceChannel, +} from "discord.js"; +import type { + Player, + Track, + TrackEndEvent, + TrackExceptionEvent, + TrackStuckEvent, +} from "lavalink-client"; import ms from "parse-ms"; import { MessageTools } from "../../commands/Message"; @@ -25,13 +38,23 @@ export class QueueEvents { track: Track, payload: TrackEndEvent | TrackStuckEvent | TrackExceptionEvent, ) { - const textChannel = this.client.channels.cache.get(player.textChannelId) as TextChannel; - const voiceChannel = this.client.channels.cache.get(player.voiceChannelId) as VoiceChannel; - if (this.config.getOrThrow("Music").Player.AutoLeaveEmpty.Queue.Enable) { + const textChannel = this.client.channels.cache.get( + player.textChannelId, + ) as TextChannel; + const voiceChannel = this.client.channels.cache.get( + player.voiceChannelId, + ) as VoiceChannel; + if ( + this.config.getOrThrow("Music").Player.AutoLeaveEmpty + .Queue.Enable + ) { setTimeout(async () => { try { if (!player.queue && player.queue.current) { - const Timer = ms(this.config.getOrThrow("Music").Player.AutoLeaveEmpty.Queue.Delay); + const Timer = ms( + this.config.getOrThrow("Music").Player + .AutoLeaveEmpty.Queue.Delay, + ); const embed = new EmbedBuilder() .setAuthor({ name: this.client.user.tag, @@ -82,7 +105,9 @@ export class QueueEvents { } catch (error) { this.logger.error("Queue End Error: ", String(error)); } - }, this.config.getOrThrow("Music").Player.AutoLeaveEmpty.Queue.Delay); + }, this.config.getOrThrow( + "Music", + ).Player.AutoLeaveEmpty.Queue.Delay); } } } diff --git a/src/modules/music/events/Voice.ts b/src/modules/music/events/Voice.ts index b4e70fcf1..2bbfcb5dd 100644 --- a/src/modules/music/events/Voice.ts +++ b/src/modules/music/events/Voice.ts @@ -1,11 +1,20 @@ -import { Config } from "@/modules/shared/config/types"; -import type { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { Config } from "@/modules/config/types"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; -import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; +import { + LOCALIZATION_ADAPTER, + type NestedLocalizationAdapter, +} from "@necord/localization"; import { Inject, Logger } from "@nestjs/common"; -import { ConfigService } from "@nestjs/config"; -import { ChannelType, Client, EmbedBuilder, TextChannel, VoiceChannel } from "discord.js"; -import { Context, ContextOf, On } from "necord"; +import type { ConfigService } from "@nestjs/config"; +import { + ChannelType, + EmbedBuilder, + type Client, + type TextChannel, + type VoiceChannel, +} from "discord.js"; +import { Context, On, type ContextOf } from "necord"; import { Music } from ".."; import type { IMusicService } from "../interfaces"; diff --git a/src/modules/reactionRoles/ReactionRoles.decorator.ts b/src/modules/reactionRoles/ReactionRoles.decorator.ts index 3115e51af..e9962b938 100644 --- a/src/modules/reactionRoles/ReactionRoles.decorator.ts +++ b/src/modules/reactionRoles/ReactionRoles.decorator.ts @@ -7,4 +7,5 @@ export const ReactionRolesCommand = createCommandGroupDecorator({ nameLocalizations: localizationMapByKey("ReactionRoles.category.name"), descriptionLocalizations: localizationMapByKey("ReactionRoles.category.description"), dmPermission: false, + guilds: ["717094267243462688"] }); diff --git a/src/modules/reactionRoles/ReactionRoles.embeds.ts b/src/modules/reactionRoles/ReactionRoles.embeds.ts index af820aa05..acf82d441 100644 --- a/src/modules/reactionRoles/ReactionRoles.embeds.ts +++ b/src/modules/reactionRoles/ReactionRoles.embeds.ts @@ -1,9 +1,16 @@ import { MessageTools } from "@/modules/commands/Message"; -import { Config } from "@/modules/shared/config/types"; +import type { Config } from "@/modules/config/types"; import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; import { Inject, Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; -import { CommandInteraction, EmbedBuilder, Message, TextChannel, channelMention, roleMention } from "discord.js"; +import { + type CommandInteraction, + EmbedBuilder, + type Message, + type TextChannel, + channelMention, + roleMention, +} from "discord.js"; import type { IReactionRolesEmbeds } from "./interfaces"; import type { IReaction, REACTION_OPTIONS } from "./types"; diff --git a/src/modules/reactionRoles/ReactionRoles.module.ts b/src/modules/reactionRoles/ReactionRoles.module.ts index 4e0dd1026..0717f35be 100644 --- a/src/modules/reactionRoles/ReactionRoles.module.ts +++ b/src/modules/reactionRoles/ReactionRoles.module.ts @@ -2,10 +2,9 @@ import { Global, Module } from "@nestjs/common"; import * as Commands from "./commands"; import { ReactionRolesEvents } from "./events/ReactionRoles"; import { ReactionRolesEmbedsProvider, ReactionRolesProvider } from "./types/providers"; -//...Object.values(Commands) @Global() @Module({ - providers: [ReactionRolesEvents, ReactionRolesProvider, ReactionRolesEmbedsProvider], + providers: [ReactionRolesEvents, ReactionRolesProvider, ReactionRolesEmbedsProvider, ...Object.values(Commands)], exports: [ReactionRolesProvider, ReactionRolesEmbedsProvider], }) export class ReactionRolesModule {} diff --git a/src/modules/reactionRoles/ReactionRoles.repository.ts b/src/modules/reactionRoles/ReactionRoles.repository.ts index fc13b3beb..5fbbafcd7 100644 --- a/src/modules/reactionRoles/ReactionRoles.repository.ts +++ b/src/modules/reactionRoles/ReactionRoles.repository.ts @@ -1,8 +1,8 @@ -import { PrismaService } from "@/modules/shared/database/prisma/Prisma.service"; +import type { PrismaService } from "@/modules/database/prisma/Prisma.service"; import { Services } from "@/types/Constants"; import { Inject, Injectable } from "@nestjs/common"; -import { Guild, TextChannel } from "discord.js"; -import { ReactionRolesEntity } from "./entities/ReactionRole.entity"; +import type { Guild, TextChannel } from "discord.js"; +import type { ReactionRolesEntity } from "./entities/ReactionRole.entity"; import type { IReactionRolesRepository } from "./interfaces/IReactionRoleRepository"; import type { IReaction, REACTION_OPTIONS } from "./types"; @@ -30,12 +30,18 @@ export class ReactionRolesRepository implements IReactionRolesRepository { })[0]; } - public async getInChannel(guild: Guild, channel: TextChannel): Promise { + public async getInChannel( + guild: Guild, + channel: TextChannel, + ): Promise { const data = await this.getAll(guild); return data.filter(async (reaction) => reaction.Channel === channel.id); } - private async checkIfExists(guild: Guild, { Channel, Message, Role, Emoji, Option }: IReaction): Promise { + private async checkIfExists( + guild: Guild, + { Channel, Message, Role, Emoji, Option }: IReaction, + ): Promise { const GetGuild = await this.getAll(guild); let Verify = false; for (const reaction of GetGuild) { @@ -118,7 +124,9 @@ export class ReactionRolesRepository implements IReactionRolesRepository { return { status: "Deleted" }; } - public async deleteMany(guild: Guild): Promise<{ status: "UnableToDelete" | "Deleted"; count: number }> { + public async deleteMany( + guild: Guild, + ): Promise<{ status: "UnableToDelete" | "Deleted"; count: number }> { const count = await this.prisma.guildReactionRoles.count({ where: { guildId: guild.id }, }); diff --git a/src/modules/reactionRoles/ReactionRoles.service.ts b/src/modules/reactionRoles/ReactionRoles.service.ts index bdd6a5ca0..c3bee2d53 100644 --- a/src/modules/reactionRoles/ReactionRoles.service.ts +++ b/src/modules/reactionRoles/ReactionRoles.service.ts @@ -1,8 +1,15 @@ -import type { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { Inject, Injectable } from "@nestjs/common"; -import { Client, CommandInteraction, Guild, Message, Role, TextChannel } from "discord.js"; -import { ReactionRolesEntity } from "./entities/ReactionRole.entity"; +import type { + Client, + CommandInteraction, + Guild, + Message, + Role, + TextChannel, +} from "discord.js"; +import type { ReactionRolesEntity } from "./entities/ReactionRole.entity"; import type { IReactionRolesEmbeds, IReactionRolesService } from "./interfaces"; import type { IReaction, REACTION_OPTIONS } from "./types"; import { ReactionRoles } from "./types/constants"; @@ -22,7 +29,10 @@ export class ReactionRolesService implements IReactionRolesService { return await this.database.ReactionRolesRepo().getAll(guild); } - public async getInChannel(guild: Guild, channel: TextChannel): Promise { + public async getInChannel( + guild: Guild, + channel: TextChannel, + ): Promise { return await this.database.ReactionRolesRepo().getInChannel(guild, channel); } @@ -64,7 +74,9 @@ export class ReactionRolesService implements IReactionRolesService { }); } - public async DeleteAll(guild: Guild): Promise<{ status: "UnableToDelete" | "Deleted"; count: number }> { + public async DeleteAll( + guild: Guild, + ): Promise<{ status: "UnableToDelete" | "Deleted"; count: number }> { return await this.database.ReactionRolesRepo().deleteMany(guild); } @@ -99,7 +111,9 @@ export class ReactionRolesService implements IReactionRolesService { emoji: string, ) { if (!message) { - return await interaction.reply({ embeds: [await this.embeds.MessageNotFoundEmbed(interaction)] }); + return await interaction.reply({ + embeds: [await this.embeds.MessageNotFoundEmbed(interaction)], + }); } } } diff --git a/src/modules/reactionRoles/commands/CreateReaction/CreateReaction.command.ts b/src/modules/reactionRoles/commands/CreateReaction/CreateReaction.command.ts index df542f66c..0326ef886 100644 --- a/src/modules/reactionRoles/commands/CreateReaction/CreateReaction.command.ts +++ b/src/modules/reactionRoles/commands/CreateReaction/CreateReaction.command.ts @@ -2,15 +2,16 @@ import { CommandConfig, CommandPermissions, ValidatedOptions } from "@/common/de import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; import { MessageTools } from "@/modules/commands/Message"; import { localizationMapByKey } from "@necord/localization"; -import { Inject, Injectable, Logger, UseGuards } from "@nestjs/common"; +import { Inject, Logger, UseGuards } from "@nestjs/common"; import { Client, TextChannel } from "discord.js"; import { Ctx, SlashCommandContext, Subcommand } from "necord"; import type { IReactionRolesEmbeds, IReactionRolesService } from "../../interfaces"; import type { IReaction } from "../../types"; import { ReactionRoles } from "../../types/constants"; import { CreateReactionDTO } from "./CreateReaction.dto"; +import { ReactionRolesCommand } from "../../ReactionRoles.decorator"; -@Injectable() +@ReactionRolesCommand() export class CreateReactionCommand { public constructor( @Inject(ReactionRoles.Service) private readonly reaction: IReactionRolesService, diff --git a/src/modules/reactionRoles/commands/DeleteAllReactions.command.ts b/src/modules/reactionRoles/commands/DeleteAllReactions.command.ts index 6028188d2..0d07e8b26 100644 --- a/src/modules/reactionRoles/commands/DeleteAllReactions.command.ts +++ b/src/modules/reactionRoles/commands/DeleteAllReactions.command.ts @@ -3,14 +3,15 @@ import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; import { Buttons, ConfirmButtonEnum } from "@/modules/components/Buttons.component"; import { Extends } from "@/types/Constants"; import { localizationMapByKey } from "@necord/localization"; -import { Inject, Injectable, Logger, UseGuards } from "@nestjs/common"; +import { Inject, Logger, UseGuards } from "@nestjs/common"; import { CommandInteraction } from "discord.js"; import { Button, ButtonContext, ComponentParam, Ctx, SlashCommandContext, Subcommand } from "necord"; import { InteractionTools } from "../../commands/Interaction"; import type { IReactionRolesEmbeds, IReactionRolesService } from "../interfaces"; import { ReactionRoles } from "../types/constants"; +import { ReactionRolesCommand } from "../ReactionRoles.decorator"; -@Injectable() +@ReactionRolesCommand() export class DeleteAllReactionsCommand { public constructor( @Inject(ReactionRoles.Service) private readonly reaction: IReactionRolesService, diff --git a/src/modules/reactionRoles/commands/DeleteReaction/DeleteReaction.command.ts b/src/modules/reactionRoles/commands/DeleteReaction/DeleteReaction.command.ts index 98b6e33b4..8393727dc 100644 --- a/src/modules/reactionRoles/commands/DeleteReaction/DeleteReaction.command.ts +++ b/src/modules/reactionRoles/commands/DeleteReaction/DeleteReaction.command.ts @@ -3,14 +3,15 @@ import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; import { Buttons } from "@/modules/components/Buttons.component"; import { Extends } from "@/types/Constants"; import { localizationMapByKey } from "@necord/localization"; -import { Inject, Injectable, Logger, UseGuards } from "@nestjs/common"; +import { Inject, Logger, UseGuards } from "@nestjs/common"; import { Client, TextChannel } from "discord.js"; import { Ctx, SlashCommandContext, Subcommand } from "necord"; import type { IReactionRolesEmbeds, IReactionRolesService } from "../../interfaces"; import { ReactionRoles } from "../../types/constants"; import { DeleteReactionDTO } from "./DeleteReaction.dto"; +import { ReactionRolesCommand } from "../../ReactionRoles.decorator"; -@Injectable() +@ReactionRolesCommand() export class DeleteReactionCommand { public constructor( @Inject(ReactionRoles.Service) private readonly reaction: IReactionRolesService, diff --git a/src/modules/reactionRoles/commands/EditReaction/EditReaction.command.ts b/src/modules/reactionRoles/commands/EditReaction/EditReaction.command.ts index 322fc838b..5a5ed8dc2 100644 --- a/src/modules/reactionRoles/commands/EditReaction/EditReaction.command.ts +++ b/src/modules/reactionRoles/commands/EditReaction/EditReaction.command.ts @@ -2,14 +2,15 @@ import { CommandConfig, CommandPermissions, ValidatedOptions } from "@/common/de import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; import { Buttons } from "@/modules/components/Buttons.component"; import { Extends } from "@/types/Constants"; -import { Inject, Injectable, Logger, UseGuards } from "@nestjs/common"; +import { Inject, Logger, UseGuards } from "@nestjs/common"; import { Client, TextChannel } from "discord.js"; import { Ctx, SlashCommandContext, Subcommand } from "necord"; import type { IReactionRolesEmbeds, IReactionRolesService } from "../../interfaces"; import { ReactionRoles } from "../../types/constants"; import { EditReactionDTO } from "./EditReaction.dto"; +import { ReactionRolesCommand } from "../../ReactionRoles.decorator"; -@Injectable() +@ReactionRolesCommand() export class EditReactionCommand { public constructor( @Inject(ReactionRoles.Service) private readonly reaction: IReactionRolesService, @@ -22,7 +23,7 @@ export class EditReactionCommand { @Subcommand({ name: "edit", - description: "", + description: "Edit an ReactionRole", }) @CommandConfig({ category: "🎩 ReactionRole", disable: false }) @CommandPermissions({ diff --git a/src/modules/reactionRoles/commands/ReactionTypes.command.ts b/src/modules/reactionRoles/commands/ReactionTypes.command.ts index 27babdd47..83032ed12 100644 --- a/src/modules/reactionRoles/commands/ReactionTypes.command.ts +++ b/src/modules/reactionRoles/commands/ReactionTypes.command.ts @@ -1,12 +1,13 @@ import { CommandConfig, CommandPermissions } from "@/common/decorators"; import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards"; import { localizationMapByKey } from "@necord/localization"; -import { Inject, Injectable, Logger, UseGuards } from "@nestjs/common"; -import { Ctx, SlashCommand, SlashCommandContext, Subcommand } from "necord"; +import { Inject, Logger, UseGuards } from "@nestjs/common"; +import { Ctx, SlashCommandContext, Subcommand } from "necord"; import type { IReactionRolesEmbeds, IReactionRolesService } from "../interfaces"; import { ReactionRoles } from "../types/constants"; +import { ReactionRolesCommand } from "../ReactionRoles.decorator"; -@Injectable() +@ReactionRolesCommand() export class ReactionTypesCommand { public constructor( @Inject(ReactionRoles.Service) private readonly reaction: IReactionRolesService, diff --git a/src/modules/reactionRoles/events/ReactionRoles.ts b/src/modules/reactionRoles/events/ReactionRoles.ts index 5bb8f85ad..8eddd0dad 100644 --- a/src/modules/reactionRoles/events/ReactionRoles.ts +++ b/src/modules/reactionRoles/events/ReactionRoles.ts @@ -1,10 +1,10 @@ import { MessageTools } from "@/modules/commands/Message"; -import type { IDatabaseService } from "@/modules/shared/database/interfaces/IDatabaseService"; +import type { IDatabaseService } from "@/modules/database/interfaces/IDatabaseService"; import { Services } from "@/types/Constants"; import { LOCALIZATION_ADAPTER, NestedLocalizationAdapter } from "@necord/localization"; import { Inject, Injectable } from "@nestjs/common"; import { Client, EmbedBuilder, roleMention } from "discord.js"; -import { Context, ContextOf, On } from "necord"; +import { Context, type ContextOf, On } from "necord"; import type { IReactionRolesService } from "../interfaces"; import { ReactionRoles } from "../types/constants"; diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 2f93b2e16..f12f71a1a 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,5 +1,5 @@ -import { UserEntity } from "@/modules/shared/database/entities"; -import { BaseMessageOptions, EmbedBuilder } from "discord.js"; +import type { UserEntity } from "@/modules/database/entities"; +import type { BaseMessageOptions, EmbedBuilder } from "discord.js"; import "fastify"; declare module "fastify" { diff --git a/yarn.lock b/yarn.lock index a482ffe03..e2ae7d79f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1117,6 +1117,22 @@ __metadata: languageName: node linkType: hard +"@nestjs/platform-express@npm:^10.3.8": + version: 10.3.8 + resolution: "@nestjs/platform-express@npm:10.3.8" + dependencies: + body-parser: "npm:1.20.2" + cors: "npm:2.8.5" + express: "npm:4.19.2" + multer: "npm:1.4.4-lts.1" + tslib: "npm:2.6.2" + peerDependencies: + "@nestjs/common": ^10.0.0 + "@nestjs/core": ^10.0.0 + checksum: 10c0/28877eae9b551a3eafa07fe1fe4e4608aafa97176322698c79d82179f5e87f01021a6c867e649df40dc134dfd25524601ee3ea9269eb1935471f21f680a0393c + languageName: node + linkType: hard + "@nestjs/schematics@npm:^10.0.1, @nestjs/schematics@npm:^10.1.1": version: 10.1.1 resolution: "@nestjs/schematics@npm:10.1.1" @@ -1824,6 +1840,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: "npm:~2.1.34" + negotiator: "npm:0.6.3" + checksum: 10c0/3a35c5f5586cfb9a21163ca47a5f77ac34fa8ceb5d17d2fa2c0d81f41cbd7f8c6fa52c77e2c039acc0f4d09e71abdc51144246900f6bef5e3c4b333f77d89362 + languageName: node + linkType: hard + "acorn-import-assertions@npm:^1.9.0": version: 1.9.0 resolution: "acorn-import-assertions@npm:1.9.0" @@ -2006,6 +2032,13 @@ __metadata: languageName: node linkType: hard +"append-field@npm:^1.0.0": + version: 1.0.0 + resolution: "append-field@npm:1.0.0" + checksum: 10c0/1b5abcc227e5179936a9e4f7e2af4769fa1f00eda85bbaed907f7964b0fd1f7d61f0f332b35337f391389ff13dd5310c2546ba670f8e5a743b23ec85185c73ef + languageName: node + linkType: hard + "arg@npm:^4.1.0": version: 4.1.3 resolution: "arg@npm:4.1.3" @@ -2020,6 +2053,13 @@ __metadata: languageName: node linkType: hard +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: 10c0/806966c8abb2f858b08f5324d9d18d7737480610f3bd5d3498aaae6eb5efdc501a884ba019c9b4a8f02ff67002058749d05548fd42fa8643f02c9c7f22198b91 + languageName: node + linkType: hard + "array-ify@npm:^1.0.0": version: 1.0.0 resolution: "array-ify@npm:1.0.0" @@ -2080,6 +2120,26 @@ __metadata: languageName: node linkType: hard +"body-parser@npm:1.20.2": + version: 1.20.2 + resolution: "body-parser@npm:1.20.2" + dependencies: + bytes: "npm:3.1.2" + content-type: "npm:~1.0.5" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.11.0" + raw-body: "npm:2.5.2" + type-is: "npm:~1.6.18" + unpipe: "npm:1.0.0" + checksum: 10c0/06f1438fff388a2e2354c96aa3ea8147b79bfcb1262dfcc2aae68ec13723d01d5781680657b74e9f83c808266d5baf52804032fbde2b7382b89bd8cdb273ace9 + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -2139,6 +2199,15 @@ __metadata: languageName: node linkType: hard +"busboy@npm:^1.0.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: "npm:^1.1.0" + checksum: 10c0/fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f + languageName: node + linkType: hard + "bytes@npm:3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -2527,6 +2596,18 @@ __metadata: languageName: node linkType: hard +"concat-stream@npm:^1.5.2": + version: 1.6.2 + resolution: "concat-stream@npm:1.6.2" + dependencies: + buffer-from: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^2.2.2" + typedarray: "npm:^0.0.6" + checksum: 10c0/2e9864e18282946dabbccb212c5c7cec0702745e3671679eb8291812ca7fd12023f7d8cb36493942a62f770ac96a7f90009dc5c82ad69893438371720fa92617 + languageName: node + linkType: hard + "consola@npm:^2.15.0": version: 2.15.3 resolution: "consola@npm:2.15.3" @@ -2534,6 +2615,22 @@ __metadata: languageName: node linkType: hard +"content-disposition@npm:0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: 10c0/bac0316ebfeacb8f381b38285dc691c9939bf0a78b0b7c2d5758acadad242d04783cee5337ba7d12a565a19075af1b3c11c728e1e4946de73c6ff7ce45f3f1bb + languageName: node + linkType: hard + +"content-type@npm:~1.0.4, content-type@npm:~1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + "conventional-changelog-angular@npm:^7.0.0": version: 7.0.0 resolution: "conventional-changelog-angular@npm:7.0.0" @@ -2580,13 +2677,37 @@ __metadata: languageName: node linkType: hard -"core-util-is@npm:^1.0.3": +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: 10c0/b36fd0d4e3fef8456915fcf7742e58fbfcc12a17a018e0eb9501c9d5ef6893b596466f03b0564b81af29ff2538fd0aa4b9d54fe5ccbfb4c90ea50ad29fe2d221 + languageName: node + linkType: hard + +"cookie@npm:0.6.0": + version: 0.6.0 + resolution: "cookie@npm:0.6.0" + checksum: 10c0/f2318b31af7a31b4ddb4a678d024514df5e705f9be5909a192d7f116cfb6d45cbacf96a473fa733faa95050e7cff26e7832bb3ef94751592f1387b71c8956686 + languageName: node + linkType: hard + +"core-util-is@npm:^1.0.3, core-util-is@npm:~1.0.0": version: 1.0.3 resolution: "core-util-is@npm:1.0.3" checksum: 10c0/90a0e40abbddfd7618f8ccd63a74d88deea94e77d0e8dbbea059fa7ebebb8fbb4e2909667fe26f3a467073de1a542ebe6ae4c73a73745ac5833786759cd906c9 languageName: node linkType: hard +"cors@npm:2.8.5": + version: 2.8.5 + resolution: "cors@npm:2.8.5" + dependencies: + object-assign: "npm:^4" + vary: "npm:^1" + checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761 + languageName: node + linkType: hard + "cosmiconfig-typescript-loader@npm:^5.0.0": version: 5.0.0 resolution: "cosmiconfig-typescript-loader@npm:5.0.0" @@ -2689,6 +2810,15 @@ __metadata: languageName: node linkType: hard +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + "debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" @@ -2758,6 +2888,13 @@ __metadata: languageName: node linkType: hard +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 10c0/bd7633942f57418f5a3b80d5cb53898127bcf53e24cdf5d5f4396be471417671f0fee48a4ebe9a1e9defbde2a31280011af58a57e090ff822f589b443ed4e643 + languageName: node + linkType: hard + "detect-file@npm:^1.0.0": version: 1.0.0 resolution: "detect-file@npm:1.0.0" @@ -2852,6 +2989,13 @@ __metadata: languageName: node linkType: hard +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + "electron-to-chromium@npm:^1.4.668": version: 1.4.724 resolution: "electron-to-chromium@npm:1.4.724" @@ -2880,6 +3024,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: 10c0/f6c2387379a9e7c1156c1c3d4f9cb7bb11cf16dd4c1682e1f6746512564b053df5781029b6061296832b59fb22f459dbe250386d217c2f6e203601abb2ee0bec + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -3032,6 +3183,13 @@ __metadata: languageName: node linkType: hard +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -3098,6 +3256,13 @@ __metadata: languageName: node linkType: hard +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + "eventemitter2@npm:6.4.9": version: 6.4.9 resolution: "eventemitter2@npm:6.4.9" @@ -3152,6 +3317,45 @@ __metadata: languageName: node linkType: hard +"express@npm:4.19.2": + version: 4.19.2 + resolution: "express@npm:4.19.2" + dependencies: + accepts: "npm:~1.3.8" + array-flatten: "npm:1.1.1" + body-parser: "npm:1.20.2" + content-disposition: "npm:0.5.4" + content-type: "npm:~1.0.4" + cookie: "npm:0.6.0" + cookie-signature: "npm:1.0.6" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:1.2.0" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + merge-descriptors: "npm:1.0.1" + methods: "npm:~1.1.2" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:0.1.7" + proxy-addr: "npm:~2.0.7" + qs: "npm:6.11.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.2.1" + send: "npm:0.18.0" + serve-static: "npm:1.15.0" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 10c0/e82e2662ea9971c1407aea9fc3c16d6b963e55e3830cd0ef5e00b533feda8b770af4e3be630488ef8a752d7c75c4fcefb15892868eeaafe7353cb9e3e269fdcb + languageName: node + linkType: hard + "external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" @@ -3241,6 +3445,21 @@ __metadata: languageName: node linkType: hard +"finalhandler@npm:1.2.0": + version: 1.2.0 + resolution: "finalhandler@npm:1.2.0" + dependencies: + debug: "npm:2.6.9" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + statuses: "npm:2.0.1" + unpipe: "npm:~1.0.0" + checksum: 10c0/64b7e5ff2ad1fcb14931cd012651631b721ce657da24aedb5650ddde9378bf8e95daa451da43398123f5de161a81e79ff5affe4f9f2a6d2df4a813d6d3e254b7 + languageName: node + linkType: hard + "find-node-modules@npm:^2.1.2": version: 2.1.3 resolution: "find-node-modules@npm:2.1.3" @@ -3321,6 +3540,20 @@ __metadata: languageName: node linkType: hard +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a + languageName: node + linkType: hard + "fs-extra@npm:9.1.0": version: 9.1.0 resolution: "fs-extra@npm:9.1.0" @@ -3789,7 +4022,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4": +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -3913,6 +4146,13 @@ __metadata: languageName: node linkType: hard +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -4049,6 +4289,13 @@ __metadata: languageName: node linkType: hard +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -4578,6 +4825,13 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 10c0/d160f31246907e79fed398470285f21bafb45a62869dc469b1c8877f3f064f5eabc4bcc122f9479b8b605bc5c76187d7871cf84c4ee3ecd3e487da1993279928 + languageName: node + linkType: hard + "memfs@npm:^3.4.1": version: 3.5.3 resolution: "memfs@npm:3.5.3" @@ -4594,6 +4848,13 @@ __metadata: languageName: node linkType: hard +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 10c0/b67d07bd44cfc45cebdec349bb6e1f7b077ee2fd5beb15d1f7af073849208cb6f144fe403e29a36571baf3f4e86469ac39acf13c318381e958e186b2766f54ec + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -4615,6 +4876,13 @@ __metadata: languageName: node linkType: hard +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2 + languageName: node + linkType: hard + "micromatch@npm:4.0.5, micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": version: 4.0.5 resolution: "micromatch@npm:4.0.5" @@ -4632,7 +4900,7 @@ __metadata: languageName: node linkType: hard -"mime-types@npm:^2.1.27": +"mime-types@npm:^2.1.27, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -4641,6 +4909,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: 10c0/b92cd0adc44888c7135a185bfd0dddc42c32606401c72896a842ae15da71eb88858f17669af41e498b463cd7eb998f7b48939a25b08374c7924a9c8a6f8a81b0 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -4787,6 +5064,17 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^0.5.4": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: "npm:^1.2.6" + bin: + mkdirp: bin/cmd.js + checksum: 10c0/e2e2be789218807b58abced04e7b49851d9e46e88a2f9539242cc8a92c9b5c3a0b9bab360bd3014e02a140fc4fbc58e31176c408b493f8a2a6f4986bd7527b01 + languageName: node + linkType: hard + "mkdirp@npm:^1.0.3": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -4822,6 +5110,13 @@ __metadata: languageName: node linkType: hard +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -4829,6 +5124,28 @@ __metadata: languageName: node linkType: hard +"ms@npm:2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"multer@npm:1.4.4-lts.1": + version: 1.4.4-lts.1 + resolution: "multer@npm:1.4.4-lts.1" + dependencies: + append-field: "npm:^1.0.0" + busboy: "npm:^1.0.0" + concat-stream: "npm:^1.5.2" + mkdirp: "npm:^0.5.4" + object-assign: "npm:^4.1.1" + type-is: "npm:^1.6.4" + xtend: "npm:^4.0.0" + checksum: 10c0/63277d3483869f424274ef8ce6ab7ff4ce9d2c1cc69e707fc8b5d9b2b348ae6f742809e0b357a591dea885d147594bcd06528d3d6bbe32046115d4a7e126b954 + languageName: node + linkType: hard + "mute-stream@npm:0.0.8": version: 0.0.8 resolution: "mute-stream@npm:0.0.8" @@ -4858,6 +5175,7 @@ __metadata: "@nestjs/config": "npm:^3.2.0" "@nestjs/core": "npm:^10.3.3" "@nestjs/event-emitter": "npm:^2.0.4" + "@nestjs/platform-express": "npm:^10.3.8" "@nestjs/schematics": "npm:^10.1.1" "@nestjs/testing": "npm:^10.3.3" "@prisma/client": "npm:5.11.0" @@ -4915,7 +5233,7 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: 10c0/3ec9fd413e7bf071c937ae60d572bc67155262068ed522cf4b3be5edbe6ddf67d095ec03a3a14ebf8fc8e95f8e1d61be4869db0dbb0de696f6b837358bd43fc2 @@ -5013,6 +5331,29 @@ __metadata: languageName: node linkType: hard +"object-assign@npm:^4, object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 10c0/fad603f408e345c82e946abdf4bfd774260a5ed3e5997a0b057c44153ac32c7271ff19e3a5ae39c858da683ba045ccac2f65245c12763ce4e8594f818f4a648d + languageName: node + linkType: hard + +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -5135,6 +5476,13 @@ __metadata: languageName: node linkType: hard +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + "path-exists@npm:^5.0.0": version: 5.0.0 resolution: "path-exists@npm:5.0.0" @@ -5180,6 +5528,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 10c0/50a1ddb1af41a9e68bd67ca8e331a705899d16fb720a1ea3a41e310480948387daf603abb14d7b0826c58f10146d49050a1291ba6a82b78a382d1c02c0b8f905 + languageName: node + linkType: hard + "path-to-regexp@npm:3.2.0": version: 3.2.0 resolution: "path-to-regexp@npm:3.2.0" @@ -5303,6 +5658,13 @@ __metadata: languageName: node linkType: hard +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 10c0/bec089239487833d46b59d80327a1605e1c5287eaad770a291add7f45fda1bb5e28b38e0e061add0a1d0ee0984788ce74fa394d345eed1c420cacf392c554367 + languageName: node + linkType: hard + "promise-retry@npm:^2.0.1": version: 2.0.1 resolution: "promise-retry@npm:2.0.1" @@ -5313,6 +5675,16 @@ __metadata: languageName: node linkType: hard +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210 + languageName: node + linkType: hard + "punycode@npm:^2.1.0": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -5320,6 +5692,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: "npm:^1.0.4" + checksum: 10c0/4e4875e4d7c7c31c233d07a448e7e4650f456178b9dd3766b7cfa13158fdb24ecb8c4f059fa91e820dc6ab9f2d243721d071c9c0378892dcdad86e9e9a27c68f + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -5336,7 +5717,14 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:^2.5.2": +"range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:2.5.2, raw-body@npm:^2.5.2": version: 2.5.2 resolution: "raw-body@npm:2.5.2" dependencies: @@ -5355,6 +5743,21 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^2.2.2": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: "npm:~1.0.0" + inherits: "npm:~2.0.3" + isarray: "npm:~1.0.0" + process-nextick-args: "npm:~2.0.0" + safe-buffer: "npm:~5.1.1" + string_decoder: "npm:~1.1.1" + util-deprecate: "npm:~1.0.1" + checksum: 10c0/7efdb01f3853bc35ac62ea25493567bf588773213f5f4a79f9c365e1ad13bab845ac0dae7bc946270dc40c3929483228415e92a3fc600cc7e4548992f41ee3fa + languageName: node + linkType: hard + "readable-stream@npm:^3.4.0": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -5622,13 +6025,20 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 languageName: node linkType: hard +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 + languageName: node + linkType: hard + "safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0": version: 2.1.2 resolution: "safer-buffer@npm:2.1.2" @@ -5667,6 +6077,27 @@ __metadata: languageName: node linkType: hard +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + mime: "npm:1.6.0" + ms: "npm:2.1.3" + on-finished: "npm:2.4.1" + range-parser: "npm:~1.2.1" + statuses: "npm:2.0.1" + checksum: 10c0/0eb134d6a51fc13bbcb976a1f4214ea1e33f242fae046efc311e80aff66c7a43603e26a79d9d06670283a13000e51be6e0a2cb80ff0942eaf9f1cd30b7ae736a + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -5676,6 +6107,18 @@ __metadata: languageName: node linkType: hard +"serve-static@npm:1.15.0": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + parseurl: "npm:~1.3.3" + send: "npm:0.18.0" + checksum: 10c0/fa9f0e21a540a28f301258dfe1e57bb4f81cd460d28f0e973860477dd4acef946a1f41748b5bd41c73b621bea2029569c935faa38578fd34cd42a9b4947088ba + languageName: node + linkType: hard + "set-function-length@npm:^1.2.1": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -5726,6 +6169,18 @@ __metadata: languageName: node linkType: hard +"side-channel@npm:^1.0.4": + version: 1.0.6 + resolution: "side-channel@npm:1.0.6" + dependencies: + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + object-inspect: "npm:^1.13.1" + checksum: 10c0/d2afd163dc733cc0a39aa6f7e39bf0c436293510dbccbff446733daeaf295857dbccf94297092ec8c53e2503acac30f0b78830876f0485991d62a90e9cad305f + languageName: node + linkType: hard + "siginfo@npm:^2.0.0": version: 2.0.0 resolution: "siginfo@npm:2.0.0" @@ -5888,6 +6343,13 @@ __metadata: languageName: node linkType: hard +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: 10c0/fbd9aecc2621364384d157f7e59426f4bfd385e8b424b5aaa79c83a6f5a1c8fd2e4e3289e95de1eb3511cb96bb333d6281a9919fafce760e4edb35b2cd2facab + languageName: node + linkType: hard + "string-argv@npm:0.3.2": version: 0.3.2 resolution: "string-argv@npm:0.3.2" @@ -5937,6 +6399,15 @@ __metadata: languageName: node linkType: hard +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: "npm:~5.1.0" + checksum: 10c0/b4f89f3a92fd101b5653ca3c99550e07bdf9e13b35037e9e2a1c7b47cec4e55e06ff3fc468e314a0b5e80bfbaf65c1ca5a84978764884ae9413bec1fc6ca924e + languageName: node + linkType: hard + "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": version: 6.0.1 resolution: "strip-ansi@npm:6.0.1" @@ -6319,6 +6790,23 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^1.6.4, type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 10c0/a23daeb538591b7efbd61ecf06b6feb2501b683ffdc9a19c74ef5baba362b4347e42f1b4ed81f5882a8c96a3bfff7f93ce3ffaf0cbbc879b532b04c97a55db9d + languageName: node + linkType: hard + +"typedarray@npm:^0.0.6": + version: 0.0.6 + resolution: "typedarray@npm:0.0.6" + checksum: 10c0/6005cb31df50eef8b1f3c780eb71a17925f3038a100d82f9406ac2ad1de5eb59f8e6decbdc145b3a1f8e5836e17b0c0002fb698b9fe2516b8f9f9ff602d36412 + languageName: node + linkType: hard + "typescript@npm:5.3.3": version: 5.3.3 resolution: "typescript@npm:5.3.3" @@ -6432,7 +6920,7 @@ __metadata: languageName: node linkType: hard -"unpipe@npm:1.0.0": +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": version: 1.0.0 resolution: "unpipe@npm:1.0.0" checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c @@ -6462,13 +6950,20 @@ __metadata: languageName: node linkType: hard -"util-deprecate@npm:^1.0.1": +"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 languageName: node linkType: hard +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672 + languageName: node + linkType: hard + "uuid@npm:9.0.1": version: 9.0.1 resolution: "uuid@npm:9.0.1" @@ -6492,6 +6987,13 @@ __metadata: languageName: node linkType: hard +"vary@npm:^1, vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f + languageName: node + linkType: hard + "vite-node@npm:1.4.0": version: 1.4.0 resolution: "vite-node@npm:1.4.0" @@ -6833,6 +7335,13 @@ __metadata: languageName: node linkType: hard +"xtend@npm:^4.0.0": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8"