From 2c0f9e38d9ae6902e5804d7eb4c5236a2317849a Mon Sep 17 00:00:00 2001 From: JonnyBro Date: Tue, 13 Sep 2022 12:10:32 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BC?= =?UTF-8?q?=D1=83=D0=B7=D1=8B=D0=BA=D1=83=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=BC=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B5?= =?UTF-8?q?=D0=BC=20=3D)=20=D0=A3=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B8=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=87=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B7=20npm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/JaBa.js | 2 +- commands/Music/loop.js | 2 +- commands/Music/nowplaying.js | 2 +- commands/Music/play.js | 2 +- commands/Music/queue.js | 4 +- helpers/Music/.eslintignore | 4 - helpers/Music/.eslintrc.json | 22 - helpers/Music/dist/Player.d.ts | 96 - helpers/Music/dist/Player.js | 579 --- .../Music/dist/Structures/ExtractorModel.d.ts | 29 - .../Music/dist/Structures/ExtractorModel.js | 65 - .../Music/dist/Structures/PlayerError.d.ts | 31 - helpers/Music/dist/Structures/PlayerError.js | 48 - helpers/Music/dist/Structures/Playlist.d.ts | 33 - helpers/Music/dist/Structures/Playlist.js | 108 - helpers/Music/dist/Structures/Queue.d.ts | 241 - helpers/Music/dist/Structures/Queue.js | 761 --- helpers/Music/dist/Structures/Track.d.ts | 53 - helpers/Music/dist/Structures/Track.js | 156 - .../dist/VoiceInterface/StreamDispatcher.d.ts | 88 - .../dist/VoiceInterface/StreamDispatcher.js | 225 - .../Music/dist/VoiceInterface/VoiceUtils.d.ts | 44 - .../Music/dist/VoiceInterface/VoiceUtils.js | 65 - .../VoiceInterface/VolumeTransformer.d.ts | 34 - .../dist/VoiceInterface/VolumeTransformer.js | 120 - helpers/Music/dist/index.d.ts | 15 - helpers/Music/dist/index.js | 33 - helpers/Music/dist/index.mjs | 21 - helpers/Music/dist/smoothVolume.d.ts | 1 - helpers/Music/dist/smoothVolume.js | 13 - helpers/Music/dist/types/types.d.ts | 453 -- helpers/Music/dist/types/types.js | 58 - helpers/Music/dist/utils/AudioFilters.d.ts | 36 - helpers/Music/dist/utils/AudioFilters.js | 97 - helpers/Music/dist/utils/FFmpegStream.d.ts | 16 - helpers/Music/dist/utils/FFmpegStream.js | 53 - helpers/Music/dist/utils/QueryResolver.d.ts | 20 - helpers/Music/dist/utils/QueryResolver.js | 66 - helpers/Music/dist/utils/Util.d.ts | 53 - helpers/Music/dist/utils/Util.js | 133 - helpers/Music/package-lock.json | 4577 ----------------- helpers/Music/package.json | 61 - helpers/Music/src/Player.ts | 607 --- .../Music/src/Structures/ExtractorModel.ts | 73 - helpers/Music/src/Structures/PlayerError.ts | 53 - helpers/Music/src/Structures/Playlist.ts | 138 - helpers/Music/src/Structures/Queue.ts | 776 --- helpers/Music/src/Structures/Track.ts | 191 - .../src/VoiceInterface/StreamDispatcher.ts | 253 - .../Music/src/VoiceInterface/VoiceUtils.ts | 82 - .../src/VoiceInterface/VolumeTransformer.ts | 144 - helpers/Music/src/index.ts | 19 - helpers/Music/src/smoothVolume.ts | 12 - helpers/Music/src/types/types.ts | 485 -- helpers/Music/src/utils/AudioFilters.ts | 107 - helpers/Music/src/utils/FFmpegStream.ts | 59 - helpers/Music/src/utils/QueryResolver.ts | 58 - helpers/Music/src/utils/Util.ts | 117 - helpers/Music/tsconfig.json | 18 - package-lock.json | 97 + package.json | 1 + 61 files changed, 104 insertions(+), 11706 deletions(-) delete mode 100644 helpers/Music/.eslintignore delete mode 100644 helpers/Music/.eslintrc.json delete mode 100644 helpers/Music/dist/Player.d.ts delete mode 100644 helpers/Music/dist/Player.js delete mode 100644 helpers/Music/dist/Structures/ExtractorModel.d.ts delete mode 100644 helpers/Music/dist/Structures/ExtractorModel.js delete mode 100644 helpers/Music/dist/Structures/PlayerError.d.ts delete mode 100644 helpers/Music/dist/Structures/PlayerError.js delete mode 100644 helpers/Music/dist/Structures/Playlist.d.ts delete mode 100644 helpers/Music/dist/Structures/Playlist.js delete mode 100644 helpers/Music/dist/Structures/Queue.d.ts delete mode 100644 helpers/Music/dist/Structures/Queue.js delete mode 100644 helpers/Music/dist/Structures/Track.d.ts delete mode 100644 helpers/Music/dist/Structures/Track.js delete mode 100644 helpers/Music/dist/VoiceInterface/StreamDispatcher.d.ts delete mode 100644 helpers/Music/dist/VoiceInterface/StreamDispatcher.js delete mode 100644 helpers/Music/dist/VoiceInterface/VoiceUtils.d.ts delete mode 100644 helpers/Music/dist/VoiceInterface/VoiceUtils.js delete mode 100644 helpers/Music/dist/VoiceInterface/VolumeTransformer.d.ts delete mode 100644 helpers/Music/dist/VoiceInterface/VolumeTransformer.js delete mode 100644 helpers/Music/dist/index.d.ts delete mode 100644 helpers/Music/dist/index.js delete mode 100644 helpers/Music/dist/index.mjs delete mode 100644 helpers/Music/dist/smoothVolume.d.ts delete mode 100644 helpers/Music/dist/smoothVolume.js delete mode 100644 helpers/Music/dist/types/types.d.ts delete mode 100644 helpers/Music/dist/types/types.js delete mode 100644 helpers/Music/dist/utils/AudioFilters.d.ts delete mode 100644 helpers/Music/dist/utils/AudioFilters.js delete mode 100644 helpers/Music/dist/utils/FFmpegStream.d.ts delete mode 100644 helpers/Music/dist/utils/FFmpegStream.js delete mode 100644 helpers/Music/dist/utils/QueryResolver.d.ts delete mode 100644 helpers/Music/dist/utils/QueryResolver.js delete mode 100644 helpers/Music/dist/utils/Util.d.ts delete mode 100644 helpers/Music/dist/utils/Util.js delete mode 100644 helpers/Music/package-lock.json delete mode 100644 helpers/Music/package.json delete mode 100644 helpers/Music/src/Player.ts delete mode 100644 helpers/Music/src/Structures/ExtractorModel.ts delete mode 100644 helpers/Music/src/Structures/PlayerError.ts delete mode 100644 helpers/Music/src/Structures/Playlist.ts delete mode 100644 helpers/Music/src/Structures/Queue.ts delete mode 100644 helpers/Music/src/Structures/Track.ts delete mode 100644 helpers/Music/src/VoiceInterface/StreamDispatcher.ts delete mode 100644 helpers/Music/src/VoiceInterface/VoiceUtils.ts delete mode 100644 helpers/Music/src/VoiceInterface/VolumeTransformer.ts delete mode 100644 helpers/Music/src/index.ts delete mode 100644 helpers/Music/src/smoothVolume.ts delete mode 100644 helpers/Music/src/types/types.ts delete mode 100644 helpers/Music/src/utils/AudioFilters.ts delete mode 100644 helpers/Music/src/utils/FFmpegStream.ts delete mode 100644 helpers/Music/src/utils/QueryResolver.ts delete mode 100644 helpers/Music/src/utils/Util.ts delete mode 100644 helpers/Music/tsconfig.json diff --git a/base/JaBa.js b/base/JaBa.js index fbcca650..97bcece4 100644 --- a/base/JaBa.js +++ b/base/JaBa.js @@ -1,5 +1,5 @@ const { Client, Collection, SlashCommandBuilder, ContextMenuCommandBuilder } = require("discord.js"), - { Player } = require("../helpers/Music/dist/index"), + { Player } = require("discord-player-play-dl"), { DiscordTogether } = require("../helpers/discordTogether"), { GiveawaysManager } = require("discord-giveaways"), { REST } = require("@discordjs/rest"), diff --git a/commands/Music/loop.js b/commands/Music/loop.js index 94cb7a33..c07d7281 100644 --- a/commands/Music/loop.js +++ b/commands/Music/loop.js @@ -1,5 +1,5 @@ const { SlashCommandBuilder, ActionRowBuilder, SelectMenuBuilder } = require("discord.js"), - { QueueRepeatMode } = require("../../helpers/Music/dist/index"); + { QueueRepeatMode } = require("discord-player-play-dl"); const BaseCommand = require("../../base/BaseCommand"); class Loop extends BaseCommand { diff --git a/commands/Music/nowplaying.js b/commands/Music/nowplaying.js index 0456a8e1..e9b6463e 100644 --- a/commands/Music/nowplaying.js +++ b/commands/Music/nowplaying.js @@ -1,5 +1,5 @@ const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"), - { QueueRepeatMode } = require("../../helpers/Music/dist/index"); + { QueueRepeatMode } = require("discord-player-play-dl"); const BaseCommand = require("../../base/BaseCommand"); class Nowplaying extends BaseCommand { diff --git a/commands/Music/play.js b/commands/Music/play.js index 0864cdfe..2ea93072 100644 --- a/commands/Music/play.js +++ b/commands/Music/play.js @@ -1,5 +1,5 @@ const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, PermissionsBitField } = require("discord.js"), - { QueryType } = require("../../helpers/Music/dist/index"); + { QueryType } = require("discord-player-play-dl"); const BaseCommand = require("../../base/BaseCommand"); class Play extends BaseCommand { diff --git a/commands/Music/queue.js b/commands/Music/queue.js index 4dae6a2b..9497eba2 100644 --- a/commands/Music/queue.js +++ b/commands/Music/queue.js @@ -1,5 +1,5 @@ const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js"), - { QueueRepeatMode } = require("../../helpers/Music/dist/index"); + { QueueRepeatMode } = require("discord-player-play-dl"); const BaseCommand = require("../../base/BaseCommand"); class Queue extends BaseCommand { @@ -151,7 +151,7 @@ class Queue extends BaseCommand { /** * * @param {import("discord.js").ChatInputCommandInteraction} interaction - * @param {import("../../helpers/Music/dist/index").Queue} queue + * @param {import("discord-player-play-dl").Queue} queue * @returns */ function generateQueueEmbeds(interaction, queue) { diff --git a/helpers/Music/.eslintignore b/helpers/Music/.eslintignore deleted file mode 100644 index cc4c338f..00000000 --- a/helpers/Music/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules/ -dist/ - -*.d.ts \ No newline at end of file diff --git a/helpers/Music/.eslintrc.json b/helpers/Music/.eslintrc.json deleted file mode 100644 index d7521756..00000000 --- a/helpers/Music/.eslintrc.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "env": { - "node": true - }, - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended" - ], - "rules": { - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-unused-vars": "error", - "@typescript-eslint/no-explicit-any": "error", - "@typescript-eslint/ban-ts-comment": "error", - "semi": "error", - "no-console": "error" - } -} \ No newline at end of file diff --git a/helpers/Music/dist/Player.d.ts b/helpers/Music/dist/Player.d.ts deleted file mode 100644 index 02a4fa73..00000000 --- a/helpers/Music/dist/Player.d.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Client, Collection, GuildResolvable } from "discord.js"; -import { TypedEmitter as EventEmitter } from "tiny-typed-emitter"; -import { Queue } from "./Structures/Queue"; -import { VoiceUtils } from "./VoiceInterface/VoiceUtils"; -import { PlayerEvents, PlayerOptions, SearchOptions, PlayerInitOptions, PlayerSearchResult, PlaylistInitData } from "./types/types"; -import Track from "./Structures/Track"; -import { Playlist } from "./Structures/Playlist"; -import { ExtractorModel } from "./Structures/ExtractorModel"; -declare class Player extends EventEmitter { - readonly client: Client; - readonly options: PlayerInitOptions; - readonly queues: Collection>; - readonly voiceUtils: VoiceUtils; - readonly extractors: Collection; - requiredEvents: string[]; - /** - * Creates new Discord Player - * @param {Client} client The Discord Client - * @param {PlayerInitOptions} [options] The player init options - */ - constructor(client: Client, options?: PlayerInitOptions); - /** - * Handles voice state update - * @param {VoiceState} oldState The old voice state - * @param {VoiceState} newState The new voice state - * @returns {void} - * @private - */ - private _handleVoiceState; - /** - * Creates a queue for a guild if not available, else returns existing queue - * @param {GuildResolvable} guild The guild - * @param {PlayerOptions} queueInitOptions Queue init options - * @returns {Queue} - */ - createQueue(guild: GuildResolvable, queueInitOptions?: PlayerOptions & { - metadata?: T; - }): Queue; - /** - * Returns the queue if available - * @param {GuildResolvable} guild The guild id - * @returns {Queue} - */ - getQueue(guild: GuildResolvable): Queue; - /** - * Deletes a queue and returns deleted queue object - * @param {GuildResolvable} guild The guild id to remove - * @returns {Queue} - */ - deleteQueue(guild: GuildResolvable): Queue; - /** - * @typedef {object} PlayerSearchResult - * @property {Playlist} [playlist] The playlist (if any) - * @property {Track[]} tracks The tracks - */ - /** - * Search tracks - * @param {string|Track} query The search query - * @param {SearchOptions} options The search options - * @returns {Promise} - */ - search(query: string | Track, options: SearchOptions): Promise; - /** - * Registers extractor - * @param {string} extractorName The extractor name - * @param {ExtractorModel|any} extractor The extractor object - * @param {boolean} [force=false] Overwrite existing extractor with this name (if available) - * @returns {ExtractorModel} - */ - use(extractorName: string, extractor: ExtractorModel | any, force?: boolean): ExtractorModel; - /** - * Removes registered extractor - * @param {string} extractorName The extractor name - * @returns {ExtractorModel} - */ - unuse(extractorName: string): ExtractorModel; - /** - * Generates a report of the dependencies used by the `@discordjs/voice` module. Useful for debugging. - * @returns {string} - */ - scanDeps(): string; - emit(eventName: U, ...args: Parameters): boolean; - /** - * Resolves queue - * @param {GuildResolvable|Queue} queueLike Queue like object - * @returns {Queue} - */ - resolveQueue(queueLike: GuildResolvable | Queue): Queue; - [Symbol.iterator](): Generator, void, undefined>; - /** - * Creates `Playlist` instance - * @param data The data to initialize a playlist - */ - createPlaylist(data: PlaylistInitData): Playlist; -} -export { Player }; diff --git a/helpers/Music/dist/Player.js b/helpers/Music/dist/Player.js deleted file mode 100644 index 4cde7d71..00000000 --- a/helpers/Music/dist/Player.js +++ /dev/null @@ -1,579 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Player = void 0; -const tslib_1 = require("tslib"); -const discord_js_1 = require("discord.js"); -const tiny_typed_emitter_1 = require("tiny-typed-emitter"); -const Queue_1 = require("./Structures/Queue"); -const VoiceUtils_1 = require("./VoiceInterface/VoiceUtils"); -const types_1 = require("./types/types"); -const Track_1 = tslib_1.__importDefault(require("./Structures/Track")); -const play_dl_1 = tslib_1.__importDefault(require("play-dl")); -const spotify_url_info_1 = tslib_1.__importDefault(require("spotify-url-info")); -const QueryResolver_1 = require("./utils/QueryResolver"); -const Util_1 = require("./utils/Util"); -const PlayerError_1 = require("./Structures/PlayerError"); -const Playlist_1 = require("./Structures/Playlist"); -const ExtractorModel_1 = require("./Structures/ExtractorModel"); -const voice_1 = require("@discordjs/voice"); -class Player extends tiny_typed_emitter_1.TypedEmitter { - /** - * Creates new Discord Player - * @param {Client} client The Discord Client - * @param {PlayerInitOptions} [options] The player init options - */ - constructor(client, options = {}) { - super(); - this.options = { - autoRegisterExtractor: true, - connectionTimeout: 20000 - }; - this.queues = new discord_js_1.Collection(); - this.voiceUtils = new VoiceUtils_1.VoiceUtils(); - this.extractors = new discord_js_1.Collection(); - this.requiredEvents = ["error", "connectionError"]; - /** - * The discord.js client - * @type {Client} - */ - this.client = client; - if (this.client?.options?.intents && !new discord_js_1.IntentsBitField(this.client?.options?.intents).has(discord_js_1.IntentsBitField.Flags.GuildVoiceStates)) { - throw new PlayerError_1.PlayerError('client is missing "GuildVoiceStates" intent'); - } - /** - * The extractors collection - * @type {ExtractorModel} - */ - this.options = Object.assign(this.options, options); - this.client.on("voiceStateUpdate", this._handleVoiceState.bind(this)); - if (this.options?.autoRegisterExtractor) { - let nv; // eslint-disable-line @typescript-eslint/no-explicit-any - if ((nv = Util_1.Util.require("@discord-player/extractor"))) { - ["Attachment", "Facebook", "Reverbnation", "Vimeo"].forEach((ext) => void this.use(ext, nv[ext])); - } - } - } - /** - * Handles voice state update - * @param {VoiceState} oldState The old voice state - * @param {VoiceState} newState The new voice state - * @returns {void} - * @private - */ - _handleVoiceState(oldState, newState) { - const queue = this.getQueue(oldState.guild.id); - if (!queue || !queue.connection) - return; - if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) { - try { - queue.destroy(); - } - catch { - /* noop */ - } - return void this.emit("botDisconnect", queue); - } - if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (!oldState.serverMute && newState.serverMute) { - // state.serverMute can be null - queue.setPaused(!!newState.serverMute); - } - else if (!oldState.suppress && newState.suppress) { - // state.suppress can be null - queue.setPaused(!!newState.suppress); - if (newState.suppress) { - newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop); - } - } - } - if (oldState.channelId === newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (!oldState.serverMute && newState.serverMute) { - // state.serverMute can be null - queue.setPaused(!!newState.serverMute); - } - else if (!oldState.suppress && newState.suppress) { - // state.suppress can be null - queue.setPaused(!!newState.suppress); - if (newState.suppress) { - newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop); - } - } - } - if (queue.connection && !newState.channelId && oldState.channelId === queue.connection.channel.id) { - if (!Util_1.Util.isVoiceEmpty(queue.connection.channel)) - return; - const timeout = setTimeout(() => { - if (!Util_1.Util.isVoiceEmpty(queue.connection.channel)) - return; - if (!this.queues.has(queue.guild.id)) - return; - if (queue.options.leaveOnEmpty) - queue.destroy(true); - this.emit("channelEmpty", queue); - }, queue.options.leaveOnEmptyCooldown || 0).unref(); - queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout); - } - if (queue.connection && newState.channelId && newState.channelId === queue.connection.channel.id) { - const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`); - const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel); - if (!channelEmpty && emptyTimeout) { - clearTimeout(emptyTimeout); - queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`); - } - } - if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (queue.connection && newState.member.id === newState.guild.members.me.id) - queue.connection.channel = newState.channel; - const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`); - const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel); - if (!channelEmpty && emptyTimeout) { - clearTimeout(emptyTimeout); - queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`); - } - else { - const timeout = setTimeout(() => { - if (queue.connection && !Util_1.Util.isVoiceEmpty(queue.connection.channel)) - return; - if (!this.queues.has(queue.guild.id)) - return; - if (queue.options.leaveOnEmpty) - queue.destroy(true); - this.emit("channelEmpty", queue); - }, queue.options.leaveOnEmptyCooldown || 0).unref(); - queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout); - } - } - } - /** - * Creates a queue for a guild if not available, else returns existing queue - * @param {GuildResolvable} guild The guild - * @param {PlayerOptions} queueInitOptions Queue init options - * @returns {Queue} - */ - createQueue(guild, queueInitOptions = {}) { - guild = this.client.guilds.resolve(guild); - if (!guild) - throw new PlayerError_1.PlayerError("Unknown Guild", PlayerError_1.ErrorStatusCode.UNKNOWN_GUILD); - if (this.queues.has(guild.id)) - return this.queues.get(guild.id); - const _meta = queueInitOptions.metadata; - delete queueInitOptions["metadata"]; - queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = 0.08); - const queue = new Queue_1.Queue(this, guild, queueInitOptions); - queue.metadata = _meta; - this.queues.set(guild.id, queue); - return queue; - } - /** - * Returns the queue if available - * @param {GuildResolvable} guild The guild id - * @returns {Queue} - */ - getQueue(guild) { - guild = this.client.guilds.resolve(guild); - if (!guild) - throw new PlayerError_1.PlayerError("Unknown Guild", PlayerError_1.ErrorStatusCode.UNKNOWN_GUILD); - return this.queues.get(guild.id); - } - /** - * Deletes a queue and returns deleted queue object - * @param {GuildResolvable} guild The guild id to remove - * @returns {Queue} - */ - deleteQueue(guild) { - guild = this.client.guilds.resolve(guild); - if (!guild) - throw new PlayerError_1.PlayerError("Unknown Guild", PlayerError_1.ErrorStatusCode.UNKNOWN_GUILD); - const prev = this.getQueue(guild); - try { - prev.destroy(); - } - catch { } // eslint-disable-line no-empty - this.queues.delete(guild.id); - return prev; - } - /** - * @typedef {object} PlayerSearchResult - * @property {Playlist} [playlist] The playlist (if any) - * @property {Track[]} tracks The tracks - */ - /** - * Search tracks - * @param {string|Track} query The search query - * @param {SearchOptions} options The search options - * @returns {Promise} - */ - async search(query, options) { - if (query instanceof Track_1.default) - return { playlist: query.playlist || null, tracks: [query] }; - if (!options) - throw new PlayerError_1.PlayerError("DiscordPlayer#search needs search options!", PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE); - options.requestedBy = this.client.users.resolve(options.requestedBy); - if (!("searchEngine" in options)) - options.searchEngine = types_1.QueryType.AUTO; - if (typeof options.searchEngine === "string" && this.extractors.has(options.searchEngine)) { - const extractor = this.extractors.get(options.searchEngine); - if (!extractor.validate(query)) - return { playlist: null, tracks: [] }; - const data = await extractor.handle(query); - if (data && data.data.length) { - const playlist = !data.playlist - ? null - : new Playlist_1.Playlist(this, { - ...data.playlist, - tracks: [] - }); - const tracks = data.data.map((m) => new Track_1.default(this, { - ...m, - requestedBy: options.requestedBy, - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)), - playlist: playlist - })); - if (playlist) - playlist.tracks = tracks; - return { playlist: playlist, tracks: tracks }; - } - } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - for (const [_, extractor] of this.extractors) { - if (options.blockExtractor) - break; - if (!extractor.validate(query)) - continue; - const data = await extractor.handle(query); - if (data && data.data.length) { - const playlist = !data.playlist - ? null - : new Playlist_1.Playlist(this, { - ...data.playlist, - tracks: [] - }); - const tracks = data.data.map((m) => new Track_1.default(this, { - ...m, - requestedBy: options.requestedBy, - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)), - playlist: playlist - })); - if (playlist) - playlist.tracks = tracks; - return { playlist: playlist, tracks: tracks }; - } - } - const qt = options.searchEngine === types_1.QueryType.AUTO ? await QueryResolver_1.QueryResolver.resolve(query) : options.searchEngine; - switch (qt) { - case types_1.QueryType.YOUTUBE_VIDEO: { - const info = await play_dl_1.default.video_info(query).catch(Util_1.Util.noop); - if (!info) - return { playlist: null, tracks: [] }; - const track = new Track_1.default(this, { - title: info.video_details.title, - description: info.video_details.description, - author: info.video_details.channel?.name, - url: info.video_details.url, - requestedBy: options.requestedBy, - thumbnail: Util_1.Util.last(info.video_details.thumbnails)?.url, - views: info.video_details.views || 0, - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(info.video_details.durationInSec * 1000)), - source: "youtube", - raw: info - }); - return { playlist: null, tracks: [track] }; - } - case types_1.QueryType.YOUTUBE_SEARCH: { - const videos = await play_dl_1.default.search(query, { - limit: 10, - source: { youtube: "video" } - }).catch(Util_1.Util.noop); - if (!videos) - return { playlist: null, tracks: [] }; - const tracks = videos.map(m => { - m.source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any - return new Track_1.default(this, { - title: m.title, - description: m.description, - author: m.channel?.name, - url: m.url, - requestedBy: options.requestedBy, - thumbnail: Util_1.Util.last(m.thumbnails).url, - views: m.views, - duration: m.durationRaw, - source: "youtube", - raw: m - }); - }); - return { playlist: null, tracks, searched: true }; - } - case types_1.QueryType.SOUNDCLOUD_TRACK: - case types_1.QueryType.SOUNDCLOUD_SEARCH: { - const result = await QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await play_dl_1.default.search(query, { - limit: 5, - source: { soundcloud: "tracks" } - }).catch(() => []); - if (!result || !result.length) - return { playlist: null, tracks: [] }; - const res = []; - for (const r of result) { - const trackInfo = await play_dl_1.default.soundcloud(r.url).catch(Util_1.Util.noop); - if (!trackInfo) - continue; - const track = new Track_1.default(this, { - title: trackInfo.name, - url: trackInfo.url, - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(trackInfo.durationInMs)), - description: "", - thumbnail: trackInfo.user.thumbnail, - views: 0, - author: trackInfo.user.name, - requestedBy: options.requestedBy, - source: "soundcloud", - engine: trackInfo - }); - res.push(track); - } - return { playlist: null, tracks: res }; - } - case types_1.QueryType.SPOTIFY_SONG: { - const spotifyData = await (0, spotify_url_info_1.default)(await Util_1.Util.getFetch()) - .getData(query) - .catch(Util_1.Util.noop); - if (!spotifyData) - return { playlist: null, tracks: [] }; - const spotifyTrack = new Track_1.default(this, { - title: spotifyData.name, - description: spotifyData.description ?? "", - author: spotifyData.artists[0]?.name ?? "Unknown Artist", - url: spotifyData.external_urls?.spotify ?? query, - thumbnail: spotifyData.album?.images[0]?.url ?? spotifyData.preview_url?.length - ? `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}` - : "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms)), - views: 0, - requestedBy: options.requestedBy, - source: "spotify" - }); - return { playlist: null, tracks: [spotifyTrack] }; - } - case types_1.QueryType.SPOTIFY_PLAYLIST: - case types_1.QueryType.SPOTIFY_ALBUM: { - const spotifyPlaylist = await (0, spotify_url_info_1.default)(await Util_1.Util.getFetch()) - .getData(query) - .catch(Util_1.Util.noop); - if (!spotifyPlaylist) - return { playlist: null, tracks: [] }; - const playlist = new Playlist_1.Playlist(this, { - title: spotifyPlaylist.name ?? spotifyPlaylist.title, - description: spotifyPlaylist.description ?? "", - thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - type: spotifyPlaylist.type, - source: "spotify", - author: spotifyPlaylist.type !== "playlist" - ? { - name: spotifyPlaylist.artists[0]?.name ?? "Unknown Artist", - url: spotifyPlaylist.artists[0]?.external_urls?.spotify ?? null - } - : { - name: spotifyPlaylist.owner?.display_name ?? spotifyPlaylist.owner?.id ?? "Unknown Artist", - url: spotifyPlaylist.owner?.external_urls?.spotify ?? null - }, - tracks: [], - id: spotifyPlaylist.id, - url: spotifyPlaylist.external_urls?.spotify ?? query, - rawPlaylist: spotifyPlaylist - }); - if (spotifyPlaylist.type !== "playlist") { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - playlist.tracks = spotifyPlaylist.tracks.items.map((m) => { - const data = new Track_1.default(this, { - title: m.name ?? "", - description: m.description ?? "", - author: m.artists[0]?.name ?? "Unknown Artist", - url: m.external_urls?.spotify ?? query, - thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration_ms)), - views: 0, - requestedBy: options.requestedBy, - playlist, - source: "spotify" - }); - return data; - }); - } - else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - playlist.tracks = spotifyPlaylist.tracks.items.map((m) => { - const data = new Track_1.default(this, { - title: m.track.name ?? "", - description: m.track.description ?? "", - author: m.track.artists?.[0]?.name ?? "Unknown Artist", - url: m.track.external_urls?.spotify ?? query, - thumbnail: m.track.album?.images?.[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.track.duration_ms)), - views: 0, - requestedBy: options.requestedBy, - playlist, - source: "spotify" - }); - return data; - }); - } - return { playlist: playlist, tracks: playlist.tracks }; - } - case types_1.QueryType.SOUNDCLOUD_PLAYLIST: { - const data = await play_dl_1.default.soundcloud(query).catch(Util_1.Util.noop); - if (!data) - return { playlist: null, tracks: [] }; - const res = new Playlist_1.Playlist(this, { - title: data.name, - description: "", - thumbnail: "https://soundcloud.com/pwa-icon-192.png", - type: "playlist", - source: "soundcloud", - author: { - name: data.user.name ?? "Unknown Owner", - url: data.user.url - }, - tracks: [], - id: `${data.id}`, - url: data.url, - rawPlaylist: data - }); - const songs = await data.all_tracks(); - for (const song of songs) { - const track = new Track_1.default(this, { - title: song.name, - description: "", - author: song.publisher.name ?? "Unknown Publisher", - url: song.url, - thumbnail: song.thumbnail, - duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(song.durationInMs)), - views: 0, - requestedBy: options.requestedBy, - playlist: res, - source: "soundcloud", - engine: song - }); - res.tracks.push(track); - } - return { playlist: res, tracks: res.tracks }; - } - case types_1.QueryType.YOUTUBE_PLAYLIST: { - const ytpl = await play_dl_1.default.playlist_info(query, { incomplete: true }).catch(Util_1.Util.noop); - if (!ytpl) - return { playlist: null, tracks: [] }; - const playlist = new Playlist_1.Playlist(this, { - title: ytpl.title, - thumbnail: ytpl.thumbnail, - description: "", - type: "playlist", - source: "youtube", - author: { - name: ytpl.channel.name, - url: ytpl.channel.url - }, - tracks: [], - id: ytpl.id, - url: ytpl.url, - rawPlaylist: ytpl - }); - const videos = await ytpl.all_videos(); - playlist.tracks = videos.map(video => new Track_1.default(this, { - title: video.title, - description: video.description, - author: video.channel?.name, - url: video.url, - requestedBy: options.requestedBy, - thumbnail: Util_1.Util.last(video.thumbnails).url, - views: video.views, - duration: video.durationRaw, - raw: video, - playlist: playlist, - source: "youtube" - })); - return { playlist: playlist, tracks: playlist.tracks }; - } - default: - return { playlist: null, tracks: [] }; - } - } - /** - * Registers extractor - * @param {string} extractorName The extractor name - * @param {ExtractorModel|any} extractor The extractor object - * @param {boolean} [force=false] Overwrite existing extractor with this name (if available) - * @returns {ExtractorModel} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - use(extractorName, extractor, force = false) { - if (!extractorName) - throw new PlayerError_1.PlayerError("Cannot use unknown extractor!", PlayerError_1.ErrorStatusCode.UNKNOWN_EXTRACTOR); - if (this.extractors.has(extractorName) && !force) - return this.extractors.get(extractorName); - if (extractor instanceof ExtractorModel_1.ExtractorModel) { - this.extractors.set(extractorName, extractor); - return extractor; - } - for (const method of ["validate", "getInfo"]) { - if (typeof extractor[method] !== "function") - throw new PlayerError_1.PlayerError("Invalid extractor data!", PlayerError_1.ErrorStatusCode.INVALID_EXTRACTOR); - } - const model = new ExtractorModel_1.ExtractorModel(extractorName, extractor); - this.extractors.set(model.name, model); - return model; - } - /** - * Removes registered extractor - * @param {string} extractorName The extractor name - * @returns {ExtractorModel} - */ - unuse(extractorName) { - if (!this.extractors.has(extractorName)) - throw new PlayerError_1.PlayerError(`Cannot find extractor "${extractorName}"`, PlayerError_1.ErrorStatusCode.UNKNOWN_EXTRACTOR); - const prev = this.extractors.get(extractorName); - this.extractors.delete(extractorName); - return prev; - } - /** - * Generates a report of the dependencies used by the `@discordjs/voice` module. Useful for debugging. - * @returns {string} - */ - scanDeps() { - const line = "-".repeat(50); - const depsReport = (0, voice_1.generateDependencyReport)(); - const extractorReport = this.extractors - .map((m) => { - return `${m.name} :: ${m.version || "0.1.0"}`; - }) - .join("\n"); - return `${depsReport}\n${line}\nLoaded Extractors:\n${extractorReport || "None"}`; - } - emit(eventName, ...args) { - if (this.requiredEvents.includes(eventName) && !super.eventNames().includes(eventName)) { - // eslint-disable-next-line no-console - console.error(...args); - process.emitWarning(`[DiscordPlayerWarning] Unhandled "${eventName}" event! Events ${this.requiredEvents.map((m) => `"${m}"`).join(", ")} must have event listeners!`); - return false; - } - else { - return super.emit(eventName, ...args); - } - } - /** - * Resolves queue - * @param {GuildResolvable|Queue} queueLike Queue like object - * @returns {Queue} - */ - resolveQueue(queueLike) { - return this.getQueue(queueLike instanceof Queue_1.Queue ? queueLike.guild : queueLike); - } - *[Symbol.iterator]() { - yield* Array.from(this.queues.values()); - } - /** - * Creates `Playlist` instance - * @param data The data to initialize a playlist - */ - createPlaylist(data) { - return new Playlist_1.Playlist(this, data); - } -} -exports.Player = Player; diff --git a/helpers/Music/dist/Structures/ExtractorModel.d.ts b/helpers/Music/dist/Structures/ExtractorModel.d.ts deleted file mode 100644 index 27938306..00000000 --- a/helpers/Music/dist/Structures/ExtractorModel.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { ExtractorModelData } from "../types/types"; -declare class ExtractorModel { - name: string; - private _raw; - /** - * Model for raw Discord Player extractors - * @param {string} extractorName Name of the extractor - * @param {object} data Extractor object - */ - constructor(extractorName: string, data: any); - /** - * Method to handle requests from `Player.play()` - * @param {string} query Query to handle - * @returns {Promise} - */ - handle(query: string): Promise; - /** - * Method used by Discord Player to validate query with this extractor - * @param {string} query The query to validate - * @returns {boolean} - */ - validate(query: string): boolean; - /** - * The extractor version - * @type {string} - */ - get version(): string; -} -export { ExtractorModel }; diff --git a/helpers/Music/dist/Structures/ExtractorModel.js b/helpers/Music/dist/Structures/ExtractorModel.js deleted file mode 100644 index 253ddc8d..00000000 --- a/helpers/Music/dist/Structures/ExtractorModel.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ExtractorModel = void 0; -class ExtractorModel { - /** - * Model for raw Discord Player extractors - * @param {string} extractorName Name of the extractor - * @param {object} data Extractor object - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - constructor(extractorName, data) { - /** - * The extractor name - * @type {string} - */ - this.name = extractorName; - /** - * The raw model - * @name ExtractorModel#_raw - * @type {any} - * @private - */ - Object.defineProperty(this, "_raw", { value: data, configurable: false, writable: false, enumerable: false }); - } - /** - * Method to handle requests from `Player.play()` - * @param {string} query Query to handle - * @returns {Promise} - */ - async handle(query) { - const data = await this._raw.getInfo(query); - if (!data) - return null; - return { - playlist: data.playlist ?? null, - data: data.info?.map((m) => ({ - title: m.title, - duration: m.duration, - thumbnail: m.thumbnail, - engine: m.engine, - views: m.views, - author: m.author, - description: m.description, - url: m.url, - source: m.source || "arbitrary" - })) ?? [] - }; - } - /** - * Method used by Discord Player to validate query with this extractor - * @param {string} query The query to validate - * @returns {boolean} - */ - validate(query) { - return Boolean(this._raw.validate(query)); - } - /** - * The extractor version - * @type {string} - */ - get version() { - return this._raw.version ?? "0.0.0"; - } -} -exports.ExtractorModel = ExtractorModel; diff --git a/helpers/Music/dist/Structures/PlayerError.d.ts b/helpers/Music/dist/Structures/PlayerError.d.ts deleted file mode 100644 index fcd61a5e..00000000 --- a/helpers/Music/dist/Structures/PlayerError.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -export declare enum ErrorStatusCode { - STREAM_ERROR = "StreamError", - AUDIO_PLAYER_ERROR = "AudioPlayerError", - PLAYER_ERROR = "PlayerError", - NO_AUDIO_RESOURCE = "NoAudioResource", - UNKNOWN_GUILD = "UnknownGuild", - INVALID_ARG_TYPE = "InvalidArgType", - UNKNOWN_EXTRACTOR = "UnknownExtractor", - INVALID_EXTRACTOR = "InvalidExtractor", - INVALID_CHANNEL_TYPE = "InvalidChannelType", - INVALID_TRACK = "InvalidTrack", - UNKNOWN_REPEAT_MODE = "UnknownRepeatMode", - TRACK_NOT_FOUND = "TrackNotFound", - NO_CONNECTION = "NoConnection", - DESTROYED_QUEUE = "DestroyedQueue" -} -export declare class PlayerError extends Error { - message: string; - statusCode: ErrorStatusCode; - createdAt: Date; - constructor(message: string, code?: ErrorStatusCode); - get createdTimestamp(): number; - valueOf(): ErrorStatusCode; - toJSON(): { - stack: string; - code: ErrorStatusCode; - message: string; - created: number; - }; - toString(): string; -} diff --git a/helpers/Music/dist/Structures/PlayerError.js b/helpers/Music/dist/Structures/PlayerError.js deleted file mode 100644 index e65aeb65..00000000 --- a/helpers/Music/dist/Structures/PlayerError.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PlayerError = exports.ErrorStatusCode = void 0; -var ErrorStatusCode; -(function (ErrorStatusCode) { - ErrorStatusCode["STREAM_ERROR"] = "StreamError"; - ErrorStatusCode["AUDIO_PLAYER_ERROR"] = "AudioPlayerError"; - ErrorStatusCode["PLAYER_ERROR"] = "PlayerError"; - ErrorStatusCode["NO_AUDIO_RESOURCE"] = "NoAudioResource"; - ErrorStatusCode["UNKNOWN_GUILD"] = "UnknownGuild"; - ErrorStatusCode["INVALID_ARG_TYPE"] = "InvalidArgType"; - ErrorStatusCode["UNKNOWN_EXTRACTOR"] = "UnknownExtractor"; - ErrorStatusCode["INVALID_EXTRACTOR"] = "InvalidExtractor"; - ErrorStatusCode["INVALID_CHANNEL_TYPE"] = "InvalidChannelType"; - ErrorStatusCode["INVALID_TRACK"] = "InvalidTrack"; - ErrorStatusCode["UNKNOWN_REPEAT_MODE"] = "UnknownRepeatMode"; - ErrorStatusCode["TRACK_NOT_FOUND"] = "TrackNotFound"; - ErrorStatusCode["NO_CONNECTION"] = "NoConnection"; - ErrorStatusCode["DESTROYED_QUEUE"] = "DestroyedQueue"; -})(ErrorStatusCode = exports.ErrorStatusCode || (exports.ErrorStatusCode = {})); -class PlayerError extends Error { - constructor(message, code = ErrorStatusCode.PLAYER_ERROR) { - super(); - this.createdAt = new Date(); - this.message = `[${code}] ${message}`; - this.statusCode = code; - this.name = code; - Error.captureStackTrace(this); - } - get createdTimestamp() { - return this.createdAt.getTime(); - } - valueOf() { - return this.statusCode; - } - toJSON() { - return { - stack: this.stack, - code: this.statusCode, - message: this.message, - created: this.createdTimestamp - }; - } - toString() { - return this.stack; - } -} -exports.PlayerError = PlayerError; diff --git a/helpers/Music/dist/Structures/Playlist.d.ts b/helpers/Music/dist/Structures/Playlist.d.ts deleted file mode 100644 index ff144b80..00000000 --- a/helpers/Music/dist/Structures/Playlist.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Player } from "../Player"; -import { Track } from "./Track"; -import { PlaylistInitData, PlaylistJSON, TrackSource } from "../types/types"; -declare class Playlist { - readonly player: Player; - tracks: Track[]; - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - id: string; - url: string; - readonly rawPlaylist?: any; - /** - * Playlist constructor - * @param {Player} player The player - * @param {PlaylistInitData} data The data - */ - constructor(player: Player, data: PlaylistInitData); - [Symbol.iterator](): Generator; - /** - * JSON representation of this playlist - * @param {boolean} [withTracks=true] If it should build json with tracks - * @returns {PlaylistJSON} - */ - toJSON(withTracks?: boolean): PlaylistJSON; -} -export { Playlist }; diff --git a/helpers/Music/dist/Structures/Playlist.js b/helpers/Music/dist/Structures/Playlist.js deleted file mode 100644 index f86629a6..00000000 --- a/helpers/Music/dist/Structures/Playlist.js +++ /dev/null @@ -1,108 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Playlist = void 0; -class Playlist { - /** - * Playlist constructor - * @param {Player} player The player - * @param {PlaylistInitData} data The data - */ - constructor(player, data) { - /** - * The player - * @name Playlist#player - * @type {Player} - * @readonly - */ - this.player = player; - /** - * The tracks in this playlist - * @name Playlist#tracks - * @type {Track[]} - */ - this.tracks = data.tracks ?? []; - /** - * The author of this playlist - * @name Playlist#author - * @type {object} - */ - this.author = data.author; - /** - * The description - * @name Playlist#description - * @type {string} - */ - this.description = data.description; - /** - * The thumbnail of this playlist - * @name Playlist#thumbnail - * @type {string} - */ - this.thumbnail = data.thumbnail; - /** - * The playlist type: - * - `album` - * - `playlist` - * @name Playlist#type - * @type {string} - */ - this.type = data.type; - /** - * The source of this playlist: - * - `youtube` - * - `soundcloud` - * - `spotify` - * - `arbitrary` - * @name Playlist#source - * @type {string} - */ - this.source = data.source; - /** - * The playlist id - * @name Playlist#id - * @type {string} - */ - this.id = data.id; - /** - * The playlist url - * @name Playlist#url - * @type {string} - */ - this.url = data.url; - /** - * The playlist title - * @type {string} - */ - this.title = data.title; - /** - * @name Playlist#rawPlaylist - * @type {any} - * @readonly - */ - } - *[Symbol.iterator]() { - yield* this.tracks; - } - /** - * JSON representation of this playlist - * @param {boolean} [withTracks=true] If it should build json with tracks - * @returns {PlaylistJSON} - */ - toJSON(withTracks = true) { - const payload = { - id: this.id, - url: this.url, - title: this.title, - description: this.description, - thumbnail: this.thumbnail, - type: this.type, - source: this.source, - author: this.author, - tracks: [] - }; - if (withTracks) - payload.tracks = this.tracks.map((m) => m.toJSON(true)); - return payload; - } -} -exports.Playlist = Playlist; diff --git a/helpers/Music/dist/Structures/Queue.d.ts b/helpers/Music/dist/Structures/Queue.d.ts deleted file mode 100644 index fa21c4c8..00000000 --- a/helpers/Music/dist/Structures/Queue.d.ts +++ /dev/null @@ -1,241 +0,0 @@ -/// -/// -import { Collection, Guild, GuildChannelResolvable } from "discord.js"; -import { Player } from "../Player"; -import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher"; -import Track from "./Track"; -import { PlayerOptions, PlayerProgressbarOptions, PlayOptions, QueueFilters, QueueRepeatMode, TrackSource } from "../types/types"; -import type { Readable } from "stream"; -declare class Queue { - #private; - readonly guild: Guild; - readonly player: Player; - connection: StreamDispatcher; - tracks: Track[]; - previousTracks: Track[]; - options: PlayerOptions; - playing: boolean; - metadata?: T; - repeatMode: QueueRepeatMode; - readonly id: string; - private _streamTime; - _cooldownsTimeout: Collection; - private _activeFilters; - private _filtersUpdate; - onBeforeCreateStream: (track: Track, source: TrackSource, queue: Queue) => Promise; - /** - * Queue constructor - * @param {Player} player The player that instantiated this queue - * @param {Guild} guild The guild that instantiated this queue - * @param {PlayerOptions} [options] Player options for the queue - */ - constructor(player: Player, guild: Guild, options?: PlayerOptions); - /** - * Returns current track - * @type {Track} - */ - get current(): Track; - /** - * If this queue is destroyed - * @type {boolean} - */ - get destroyed(): boolean; - /** - * Returns current track - * @returns {Track} - */ - nowPlaying(): Track; - /** - * Connects to a voice channel - * @param {GuildChannelResolvable} channel The voice/stage channel - * @returns {Promise} - */ - connect(channel: GuildChannelResolvable): Promise; - /** - * Destroys this queue - * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy - * @returns {void} - */ - destroy(disconnect?: boolean): void; - /** - * Skips current track - * @returns {boolean} - */ - skip(): boolean; - /** - * Adds single track to the queue - * @param {Track} track The track to add - * @returns {void} - */ - addTrack(track: Track): void; - /** - * Adds multiple tracks to the queue - * @param {Track[]} tracks Array of tracks to add - */ - addTracks(tracks: Track[]): void; - /** - * Sets paused state - * @param {boolean} paused The paused state - * @returns {boolean} - */ - setPaused(paused?: boolean): boolean; - /** - * Sets bitrate - * @param {number|auto} bitrate bitrate to set - * @returns {void} - */ - setBitrate(bitrate: number | "auto"): void; - /** - * Sets volume - * @param {number} amount The volume amount - * @returns {boolean} - */ - setVolume(amount: number): boolean; - /** - * Sets repeat mode - * @param {QueueRepeatMode} mode The repeat mode - * @returns {boolean} - */ - setRepeatMode(mode: QueueRepeatMode): boolean; - /** - * The current volume amount - * @type {number} - */ - get volume(): number; - set volume(amount: number); - /** - * The stream time of this queue - * @type {number} - */ - get streamTime(): number; - set streamTime(time: number); - /** - * Returns enabled filters - * @returns {AudioFilters} - */ - getFiltersEnabled(): (keyof QueueFilters)[]; - /** - * Returns disabled filters - * @returns {AudioFilters} - */ - getFiltersDisabled(): (keyof QueueFilters)[]; - /** - * Sets filters - * @param {QueueFilters} filters Queue filters - * @returns {Promise} - */ - setFilters(filters?: QueueFilters): Promise; - /** - * Seeks to the given time - * @param {number} position The position - * @returns {boolean} - */ - seek(position: number): Promise; - /** - * Plays previous track - * @returns {Promise} - */ - back(): Promise; - /** - * Clear this queue - */ - clear(): void; - /** - * Stops the player - * @returns {void} - */ - stop(): void; - /** - * Shuffles this queue - * @returns {boolean} - */ - shuffle(): boolean; - /** - * Removes a track from the queue - * @param {Track|string|number} track The track to remove - * @returns {Track} - */ - remove(track: Track | string | number): Track; - /** - * Returns the index of the specified track. If found, returns the track index else returns -1. - * @param {number|Track|string} track The track - * @returns {number} - */ - getTrackPosition(track: number | Track | string): number; - /** - * Jumps to particular track - * @param {Track|number} track The track - * @returns {void} - */ - jump(track: Track | number): void; - /** - * Jumps to particular track, removing other tracks on the way - * @param {Track|number} track The track - * @returns {void} - */ - skipTo(track: Track | number): void; - /** - * Inserts the given track to specified index - * @param {Track} track The track to insert - * @param {number} [index=0] The index where this track should be - */ - insert(track: Track, index?: number): void; - /** - * @typedef {object} PlayerTimestamp - * @property {string} current The current progress - * @property {string} end The total time - * @property {number} progress Progress in % - */ - /** - * Returns player stream timestamp - * @returns {PlayerTimestamp} - */ - getPlayerTimestamp(): { - current: string; - end: string; - progress: number; - }; - /** - * Creates progress bar string - * @param {PlayerProgressbarOptions} options The progress bar options - * @returns {string} - */ - createProgressBar(options?: PlayerProgressbarOptions): string; - /** - * Total duration - * @type {Number} - */ - get totalTime(): number; - /** - * Play stream in a voice/stage channel - * @param {Track} [src] The track to play (if empty, uses first track from the queue) - * @param {PlayOptions} [options] The options - * @returns {Promise} - */ - play(src?: Track, options?: PlayOptions): Promise; - /** - * Private method to handle autoplay - * @param {Track} track The source track to find its similar track for autoplay - * @returns {Promise} - * @private - */ - private _handleAutoplay; - [Symbol.iterator](): Generator; - /** - * JSON representation of this queue - * @returns {object} - */ - toJSON(): { - id: string; - guild: string; - voiceChannel: string; - options: PlayerOptions; - tracks: import("../types/types").TrackJSON[]; - }; - /** - * String representation of this queue - * @returns {string} - */ - toString(): string; -} -export { Queue }; diff --git a/helpers/Music/dist/Structures/Queue.js b/helpers/Music/dist/Structures/Queue.js deleted file mode 100644 index f4f342ac..00000000 --- a/helpers/Music/dist/Structures/Queue.js +++ /dev/null @@ -1,761 +0,0 @@ -"use strict"; -var _Queue_instances, _Queue_lastVolume, _Queue_destroyed, _Queue_watchDestroyed, _Queue_getBufferingTimeout; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Queue = void 0; -const tslib_1 = require("tslib"); -const discord_js_1 = require("discord.js"); -const Track_1 = tslib_1.__importDefault(require("./Track")); -const types_1 = require("../types/types"); -const voice_1 = require("@discordjs/voice"); -const play_dl_1 = tslib_1.__importDefault(require("play-dl")); -const Util_1 = require("../utils/Util"); -const AudioFilters_1 = tslib_1.__importDefault(require("../utils/AudioFilters")); -const PlayerError_1 = require("./PlayerError"); -const FFmpegStream_1 = require("../utils/FFmpegStream"); -class Queue { - /** - * Queue constructor - * @param {Player} player The player that instantiated this queue - * @param {Guild} guild The guild that instantiated this queue - * @param {PlayerOptions} [options] Player options for the queue - */ - constructor(player, guild, options = {}) { - _Queue_instances.add(this); - this.tracks = []; - this.previousTracks = []; - this.playing = false; - this.metadata = null; - this.repeatMode = 0; - this.id = discord_js_1.SnowflakeUtil.generate().toString(); - this._streamTime = 0; - this._cooldownsTimeout = new discord_js_1.Collection(); - this._activeFilters = []; // eslint-disable-line @typescript-eslint/no-explicit-any - this._filtersUpdate = false; - _Queue_lastVolume.set(this, 0); - _Queue_destroyed.set(this, false); - this.onBeforeCreateStream = null; - /** - * The player that instantiated this queue - * @type {Player} - * @readonly - */ - this.player = player; - /** - * The guild that instantiated this queue - * @type {Guild} - * @readonly - */ - this.guild = guild; - /** - * The player options for this queue - * @type {PlayerOptions} - */ - this.options = {}; - /** - * Queue repeat mode - * @type {QueueRepeatMode} - * @name Queue#repeatMode - */ - /** - * Queue metadata - * @type {any} - * @name Queue#metadata - */ - /** - * Previous tracks - * @type {Track[]} - * @name Queue#previousTracks - */ - /** - * Regular tracks - * @type {Track[]} - * @name Queue#tracks - */ - /** - * The connection - * @type {StreamDispatcher} - * @name Queue#connection - */ - /** - * The ID of this queue - * @type {Snowflake} - * @name Queue#id - */ - Object.assign(this.options, { - leaveOnEnd: true, - leaveOnStop: true, - leaveOnEmpty: true, - leaveOnEmptyCooldown: 1000, - autoSelfDeaf: true, - ytdlOptions: { - highWaterMark: 1 << 25 - }, - initialVolume: 100, - bufferingTimeout: 3000, - spotifyBridge: true, - disableVolume: false - }, options); - if ("onBeforeCreateStream" in this.options) - this.onBeforeCreateStream = this.options.onBeforeCreateStream; - this.player.emit("debug", this, `Queue initialized:\n\n${this.player.scanDeps()}`); - } - /** - * Returns current track - * @type {Track} - */ - get current() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return this.connection.audioResource?.metadata ?? this.tracks[0]; - } - /** - * If this queue is destroyed - * @type {boolean} - */ - get destroyed() { - return tslib_1.__classPrivateFieldGet(this, _Queue_destroyed, "f"); - } - /** - * Returns current track - * @returns {Track} - */ - nowPlaying() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return this.current; - } - /** - * Connects to a voice channel - * @param {GuildChannelResolvable} channel The voice/stage channel - * @returns {Promise} - */ - async connect(channel) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const _channel = this.guild.channels.resolve(channel); - if (![discord_js_1.ChannelType.GuildStageVoice, discord_js_1.ChannelType.GuildVoice].includes(_channel?.type)) - throw new PlayerError_1.PlayerError(`Channel type must be GuildVoice or GuildStageVoice, got ${_channel?.type}!`, PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE); - const connection = await this.player.voiceUtils.connect(_channel, { - deaf: this.options.autoSelfDeaf - }); - this.connection = connection; - if (_channel.type === discord_js_1.ChannelType.GuildStageVoice) { - await _channel.guild.members.me.voice.setSuppressed(false).catch(async () => { - return await _channel.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop); - }); - } - this.connection.on("error", (err) => { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false)) - return; - this.player.emit("connectionError", this, err); - }); - this.connection.on("debug", (msg) => { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false)) - return; - this.player.emit("debug", this, msg); - }); - this.player.emit("connectionCreate", this, this.connection); - this.connection.on("start", (resource) => { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false)) - return; - this.playing = true; - if (!this._filtersUpdate) - this.player.emit("trackStart", this, resource?.metadata ?? this.current); - this._filtersUpdate = false; - }); - this.connection.on("finish", async (resource) => { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false)) - return; - this.playing = false; - if (this._filtersUpdate) - return; - this._streamTime = 0; - if (resource?.metadata) - this.previousTracks.push(resource.metadata); - this.player.emit("trackEnd", this, resource.metadata); - if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) { - if (this.options.leaveOnEnd) - this.destroy(); - this.player.emit("queueEnd", this); - } - else if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.AUTOPLAY) { - this._handleAutoplay(Util_1.Util.last(this.previousTracks)); - } - else { - if (this.repeatMode === types_1.QueueRepeatMode.TRACK) - return void this.play(Util_1.Util.last(this.previousTracks), { immediate: true }); - if (this.repeatMode === types_1.QueueRepeatMode.QUEUE) - this.tracks.push(Util_1.Util.last(this.previousTracks)); - const nextTrack = this.tracks.shift(); - this.play(nextTrack, { immediate: true }); - return; - } - }); - return this; - } - /** - * Destroys this queue - * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy - * @returns {void} - */ - destroy(disconnect = this.options.leaveOnStop) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (this.connection) - this.connection.end(); - if (disconnect) - this.connection?.disconnect(); - this.player.queues.delete(this.guild.id); - this.player.voiceUtils.cache.delete(this.guild.id); - tslib_1.__classPrivateFieldSet(this, _Queue_destroyed, true, "f"); - } - /** - * Skips current track - * @returns {boolean} - */ - skip() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection) - return false; - this._filtersUpdate = false; - this.connection.end(); - return true; - } - /** - * Adds single track to the queue - * @param {Track} track The track to add - * @returns {void} - */ - addTrack(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!(track instanceof Track_1.default)) - throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK); - this.tracks.push(track); - this.player.emit("trackAdd", this, track); - } - /** - * Adds multiple tracks to the queue - * @param {Track[]} tracks Array of tracks to add - */ - addTracks(tracks) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!tracks.every((y) => y instanceof Track_1.default)) - throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK); - this.tracks.push(...tracks); - this.player.emit("tracksAdd", this, tracks); - } - /** - * Sets paused state - * @param {boolean} paused The paused state - * @returns {boolean} - */ - setPaused(paused) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection) - return false; - return paused ? this.connection.pause(true) : this.connection.resume(); - } - /** - * Sets bitrate - * @param {number|auto} bitrate bitrate to set - * @returns {void} - */ - setBitrate(bitrate) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection?.audioResource?.encoder) - return; - if (bitrate === "auto") - bitrate = this.connection.channel?.bitrate ?? 64000; - this.connection.audioResource.encoder.setBitrate(bitrate); - } - /** - * Sets volume - * @param {number} amount The volume amount - * @returns {boolean} - */ - setVolume(amount) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection) - return false; - tslib_1.__classPrivateFieldSet(this, _Queue_lastVolume, amount, "f"); - this.options.initialVolume = amount; - return this.connection.setVolume(amount); - } - /** - * Sets repeat mode - * @param {QueueRepeatMode} mode The repeat mode - * @returns {boolean} - */ - setRepeatMode(mode) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (![types_1.QueueRepeatMode.OFF, types_1.QueueRepeatMode.QUEUE, types_1.QueueRepeatMode.TRACK, types_1.QueueRepeatMode.AUTOPLAY].includes(mode)) - throw new PlayerError_1.PlayerError(`Unknown repeat mode "${mode}"!`, PlayerError_1.ErrorStatusCode.UNKNOWN_REPEAT_MODE); - if (mode === this.repeatMode) - return false; - this.repeatMode = mode; - return true; - } - /** - * The current volume amount - * @type {number} - */ - get volume() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection) - return 100; - return this.connection.volume; - } - set volume(amount) { - this.setVolume(amount); - } - /** - * The stream time of this queue - * @type {number} - */ - get streamTime() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.connection) - return 0; - const playbackTime = this._streamTime + this.connection.streamTime; - const NC = this._activeFilters.includes("nightcore") ? 1.25 : null; - const VW = this._activeFilters.includes("vaporwave") ? 0.8 : null; - if (NC && VW) - return playbackTime * (NC + VW); - return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime; - } - set streamTime(time) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - this.seek(time); - } - /** - * Returns enabled filters - * @returns {AudioFilters} - */ - getFiltersEnabled() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return AudioFilters_1.default.names.filter((x) => this._activeFilters.includes(x)); - } - /** - * Returns disabled filters - * @returns {AudioFilters} - */ - getFiltersDisabled() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return AudioFilters_1.default.names.filter((x) => !this._activeFilters.includes(x)); - } - /** - * Sets filters - * @param {QueueFilters} filters Queue filters - * @returns {Promise} - */ - async setFilters(filters) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!filters || !Object.keys(filters).length) { - // reset filters - const streamTime = this.streamTime; - this._activeFilters = []; - return await this.play(this.current, { - immediate: true, - filtersUpdate: true, - seek: streamTime, - encoderArgs: [] - }); - } - const _filters = []; // eslint-disable-line @typescript-eslint/no-explicit-any - for (const filter in filters) { - if (filters[filter] === true) - _filters.push(filter); - } - if (this._activeFilters.join("") === _filters.join("")) - return; - const newFilters = AudioFilters_1.default.create(_filters).trim(); - const streamTime = this.streamTime; - this._activeFilters = _filters; - return await this.play(this.current, { - immediate: true, - filtersUpdate: true, - seek: streamTime, - encoderArgs: !_filters.length ? undefined : ["-af", newFilters] - }); - } - /** - * Seeks to the given time - * @param {number} position The position - * @returns {boolean} - */ - async seek(position) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.playing || !this.current) - return false; - if (position < 1) - position = 0; - if (position >= this.current.durationMS) - return this.skip(); - await this.play(this.current, { - immediate: true, - filtersUpdate: true, - seek: position - }); - return true; - } - /** - * Plays previous track - * @returns {Promise} - */ - async back() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const prev = this.previousTracks[this.previousTracks.length - 2]; // because last item is the current track - if (!prev) - throw new PlayerError_1.PlayerError("Could not find previous track", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND); - return await this.play(prev, { immediate: true }); - } - /** - * Clear this queue - */ - clear() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - this.tracks = []; - this.previousTracks = []; - } - /** - * Stops the player - * @returns {void} - */ - stop() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return this.destroy(); - } - /** - * Shuffles this queue - * @returns {boolean} - */ - shuffle() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.tracks.length || this.tracks.length < 2) - return false; - for (let i = this.tracks.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]]; - } - return true; - } - /** - * Removes a track from the queue - * @param {Track|string|number} track The track to remove - * @returns {Track} - */ - remove(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - let trackFound = null; - if (typeof track === "number") { - trackFound = this.tracks[track]; - if (trackFound) { - this.tracks = this.tracks.filter((t) => t.id !== trackFound.id); - } - } - else { - trackFound = this.tracks.find((s) => s.id === (track instanceof Track_1.default ? track.id : track)); - if (trackFound) { - this.tracks = this.tracks.filter((s) => s.id !== trackFound.id); - } - } - return trackFound; - } - /** - * Returns the index of the specified track. If found, returns the track index else returns -1. - * @param {number|Track|string} track The track - * @returns {number} - */ - getTrackPosition(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (typeof track === "number") - return this.tracks[track] != null ? track : -1; - return this.tracks.findIndex((pred) => pred.id === (track instanceof Track_1.default ? track.id : track)); - } - /** - * Jumps to particular track - * @param {Track|number} track The track - * @returns {void} - */ - jump(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const foundTrack = this.remove(track); - if (!foundTrack) - throw new PlayerError_1.PlayerError("Track not found", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND); - this.tracks.splice(0, 0, foundTrack); - return void this.skip(); - } - /** - * Jumps to particular track, removing other tracks on the way - * @param {Track|number} track The track - * @returns {void} - */ - skipTo(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const trackIndex = this.getTrackPosition(track); - const removedTrack = this.remove(track); - if (!removedTrack) - throw new PlayerError_1.PlayerError("Track not found", PlayerError_1.ErrorStatusCode.TRACK_NOT_FOUND); - this.tracks.splice(0, trackIndex, removedTrack); - return void this.skip(); - } - /** - * Inserts the given track to specified index - * @param {Track} track The track to insert - * @param {number} [index=0] The index where this track should be - */ - insert(track, index = 0) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!track || !(track instanceof Track_1.default)) - throw new PlayerError_1.PlayerError("track must be the instance of Track", PlayerError_1.ErrorStatusCode.INVALID_TRACK); - if (typeof index !== "number" || index < 0 || !Number.isFinite(index)) - throw new PlayerError_1.PlayerError(`Invalid index "${index}"`, PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE); - this.tracks.splice(index, 0, track); - this.player.emit("trackAdd", this, track); - } - /** - * @typedef {object} PlayerTimestamp - * @property {string} current The current progress - * @property {string} end The total time - * @property {number} progress Progress in % - */ - /** - * Returns player stream timestamp - * @returns {PlayerTimestamp} - */ - getPlayerTimestamp() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const currentStreamTime = this.streamTime; - const totalTime = this.current.durationMS; - const currentTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(currentStreamTime)); - const endTimecode = Util_1.Util.buildTimeCode(Util_1.Util.parseMS(totalTime)); - return { - current: currentTimecode, - end: endTimecode, - progress: Math.round((currentStreamTime / totalTime) * 100) - }; - } - /** - * Creates progress bar string - * @param {PlayerProgressbarOptions} options The progress bar options - * @returns {string} - */ - createProgressBar(options = { timecodes: true }) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - const length = typeof options.length === "number" ? (options.length <= 0 || options.length === Infinity ? 15 : options.length) : 15; - const index = Math.round((this.streamTime / this.current.durationMS) * length); - const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "🔘"; - const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "▬"; - if (index >= 1 && index <= length) { - const bar = line.repeat(length - 1).split(""); - bar.splice(index, 0, indicator); - if (options.timecodes) { - const timestamp = this.getPlayerTimestamp(); - return `${timestamp.current} ┃ ${bar.join("")} ┃ ${timestamp.end}`; - } - else { - return `${bar.join("")}`; - } - } - else { - if (options.timecodes) { - const timestamp = this.getPlayerTimestamp(); - return `${timestamp.current} ┃ ${indicator}${line.repeat(length - 1)} ┃ ${timestamp.end}`; - } - else { - return `${indicator}${line.repeat(length - 1)}`; - } - } - } - /** - * Total duration - * @type {Number} - */ - get totalTime() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0; - } - /** - * Play stream in a voice/stage channel - * @param {Track} [src] The track to play (if empty, uses first track from the queue) - * @param {PlayOptions} [options] The options - * @returns {Promise} - */ - async play(src, options = {}) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this, false)) - return; - if (!this.connection || !this.connection.voiceConnection) - throw new PlayerError_1.PlayerError("Voice connection is not available, use .connect()!", PlayerError_1.ErrorStatusCode.NO_CONNECTION); - if (src && (this.playing || this.tracks.length) && !options.immediate) - return this.addTrack(src); - const track = options.filtersUpdate && !options.immediate ? src || this.current : src ?? this.tracks.shift(); - if (!track) - return; - this.player.emit("debug", this, "Received play request"); - if (!options.filtersUpdate) { - this.previousTracks = this.previousTracks.filter((x) => x.id !== track.id); - this.previousTracks.push(track); - } - let stream = null; - const hasCustomDownloader = typeof this.onBeforeCreateStream === "function"; - if (["youtube", "spotify"].includes(track.raw.source)) { - let spotifyResolved = false; - if (this.options.spotifyBridge && track.raw.source === "spotify" && !track.raw.engine) { - track.raw.engine = await play_dl_1.default.search(`${track.author} ${track.title}`, { source: { youtube: "video" } }) - .then(res => res[0].url) - .catch(() => null); - spotifyResolved = true; - } - const url = track.raw.source === "spotify" ? track.raw.engine : track.url; - if (!url) - return void this.play(this.tracks.shift(), { immediate: true }); - if (hasCustomDownloader) { - stream = (await this.onBeforeCreateStream(track, spotifyResolved ? "youtube" : track.raw.source, this)) || null; - } - if (!stream) { - stream = (await play_dl_1.default.stream(url, { discordPlayerCompatibility: true })).stream; - } - } - else { - const arbitraryStream = (hasCustomDownloader && (await this.onBeforeCreateStream(track, track.raw.source || track.raw.engine, this))) || null; - stream = - arbitraryStream || (track.raw.source === "soundcloud" && typeof track.raw.engine?.downloadProgressive === "function") - ? await track.raw.engine.downloadProgressive() - : typeof track.raw.engine === "function" - ? await track.raw.engine() - : track.raw.engine; - } - const ffmpegStream = (0, FFmpegStream_1.createFFmpegStream)(stream, { - encoderArgs: options.encoderArgs || [], - seek: options.seek ? options.seek / 1000 : 0, - fmt: "s16le" - }).on("error", (err) => { - if (!`${err}`.toLowerCase().includes("premature close")) - this.player.emit("error", this, err); - }); - const resource = this.connection.createStream(ffmpegStream, { - type: voice_1.StreamType.Raw, - data: track, - disableVolume: Boolean(this.options.disableVolume) - }); - if (options.seek) - this._streamTime = options.seek; - this._filtersUpdate = options.filtersUpdate; - const volumeTransformer = resource.volume; - if (volumeTransformer && typeof this.options.initialVolume === "number") - Reflect.set(volumeTransformer, "volume", Math.pow(this.options.initialVolume / 100, 1.660964)); - if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") { - if (typeof volumeTransformer.setSmoothness === "function") - volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0); - } - setTimeout(() => { - this.connection.playStream(resource); - }, tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_getBufferingTimeout).call(this)).unref(); - } - /** - * Private method to handle autoplay - * @param {Track} track The source track to find its similar track for autoplay - * @returns {Promise} - * @private - */ - async _handleAutoplay(track) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!track || ![track.source, track.raw?.source].includes("youtube")) { - if (this.options.leaveOnEnd) - this.destroy(); - return void this.player.emit("queueEnd", this); - } - const info = await play_dl_1.default.video_info(track.url) - .catch(Util_1.Util.noop); - if (!info) { - if (this.options.leaveOnEnd) - this.destroy(); - return void this.player.emit("queueEnd", this); - } - const randomRelated = await play_dl_1.default.video_info(info.related_videos[0]); - const nextTrack = new Track_1.default(this.player, { - title: randomRelated.video_details.title, - url: randomRelated.video_details.url, - duration: randomRelated.video_details.durationRaw ? Util_1.Util.buildTimeCode(Util_1.Util.parseMS(randomRelated.video_details.durationInSec * 1000)) : "0:00", - description: "", - thumbnail: Util_1.Util.last(randomRelated.video_details.thumbnails).url, - views: randomRelated.video_details.views, - author: randomRelated.video_details.channel.name, - requestedBy: track.requestedBy, - source: "youtube" - }); - this.play(nextTrack, { immediate: true }); - } - *[(_Queue_lastVolume = new WeakMap(), _Queue_destroyed = new WeakMap(), _Queue_instances = new WeakSet(), Symbol.iterator)]() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - yield* this.tracks; - } - /** - * JSON representation of this queue - * @returns {object} - */ - toJSON() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - return { - id: this.id, - guild: this.guild.id, - voiceChannel: this.connection?.channel?.id, - options: this.options, - tracks: this.tracks.map((m) => m.toJSON()) - }; - } - /** - * String representation of this queue - * @returns {string} - */ - toString() { - if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this)) - return; - if (!this.tracks.length) - return "No songs available to display!"; - return `**Upcoming Songs:**\n${this.tracks.map((m, i) => `${i + 1}. **${m.title}**`).join("\n")}`; - } -} -exports.Queue = Queue; -_Queue_watchDestroyed = function _Queue_watchDestroyed(emit = true) { - if (tslib_1.__classPrivateFieldGet(this, _Queue_destroyed, "f")) { - if (emit) - this.player.emit("error", this, new PlayerError_1.PlayerError("Cannot use destroyed queue", PlayerError_1.ErrorStatusCode.DESTROYED_QUEUE)); - return true; - } - return false; -}, _Queue_getBufferingTimeout = function _Queue_getBufferingTimeout() { - const timeout = this.options.bufferingTimeout; - if (isNaN(timeout) || timeout < 0 || !Number.isFinite(timeout)) - return 1000; - return timeout; -}; diff --git a/helpers/Music/dist/Structures/Track.d.ts b/helpers/Music/dist/Structures/Track.d.ts deleted file mode 100644 index 077b7ac9..00000000 --- a/helpers/Music/dist/Structures/Track.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { User } from "discord.js"; -import { Player } from "../Player"; -import { RawTrackData, TrackJSON } from "../types/types"; -import { Playlist } from "./Playlist"; -import { Queue } from "./Queue"; -declare class Track { - player: Player; - title: string; - description: string; - author: string; - url: string; - thumbnail: string; - duration: string; - views: number; - requestedBy: User; - playlist?: Playlist; - readonly raw: RawTrackData; - readonly id: string; - /** - * Track constructor - * @param {Player} player The player that instantiated this Track - * @param {RawTrackData} data Track data - */ - constructor(player: Player, data: RawTrackData); - private _patch; - /** - * The queue in which this track is located - * @type {Queue} - */ - get queue(): Queue; - /** - * The track duration in millisecond - * @type {number} - */ - get durationMS(): number; - /** - * Returns source of this track - * @type {TrackSource} - */ - get source(): import("../types/types").TrackSource; - /** - * String representation of this track - * @returns {string} - */ - toString(): string; - /** - * Raw JSON representation of this track - * @returns {TrackJSON} - */ - toJSON(hidePlaylist?: boolean): TrackJSON; -} -export default Track; -export { Track }; diff --git a/helpers/Music/dist/Structures/Track.js b/helpers/Music/dist/Structures/Track.js deleted file mode 100644 index 843179de..00000000 --- a/helpers/Music/dist/Structures/Track.js +++ /dev/null @@ -1,156 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Track = void 0; -const discord_js_1 = require("discord.js"); -class Track { - /** - * Track constructor - * @param {Player} player The player that instantiated this Track - * @param {RawTrackData} data Track data - */ - constructor(player, data) { - this.raw = {}; - this.id = discord_js_1.SnowflakeUtil.generate().toString(); - /** - * The player that instantiated this Track - * @name Track#player - * @type {Player} - * @readonly - */ - Object.defineProperty(this, "player", { value: player, enumerable: false }); - /** - * Title of this track - * @name Track#title - * @type {string} - */ - /** - * Description of this track - * @name Track#description - * @type {string} - */ - /** - * Author of this track - * @name Track#author - * @type {string} - */ - /** - * URL of this track - * @name Track#url - * @type {string} - */ - /** - * Thumbnail of this track - * @name Track#thumbnail - * @type {string} - */ - /** - * Duration of this track - * @name Track#duration - * @type {string} - */ - /** - * Views count of this track - * @name Track#views - * @type {number} - */ - /** - * Person who requested this track - * @name Track#requestedBy - * @type {User} - */ - /** - * If this track belongs to playlist - * @name Track#fromPlaylist - * @type {boolean} - */ - /** - * Raw track data - * @name Track#raw - * @type {RawTrackData} - */ - /** - * The track id - * @name Track#id - * @type {Snowflake} - * @readonly - */ - /** - * The playlist which track belongs - * @name Track#playlist - * @type {Playlist} - */ - void this._patch(data); - } - _patch(data) { - this.title = (0, discord_js_1.escapeMarkdown)(data.title ?? ""); - this.description = data.description ?? ""; - this.author = data.author ?? ""; - this.url = data.url ?? ""; - this.thumbnail = data.thumbnail ?? ""; - this.duration = data.duration ?? ""; - this.views = data.views ?? 0; - this.requestedBy = data.requestedBy; - this.playlist = data.playlist; - // raw - Object.defineProperty(this, "raw", { value: Object.assign({}, { source: data.raw?.source ?? data.source }, data.raw ?? data), enumerable: false }); - } - /** - * The queue in which this track is located - * @type {Queue} - */ - get queue() { - return this.player.queues.find((q) => q.tracks.some((ab) => ab.id === this.id)); - } - /** - * The track duration in millisecond - * @type {number} - */ - get durationMS() { - const times = (n, t) => { - let tn = 1; - for (let i = 0; i < t; i++) - tn *= n; - return t <= 0 ? 1000 : tn * 1000; - }; - return this.duration - .split(":") - .reverse() - .map((m, i) => parseInt(m) * times(60, i)) - .reduce((a, c) => a + c, 0); - } - /** - * Returns source of this track - * @type {TrackSource} - */ - get source() { - return this.raw.source ?? "arbitrary"; - } - /** - * String representation of this track - * @returns {string} - */ - toString() { - return `${this.title} by ${this.author}`; - } - /** - * Raw JSON representation of this track - * @returns {TrackJSON} - */ - toJSON(hidePlaylist) { - return { - id: this.id, - title: this.title, - description: this.description, - author: this.author, - url: this.url, - thumbnail: this.thumbnail, - duration: this.duration, - durationMS: this.durationMS, - views: this.views, - requestedBy: this.requestedBy?.id, - playlist: hidePlaylist ? null : this.playlist?.toJSON() ?? null - }; - } -} -exports.Track = Track; -exports.default = Track; diff --git a/helpers/Music/dist/VoiceInterface/StreamDispatcher.d.ts b/helpers/Music/dist/VoiceInterface/StreamDispatcher.d.ts deleted file mode 100644 index 5f08a09a..00000000 --- a/helpers/Music/dist/VoiceInterface/StreamDispatcher.d.ts +++ /dev/null @@ -1,88 +0,0 @@ -/// -import { AudioPlayer, AudioPlayerError, AudioPlayerStatus, AudioResource, StreamType, VoiceConnection } from "@discordjs/voice"; -import { StageChannel, VoiceChannel } from "discord.js"; -import { Duplex, Readable } from "stream"; -import { TypedEmitter as EventEmitter } from "tiny-typed-emitter"; -import Track from "../Structures/Track"; -export interface VoiceEvents { - error: (error: AudioPlayerError) => any; - debug: (message: string) => any; - start: (resource: AudioResource) => any; - finish: (resource: AudioResource) => any; -} -declare class StreamDispatcher extends EventEmitter { - readonly connectionTimeout: number; - readonly voiceConnection: VoiceConnection; - readonly audioPlayer: AudioPlayer; - channel: VoiceChannel | StageChannel; - audioResource?: AudioResource; - private readyLock; - paused: boolean; - /** - * Creates new connection object - * @param {VoiceConnection} connection The connection - * @param {VoiceChannel|StageChannel} channel The connected channel - * @private - */ - constructor(connection: VoiceConnection, channel: VoiceChannel | StageChannel, connectionTimeout?: number); - /** - * Creates stream - * @param {Readable|Duplex|string} src The stream source - * @param {object} [ops] Options - * @returns {AudioResource} - */ - createStream(src: Readable | Duplex | string, ops?: { - type?: StreamType; - data?: any; - disableVolume?: boolean; - }): AudioResource; - /** - * The player status - * @type {AudioPlayerStatus} - */ - get status(): AudioPlayerStatus; - /** - * Disconnects from voice - * @returns {void} - */ - disconnect(): void; - /** - * Stops the player - * @returns {void} - */ - end(): void; - /** - * Pauses the stream playback - * @param {boolean} [interpolateSilence=false] If true, the player will play 5 packets of silence after pausing to prevent audio glitches. - * @returns {boolean} - */ - pause(interpolateSilence?: boolean): boolean; - /** - * Resumes the stream playback - * @returns {boolean} - */ - resume(): boolean; - /** - * Play stream - * @param {AudioResource} [resource=this.audioResource] The audio resource to play - * @returns {Promise} - */ - playStream(resource?: AudioResource): Promise; - /** - * Sets playback volume - * @param {number} value The volume amount - * @returns {boolean} - */ - setVolume(value: number): boolean; - /** - * The current volume - * @type {number} - */ - get volume(): number; - /** - * The playback time - * @type {number} - */ - get streamTime(): number; -} -export { StreamDispatcher as StreamDispatcher }; diff --git a/helpers/Music/dist/VoiceInterface/StreamDispatcher.js b/helpers/Music/dist/VoiceInterface/StreamDispatcher.js deleted file mode 100644 index 24d72599..00000000 --- a/helpers/Music/dist/VoiceInterface/StreamDispatcher.js +++ /dev/null @@ -1,225 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.StreamDispatcher = void 0; -const voice_1 = require("@discordjs/voice"); -const tiny_typed_emitter_1 = require("tiny-typed-emitter"); -const Util_1 = require("../utils/Util"); -const PlayerError_1 = require("../Structures/PlayerError"); -class StreamDispatcher extends tiny_typed_emitter_1.TypedEmitter { - /** - * Creates new connection object - * @param {VoiceConnection} connection The connection - * @param {VoiceChannel|StageChannel} channel The connected channel - * @private - */ - constructor(connection, channel, connectionTimeout = 20000) { - super(); - this.connectionTimeout = connectionTimeout; - this.readyLock = false; - /** - * The voice connection - * @type {VoiceConnection} - */ - this.voiceConnection = connection; - /** - * The audio player - * @type {AudioPlayer} - */ - this.audioPlayer = (0, voice_1.createAudioPlayer)(); - /** - * The voice channel - * @type {VoiceChannel|StageChannel} - */ - this.channel = channel; - /** - * The paused state - * @type {boolean} - */ - this.paused = false; - this.voiceConnection.on("stateChange", async (_, newState) => { - if (newState.status === voice_1.VoiceConnectionStatus.Disconnected) { - if (newState.reason === voice_1.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) { - try { - await (0, voice_1.entersState)(this.voiceConnection, voice_1.VoiceConnectionStatus.Connecting, this.connectionTimeout); - } - catch { - try { - this.voiceConnection.destroy(); - } - catch (err) { - this.emit("error", err); - } - } - } - else if (this.voiceConnection.rejoinAttempts < 5) { - await Util_1.Util.wait((this.voiceConnection.rejoinAttempts + 1) * 5000); - this.voiceConnection.rejoin(); - } - else { - try { - this.voiceConnection.destroy(); - } - catch (err) { - this.emit("error", err); - } - } - } - else if (newState.status === voice_1.VoiceConnectionStatus.Destroyed) { - this.end(); - } - else if (!this.readyLock && (newState.status === voice_1.VoiceConnectionStatus.Connecting || newState.status === voice_1.VoiceConnectionStatus.Signalling)) { - this.readyLock = true; - try { - await (0, voice_1.entersState)(this.voiceConnection, voice_1.VoiceConnectionStatus.Ready, this.connectionTimeout); - } - catch { - if (this.voiceConnection.state.status !== voice_1.VoiceConnectionStatus.Destroyed) { - try { - this.voiceConnection.destroy(); - } - catch (err) { - this.emit("error", err); - } - } - } - finally { - this.readyLock = false; - } - } - }); - this.audioPlayer.on("stateChange", (oldState, newState) => { - if (newState.status === voice_1.AudioPlayerStatus.Playing) { - if (!this.paused) - return void this.emit("start", this.audioResource); - } - else if (newState.status === voice_1.AudioPlayerStatus.Idle && oldState.status !== voice_1.AudioPlayerStatus.Idle) { - if (!this.paused) { - void this.emit("finish", this.audioResource); - this.audioResource = null; - } - } - }); - this.audioPlayer.on("debug", (m) => void this.emit("debug", m)); - this.audioPlayer.on("error", (error) => void this.emit("error", error)); - this.voiceConnection.subscribe(this.audioPlayer); - } - /** - * Creates stream - * @param {Readable|Duplex|string} src The stream source - * @param {object} [ops] Options - * @returns {AudioResource} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - createStream(src, ops) { - this.audioResource = (0, voice_1.createAudioResource)(src, { - inputType: ops?.type ?? voice_1.StreamType.Arbitrary, - metadata: ops?.data, - // eslint-disable-next-line no-extra-boolean-cast - inlineVolume: !Boolean(ops?.disableVolume) - }); - return this.audioResource; - } - /** - * The player status - * @type {AudioPlayerStatus} - */ - get status() { - return this.audioPlayer.state.status; - } - /** - * Disconnects from voice - * @returns {void} - */ - disconnect() { - try { - this.audioPlayer.stop(true); - this.voiceConnection.destroy(); - } - catch { } // eslint-disable-line no-empty - } - /** - * Stops the player - * @returns {void} - */ - end() { - this.audioPlayer.stop(); - } - /** - * Pauses the stream playback - * @param {boolean} [interpolateSilence=false] If true, the player will play 5 packets of silence after pausing to prevent audio glitches. - * @returns {boolean} - */ - pause(interpolateSilence) { - const success = this.audioPlayer.pause(interpolateSilence); - this.paused = success; - return success; - } - /** - * Resumes the stream playback - * @returns {boolean} - */ - resume() { - const success = this.audioPlayer.unpause(); - this.paused = !success; - return success; - } - /** - * Play stream - * @param {AudioResource} [resource=this.audioResource] The audio resource to play - * @returns {Promise} - */ - async playStream(resource = this.audioResource) { - if (!resource) - throw new PlayerError_1.PlayerError("Audio resource is not available!", PlayerError_1.ErrorStatusCode.NO_AUDIO_RESOURCE); - if (resource.ended) - return void this.emit("error", new PlayerError_1.PlayerError("Cannot play a resource that has already ended.")); - if (!this.audioResource) - this.audioResource = resource; - if (this.voiceConnection.state.status !== voice_1.VoiceConnectionStatus.Ready) { - try { - await (0, voice_1.entersState)(this.voiceConnection, voice_1.VoiceConnectionStatus.Ready, this.connectionTimeout); - } - catch (err) { - return void this.emit("error", err); - } - } - try { - this.audioPlayer.play(resource); - } - catch (e) { - this.emit("error", e); - } - return this; - } - /** - * Sets playback volume - * @param {number} value The volume amount - * @returns {boolean} - */ - setVolume(value) { - if (!this.audioResource?.volume || isNaN(value) || value < 0 || value > Infinity) - return false; - this.audioResource.volume.setVolumeLogarithmic(value / 100); - return true; - } - /** - * The current volume - * @type {number} - */ - get volume() { - if (!this.audioResource?.volume) - return 100; - const currentVol = this.audioResource.volume.volume; - return Math.round(Math.pow(currentVol, 1 / 1.660964) * 100); - } - /** - * The playback time - * @type {number} - */ - get streamTime() { - if (!this.audioResource) - return 0; - return this.audioResource.playbackDuration; - } -} -exports.StreamDispatcher = StreamDispatcher; diff --git a/helpers/Music/dist/VoiceInterface/VoiceUtils.d.ts b/helpers/Music/dist/VoiceInterface/VoiceUtils.d.ts deleted file mode 100644 index 6f6cc57e..00000000 --- a/helpers/Music/dist/VoiceInterface/VoiceUtils.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { VoiceChannel, StageChannel, Collection, Snowflake } from "discord.js"; -import { VoiceConnection } from "@discordjs/voice"; -import { StreamDispatcher } from "./StreamDispatcher"; -declare class VoiceUtils { - cache: Collection; - /** - * The voice utils - * @private - */ - constructor(); - /** - * Joins a voice channel, creating basic stream dispatch manager - * @param {StageChannel|VoiceChannel} channel The voice channel - * @param {object} [options] Join options - * @returns {Promise} - */ - connect(channel: VoiceChannel | StageChannel, options?: { - deaf?: boolean; - maxTime?: number; - }): Promise; - /** - * Joins a voice channel - * @param {StageChannel|VoiceChannel} [channel] The voice/stage channel to join - * @param {object} [options] Join options - * @returns {VoiceConnection} - */ - join(channel: VoiceChannel | StageChannel, options?: { - deaf?: boolean; - maxTime?: number; - }): Promise; - /** - * Disconnects voice connection - * @param {VoiceConnection} connection The voice connection - * @returns {void} - */ - disconnect(connection: VoiceConnection | StreamDispatcher): void; - /** - * Returns Discord Player voice connection - * @param {Snowflake} guild The guild id - * @returns {StreamDispatcher} - */ - getConnection(guild: Snowflake): StreamDispatcher; -} -export { VoiceUtils }; diff --git a/helpers/Music/dist/VoiceInterface/VoiceUtils.js b/helpers/Music/dist/VoiceInterface/VoiceUtils.js deleted file mode 100644 index 365b74ab..00000000 --- a/helpers/Music/dist/VoiceInterface/VoiceUtils.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.VoiceUtils = void 0; -const discord_js_1 = require("discord.js"); -const voice_1 = require("@discordjs/voice"); -const StreamDispatcher_1 = require("./StreamDispatcher"); -class VoiceUtils { - /** - * The voice utils - * @private - */ - constructor() { - /** - * The cache where voice utils stores stream managers - * @type {Collection} - */ - this.cache = new discord_js_1.Collection(); - } - /** - * Joins a voice channel, creating basic stream dispatch manager - * @param {StageChannel|VoiceChannel} channel The voice channel - * @param {object} [options] Join options - * @returns {Promise} - */ - async connect(channel, options) { - const conn = await this.join(channel, options); - const sub = new StreamDispatcher_1.StreamDispatcher(conn, channel, options.maxTime); - this.cache.set(channel.guild.id, sub); - return sub; - } - /** - * Joins a voice channel - * @param {StageChannel|VoiceChannel} [channel] The voice/stage channel to join - * @param {object} [options] Join options - * @returns {VoiceConnection} - */ - async join(channel, options) { - const conn = (0, voice_1.joinVoiceChannel)({ - guildId: channel.guild.id, - channelId: channel.id, - adapterCreator: channel.guild.voiceAdapterCreator, - selfDeaf: Boolean(options.deaf) - }); - return conn; - } - /** - * Disconnects voice connection - * @param {VoiceConnection} connection The voice connection - * @returns {void} - */ - disconnect(connection) { - if (connection instanceof StreamDispatcher_1.StreamDispatcher) - return connection.voiceConnection.destroy(); - return connection.destroy(); - } - /** - * Returns Discord Player voice connection - * @param {Snowflake} guild The guild id - * @returns {StreamDispatcher} - */ - getConnection(guild) { - return this.cache.get(guild); - } -} -exports.VoiceUtils = VoiceUtils; diff --git a/helpers/Music/dist/VoiceInterface/VolumeTransformer.d.ts b/helpers/Music/dist/VoiceInterface/VolumeTransformer.d.ts deleted file mode 100644 index 8b648df0..00000000 --- a/helpers/Music/dist/VoiceInterface/VolumeTransformer.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -/// -/// -import { Transform, TransformOptions } from "stream"; -export interface VolumeTransformerOptions extends TransformOptions { - type?: "s16le" | "s16be" | "s32le" | "s32be"; - smoothness?: number; - volume?: number; -} -export declare class VolumeTransformer extends Transform { - private _bits; - private _smoothing; - private _bytes; - private _extremum; - private _chunk; - volume: number; - private _targetVolume; - type: "s16le" | "s32le" | "s16be" | "s32be"; - constructor(options?: VolumeTransformerOptions); - _readInt(buffer: Buffer, index: number): number; - _writeInt(buffer: Buffer, int: number, index: number): number; - _applySmoothness(): void; - _transform(chunk: Buffer, encoding: BufferEncoding, done: () => unknown): unknown; - _destroy(err: Error, cb: (error: Error) => void): void; - setVolume(volume: number): void; - setVolumeDecibels(db: number): void; - setVolumeLogarithmic(value: number): void; - get volumeDecibels(): number; - get volumeLogarithmic(): number; - get smoothness(): number; - setSmoothness(smoothness: number): void; - smoothingEnabled(): boolean; - get hasSmoothness(): boolean; - static get hasSmoothing(): boolean; -} diff --git a/helpers/Music/dist/VoiceInterface/VolumeTransformer.js b/helpers/Music/dist/VoiceInterface/VolumeTransformer.js deleted file mode 100644 index 13365da8..00000000 --- a/helpers/Music/dist/VoiceInterface/VolumeTransformer.js +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; -// prism's volume transformer with smooth volume support -Object.defineProperty(exports, "__esModule", { value: true }); -exports.VolumeTransformer = void 0; -const stream_1 = require("stream"); -class VolumeTransformer extends stream_1.Transform { - constructor(options = {}) { - super(options); - switch (options.type) { - case "s16le": - this._readInt = (buffer, index) => buffer.readInt16LE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index); - this._bits = 16; - break; - case "s16be": - this._readInt = (buffer, index) => buffer.readInt16BE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index); - this._bits = 16; - break; - case "s32le": - this._readInt = (buffer, index) => buffer.readInt32LE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index); - this._bits = 32; - break; - case "s32be": - this._readInt = (buffer, index) => buffer.readInt32BE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index); - this._bits = 32; - break; - default: - throw new Error("VolumeTransformer type should be one of s16le, s16be, s32le, s32be"); - } - this.type = options.type; - this._bytes = this._bits / 8; - this._extremum = Math.pow(2, this._bits - 1); - this.volume = Number.isNaN(options.volume) ? 1 : Number(options.volume); - if (!Number.isFinite(this.volume)) - this.volume = 1; - this._targetVolume = this.volume; - this._chunk = Buffer.alloc(0); - this._smoothing = options.smoothness || 0; - } - _readInt(buffer, index) { - return index; - } - _writeInt(buffer, int, index) { - return index; - } - _applySmoothness() { - if (this.volume < this._targetVolume) { - this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing; - } - else if (this.volume > this._targetVolume) { - this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing; - } - } - _transform(chunk, encoding, done) { - if (this.smoothingEnabled() && this.volume !== this._targetVolume) - this._applySmoothness(); - if (this.volume === 1) { - this.push(chunk); - return done(); - } - const { _bytes, _extremum } = this; - chunk = this._chunk = Buffer.concat([this._chunk, chunk]); - if (chunk.length < _bytes) - return done(); - const complete = Math.floor(chunk.length / _bytes) * _bytes; - for (let i = 0; i < complete; i += _bytes) { - const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i)))); - this._writeInt(chunk, int, i); - } - this._chunk = chunk.slice(complete); - this.push(chunk.slice(0, complete)); - return done(); - } - _destroy(err, cb) { - super._destroy(err, cb); - this._chunk = null; - } - setVolume(volume) { - if (Number.isNaN(volume)) - volume = 1; - if (typeof volume !== "number") - volume = Number(volume); - if (!Number.isFinite(volume)) - volume = volume < 0 ? 0 : 1; - this._targetVolume = volume; - if (this._smoothing <= 0) - this.volume = volume; - } - setVolumeDecibels(db) { - this.setVolume(Math.pow(10, db / 20)); - } - setVolumeLogarithmic(value) { - this.setVolume(Math.pow(value, 1.660964)); - } - get volumeDecibels() { - return Math.log10(this.volume) * 20; - } - get volumeLogarithmic() { - return Math.pow(this.volume, 1 / 1.660964); - } - get smoothness() { - return this._smoothing; - } - setSmoothness(smoothness) { - this._smoothing = smoothness; - } - smoothingEnabled() { - return Number.isFinite(this._smoothing) && this._smoothing > 0; - } - get hasSmoothness() { - return true; - } - static get hasSmoothing() { - return true; - } -} -exports.VolumeTransformer = VolumeTransformer; diff --git a/helpers/Music/dist/index.d.ts b/helpers/Music/dist/index.d.ts deleted file mode 100644 index e7a7ed5c..00000000 --- a/helpers/Music/dist/index.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import "./smoothVolume"; -export { AudioFilters } from "./utils/AudioFilters"; -export { ExtractorModel } from "./Structures/ExtractorModel"; -export { Playlist } from "./Structures/Playlist"; -export { Player } from "./Player"; -export { PlayerError, ErrorStatusCode } from "./Structures/PlayerError"; -export { QueryResolver } from "./utils/QueryResolver"; -export { Queue } from "./Structures/Queue"; -export { Track } from "./Structures/Track"; -export { VoiceUtils } from "./VoiceInterface/VoiceUtils"; -export { VoiceEvents, StreamDispatcher } from "./VoiceInterface/StreamDispatcher"; -export { Util } from "./utils/Util"; -export * from "./types/types"; -export * from "./utils/FFmpegStream"; -export declare const version: string; diff --git a/helpers/Music/dist/index.js b/helpers/Music/dist/index.js deleted file mode 100644 index e6be0d88..00000000 --- a/helpers/Music/dist/index.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.version = exports.Util = exports.StreamDispatcher = exports.VoiceUtils = exports.Track = exports.Queue = exports.QueryResolver = exports.ErrorStatusCode = exports.PlayerError = exports.Player = exports.Playlist = exports.ExtractorModel = exports.AudioFilters = void 0; -const tslib_1 = require("tslib"); -// try applying smooth volume patch on load -require("./smoothVolume"); -var AudioFilters_1 = require("./utils/AudioFilters"); -Object.defineProperty(exports, "AudioFilters", { enumerable: true, get: function () { return AudioFilters_1.AudioFilters; } }); -var ExtractorModel_1 = require("./Structures/ExtractorModel"); -Object.defineProperty(exports, "ExtractorModel", { enumerable: true, get: function () { return ExtractorModel_1.ExtractorModel; } }); -var Playlist_1 = require("./Structures/Playlist"); -Object.defineProperty(exports, "Playlist", { enumerable: true, get: function () { return Playlist_1.Playlist; } }); -var Player_1 = require("./Player"); -Object.defineProperty(exports, "Player", { enumerable: true, get: function () { return Player_1.Player; } }); -var PlayerError_1 = require("./Structures/PlayerError"); -Object.defineProperty(exports, "PlayerError", { enumerable: true, get: function () { return PlayerError_1.PlayerError; } }); -Object.defineProperty(exports, "ErrorStatusCode", { enumerable: true, get: function () { return PlayerError_1.ErrorStatusCode; } }); -var QueryResolver_1 = require("./utils/QueryResolver"); -Object.defineProperty(exports, "QueryResolver", { enumerable: true, get: function () { return QueryResolver_1.QueryResolver; } }); -var Queue_1 = require("./Structures/Queue"); -Object.defineProperty(exports, "Queue", { enumerable: true, get: function () { return Queue_1.Queue; } }); -var Track_1 = require("./Structures/Track"); -Object.defineProperty(exports, "Track", { enumerable: true, get: function () { return Track_1.Track; } }); -var VoiceUtils_1 = require("./VoiceInterface/VoiceUtils"); -Object.defineProperty(exports, "VoiceUtils", { enumerable: true, get: function () { return VoiceUtils_1.VoiceUtils; } }); -var StreamDispatcher_1 = require("./VoiceInterface/StreamDispatcher"); -Object.defineProperty(exports, "StreamDispatcher", { enumerable: true, get: function () { return StreamDispatcher_1.StreamDispatcher; } }); -var Util_1 = require("./utils/Util"); -Object.defineProperty(exports, "Util", { enumerable: true, get: function () { return Util_1.Util; } }); -tslib_1.__exportStar(require("./types/types"), exports); -tslib_1.__exportStar(require("./utils/FFmpegStream"), exports); -// eslint-disable-next-line @typescript-eslint/no-var-requires -exports.version = require(`${__dirname}/../package.json`).version; diff --git a/helpers/Music/dist/index.mjs b/helpers/Music/dist/index.mjs deleted file mode 100644 index ddc052d1..00000000 --- a/helpers/Music/dist/index.mjs +++ /dev/null @@ -1,21 +0,0 @@ -import mod from "./index.js"; - -export default mod; -export const AudioFilters = mod.AudioFilters; -export const ErrorStatusCode = mod.ErrorStatusCode; -export const ExtractorModel = mod.ExtractorModel; -export const FFMPEG_ARGS_PIPED = mod.FFMPEG_ARGS_PIPED; -export const FFMPEG_ARGS_STRING = mod.FFMPEG_ARGS_STRING; -export const Player = mod.Player; -export const PlayerError = mod.PlayerError; -export const Playlist = mod.Playlist; -export const QueryResolver = mod.QueryResolver; -export const QueryType = mod.QueryType; -export const Queue = mod.Queue; -export const QueueRepeatMode = mod.QueueRepeatMode; -export const StreamDispatcher = mod.StreamDispatcher; -export const Track = mod.Track; -export const Util = mod.Util; -export const VoiceUtils = mod.VoiceUtils; -export const createFFmpegStream = mod.createFFmpegStream; -export const version = mod.version; diff --git a/helpers/Music/dist/smoothVolume.d.ts b/helpers/Music/dist/smoothVolume.d.ts deleted file mode 100644 index cb0ff5c3..00000000 --- a/helpers/Music/dist/smoothVolume.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/helpers/Music/dist/smoothVolume.js b/helpers/Music/dist/smoothVolume.js deleted file mode 100644 index b92ea29d..00000000 --- a/helpers/Music/dist/smoothVolume.js +++ /dev/null @@ -1,13 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const VolumeTransformer_1 = require("./VoiceInterface/VolumeTransformer"); -try { - // eslint-disable-next-line - const mod = require("prism-media"); - if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") { - Reflect.set(mod, "VolumeTransformer", VolumeTransformer_1.VolumeTransformer); - } -} -catch { - /* do nothing */ -} diff --git a/helpers/Music/dist/types/types.d.ts b/helpers/Music/dist/types/types.d.ts deleted file mode 100644 index dcb985cb..00000000 --- a/helpers/Music/dist/types/types.d.ts +++ /dev/null @@ -1,453 +0,0 @@ -/// -import { Snowflake, User, UserResolvable } from "discord.js"; -import { Readable, Duplex } from "stream"; -import { Queue } from "../Structures/Queue"; -import Track from "../Structures/Track"; -import { Playlist } from "../Structures/Playlist"; -import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher"; -export declare type FiltersName = keyof QueueFilters; -export interface PlayerSearchResult { - playlist: Playlist | null; - tracks: Track[]; - searched?: boolean; -} -/** - * @typedef {AudioFilters} QueueFilters - */ -export interface QueueFilters { - bassboost_low?: boolean; - bassboost?: boolean; - bassboost_high?: boolean; - "8D"?: boolean; - vaporwave?: boolean; - nightcore?: boolean; - phaser?: boolean; - tremolo?: boolean; - vibrato?: boolean; - reverse?: boolean; - treble?: boolean; - normalizer?: boolean; - normalizer2?: boolean; - surrounding?: boolean; - pulsator?: boolean; - subboost?: boolean; - karaoke?: boolean; - flanger?: boolean; - gate?: boolean; - haas?: boolean; - mcompand?: boolean; - mono?: boolean; - mstlr?: boolean; - mstrr?: boolean; - compressor?: boolean; - expander?: boolean; - softlimiter?: boolean; - chorus?: boolean; - chorus2d?: boolean; - chorus3d?: boolean; - fadein?: boolean; - dim?: boolean; - earrape?: boolean; -} -/** - * The track source: - * - soundcloud - * - youtube - * - spotify - * - arbitrary - * @typedef {string} TrackSource - */ -export declare type TrackSource = "soundcloud" | "youtube" | "spotify" | "arbitrary"; -/** - * @typedef {object} RawTrackData - * @property {string} title The title - * @property {string} description The description - * @property {string} author The author - * @property {string} url The url - * @property {string} thumbnail The thumbnail - * @property {string} duration The duration - * @property {number | boolean} views The views - * @property {User} requestedBy The user who requested this track - * @property {Playlist} [playlist] The playlist - * @property {TrackSource} [source="arbitrary"] The source - * @property {any} [engine] The engine - * @property {boolean} [live] If this track is live - * @property {any} [raw] The raw data - */ -export interface RawTrackData { - title: string; - description: string; - author: string; - url: string; - thumbnail: string; - duration: string; - views: number; - requestedBy: User; - playlist?: Playlist; - source?: TrackSource; - engine?: any; - live?: boolean; - raw?: any; -} -/** - * @typedef {object} TimeData - * @property {number} days Time in days - * @property {number} hours Time in hours - * @property {number} minutes Time in minutes - * @property {number} seconds Time in seconds - */ -export interface TimeData { - days: number; - hours: number; - minutes: number; - seconds: number; -} -/** - * @typedef {object} PlayerProgressbarOptions - * @property {boolean} [timecodes] If it should render time codes - * @property {boolean} [queue] If it should create progress bar for the whole queue - * @property {number} [length] The bar length - * @property {string} [line] The bar track - * @property {string} [indicator] The indicator - */ -export interface PlayerProgressbarOptions { - timecodes?: boolean; - length?: number; - line?: string; - indicator?: string; - queue?: boolean; -} -/** - * @typedef {object} PlayerOptions - * @property {boolean} [leaveOnEnd=true] If it should leave on end - * @property {boolean} [leaveOnStop=true] If it should leave on stop - * @property {boolean} [leaveOnEmpty=true] If it should leave on empty - * @property {number} [leaveOnEmptyCooldown=1000] The cooldown in ms - * @property {boolean} [autoSelfDeaf=true] If it should set the bot in deaf mode - * @property {YTDLDownloadOptions} [ytdlOptions] The youtube download options - * @property {number} [initialVolume=100] The initial player volume - * @property {number} [bufferingTimeout=3000] Buffering timeout for the stream - * @property {boolean} [spotifyBridge=true] If player should bridge spotify source to youtube - * @property {boolean} [disableVolume=false] If player should disable inline volume - * @property {number} [volumeSmoothness=0] The volume transition smoothness between volume changes (lower the value to get better result) - * Setting this or leaving this empty will disable this effect. Example: `volumeSmoothness: 0.1` - * @property {Function} [onBeforeCreateStream] Runs before creating stream - */ -export interface PlayerOptions { - leaveOnEnd?: boolean; - leaveOnStop?: boolean; - leaveOnEmpty?: boolean; - leaveOnEmptyCooldown?: number; - autoSelfDeaf?: boolean; - initialVolume?: number; - bufferingTimeout?: number; - spotifyBridge?: boolean; - disableVolume?: boolean; - volumeSmoothness?: number; - onBeforeCreateStream?: (track: Track, source: TrackSource, queue: Queue) => Promise; -} -/** - * @typedef {object} ExtractorModelData - * @property {object} [playlist] The playlist info (if any) - * @property {string} [playlist.title] The playlist title - * @property {string} [playlist.description] The playlist description - * @property {string} [playlist.thumbnail] The playlist thumbnail - * @property {album|playlist} [playlist.type] The playlist type: `album` | `playlist` - * @property {TrackSource} [playlist.source] The playlist source - * @property {object} [playlist.author] The playlist author - * @property {string} [playlist.author.name] The author name - * @property {string} [playlist.author.url] The author url - * @property {string} [playlist.id] The playlist id - * @property {string} [playlist.url] The playlist url - * @property {any} [playlist.rawPlaylist] The raw data - * @property {ExtractorData[]} data The data - */ -/** - * @typedef {object} ExtractorData - * @property {string} title The title - * @property {number} duration The duration - * @property {string} thumbnail The thumbnail - * @property {string|Readable|Duplex} engine The stream engine - * @property {number} views The views count - * @property {string} author The author - * @property {string} description The description - * @property {string} url The url - * @property {string} [version] The extractor version - * @property {TrackSource} [source="arbitrary"] The source - */ -export interface ExtractorModelData { - playlist?: { - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - id: string; - url: string; - rawPlaylist?: any; - }; - data: { - title: string; - duration: number; - thumbnail: string; - engine: string | Readable | Duplex; - views: number; - author: string; - description: string; - url: string; - version?: string; - source?: TrackSource; - }[]; -} -/** - * The search query type - * This can be one of: - * - AUTO - * - YOUTUBE - * - YOUTUBE_PLAYLIST - * - SOUNDCLOUD_TRACK - * - SOUNDCLOUD_PLAYLIST - * - SOUNDCLOUD - * - SPOTIFY_SONG - * - SPOTIFY_ALBUM - * - SPOTIFY_PLAYLIST - * - FACEBOOK - * - VIMEO - * - ARBITRARY - * - REVERBNATION - * - YOUTUBE_SEARCH - * - YOUTUBE_VIDEO - * - SOUNDCLOUD_SEARCH - * @typedef {number} QueryType - */ -export declare enum QueryType { - AUTO = 0, - YOUTUBE = 1, - YOUTUBE_PLAYLIST = 2, - SOUNDCLOUD_TRACK = 3, - SOUNDCLOUD_PLAYLIST = 4, - SOUNDCLOUD = 5, - SPOTIFY_SONG = 6, - SPOTIFY_ALBUM = 7, - SPOTIFY_PLAYLIST = 8, - FACEBOOK = 9, - VIMEO = 10, - ARBITRARY = 11, - REVERBNATION = 12, - YOUTUBE_SEARCH = 13, - YOUTUBE_VIDEO = 14, - SOUNDCLOUD_SEARCH = 15 -} -/** - * Emitted when bot gets disconnected from a voice channel - * @event Player#botDisconnect - * @param {Queue} queue The queue - */ -/** - * Emitted when the voice channel is empty - * @event Player#channelEmpty - * @param {Queue} queue The queue - */ -/** - * Emitted when bot connects to a voice channel - * @event Player#connectionCreate - * @param {Queue} queue The queue - * @param {StreamDispatcher} connection The discord player connection object - */ -/** - * Debug information - * @event Player#debug - * @param {Queue} queue The queue - * @param {string} message The message - */ -/** - * Emitted on error - * This event should handled properly otherwise it may crash your process! - * @event Player#error - * @param {Queue} queue The queue - * @param {Error} error The error - */ -/** - * Emitted on connection error. Sometimes stream errors are emitted here as well. - * @event Player#connectionError - * @param {Queue} queue The queue - * @param {Error} error The error - */ -/** - * Emitted when queue ends - * @event Player#queueEnd - * @param {Queue} queue The queue - */ -/** - * Emitted when a single track is added - * @event Player#trackAdd - * @param {Queue} queue The queue - * @param {Track} track The track - */ -/** - * Emitted when multiple tracks are added - * @event Player#tracksAdd - * @param {Queue} queue The queue - * @param {Track[]} tracks The tracks - */ -/** - * Emitted when a track starts playing - * @event Player#trackStart - * @param {Queue} queue The queue - * @param {Track} track The track - */ -/** - * Emitted when a track ends - * @event Player#trackEnd - * @param {Queue} queue The queue - * @param {Track} track The track - */ -export interface PlayerEvents { - botDisconnect: (queue: Queue) => any; - channelEmpty: (queue: Queue) => any; - connectionCreate: (queue: Queue, connection: StreamDispatcher) => any; - debug: (queue: Queue, message: string) => any; - error: (queue: Queue, error: Error) => any; - connectionError: (queue: Queue, error: Error) => any; - queueEnd: (queue: Queue) => any; - trackAdd: (queue: Queue, track: Track) => any; - tracksAdd: (queue: Queue, track: Track[]) => any; - trackStart: (queue: Queue, track: Track) => any; - trackEnd: (queue: Queue, track: Track) => any; -} -/** - * @typedef {object} PlayOptions - * @property {boolean} [filtersUpdate=false] If this play was triggered for filters update - * @property {string[]} [encoderArgs=[]] FFmpeg args passed to encoder - * @property {number} [seek] Time to seek to before playing - * @property {boolean} [immediate=false] If it should start playing the provided track immediately - */ -export interface PlayOptions { - filtersUpdate?: boolean; - encoderArgs?: string[]; - seek?: number; - immediate?: boolean; -} -/** - * @typedef {object} SearchOptions - * @property {UserResolvable} requestedBy The user who requested this search - * @property {QueryType|string} [searchEngine=QueryType.AUTO] The query search engine, can be extractor name to target specific one (custom) - * @property {boolean} [blockExtractor=false] If it should block custom extractors - */ -export interface SearchOptions { - requestedBy: UserResolvable; - searchEngine?: QueryType | string; - blockExtractor?: boolean; -} -/** - * The queue repeat mode. This can be one of: - * - OFF - * - TRACK - * - QUEUE - * - AUTOPLAY - * @typedef {number} QueueRepeatMode - */ -export declare enum QueueRepeatMode { - OFF = 0, - TRACK = 1, - QUEUE = 2, - AUTOPLAY = 3 -} -/** - * @typedef {object} PlaylistInitData - * @property {Track[]} tracks The tracks of this playlist - * @property {string} title The playlist title - * @property {string} description The description - * @property {string} thumbnail The thumbnail - * @property {album|playlist} type The playlist type: `album` | `playlist` - * @property {TrackSource} source The playlist source - * @property {object} author The playlist author - * @property {string} [author.name] The author name - * @property {string} [author.url] The author url - * @property {string} id The playlist id - * @property {string} url The playlist url - * @property {any} [rawPlaylist] The raw playlist data - */ -export interface PlaylistInitData { - tracks: Track[]; - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - id: string; - url: string; - rawPlaylist?: any; -} -/** - * @typedef {object} TrackJSON - * @property {string} title The track title - * @property {string} description The track description - * @property {string} author The author - * @property {string} url The url - * @property {string} thumbnail The thumbnail - * @property {string} duration The duration - * @property {number} durationMS The duration in ms - * @property {number} views The views count - * @property {Snowflake} requestedBy The id of the user who requested this track - * @property {PlaylistJSON} [playlist] The playlist info (if any) - */ -export interface TrackJSON { - id: Snowflake; - title: string; - description: string; - author: string; - url: string; - thumbnail: string; - duration: string; - durationMS: number; - views: number; - requestedBy: Snowflake; - playlist?: PlaylistJSON; -} -/** - * @typedef {object} PlaylistJSON - * @property {string} id The playlist id - * @property {string} url The playlist url - * @property {string} title The playlist title - * @property {string} description The playlist description - * @property {string} thumbnail The thumbnail - * @property {album|playlist} type The playlist type: `album` | `playlist` - * @property {TrackSource} source The track source - * @property {object} author The playlist author - * @property {string} [author.name] The author name - * @property {string} [author.url] The author url - * @property {TrackJSON[]} tracks The tracks data (if any) - */ -export interface PlaylistJSON { - id: string; - url: string; - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - tracks: TrackJSON[]; -} -/** - * @typedef {object} PlayerInitOptions - * @property {boolean} [autoRegisterExtractor=true] If it should automatically register `@discord-player/extractor` - * @property {YTDLDownloadOptions} [ytdlOptions] The options passed to `ytdl-core` - * @property {number} [connectionTimeout=20000] The voice connection timeout - */ -export interface PlayerInitOptions { - autoRegisterExtractor?: boolean; - connectionTimeout?: number; -} diff --git a/helpers/Music/dist/types/types.js b/helpers/Music/dist/types/types.js deleted file mode 100644 index 726bb99f..00000000 --- a/helpers/Music/dist/types/types.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.QueueRepeatMode = exports.QueryType = void 0; -/** - * The search query type - * This can be one of: - * - AUTO - * - YOUTUBE - * - YOUTUBE_PLAYLIST - * - SOUNDCLOUD_TRACK - * - SOUNDCLOUD_PLAYLIST - * - SOUNDCLOUD - * - SPOTIFY_SONG - * - SPOTIFY_ALBUM - * - SPOTIFY_PLAYLIST - * - FACEBOOK - * - VIMEO - * - ARBITRARY - * - REVERBNATION - * - YOUTUBE_SEARCH - * - YOUTUBE_VIDEO - * - SOUNDCLOUD_SEARCH - * @typedef {number} QueryType - */ -var QueryType; -(function (QueryType) { - QueryType[QueryType["AUTO"] = 0] = "AUTO"; - QueryType[QueryType["YOUTUBE"] = 1] = "YOUTUBE"; - QueryType[QueryType["YOUTUBE_PLAYLIST"] = 2] = "YOUTUBE_PLAYLIST"; - QueryType[QueryType["SOUNDCLOUD_TRACK"] = 3] = "SOUNDCLOUD_TRACK"; - QueryType[QueryType["SOUNDCLOUD_PLAYLIST"] = 4] = "SOUNDCLOUD_PLAYLIST"; - QueryType[QueryType["SOUNDCLOUD"] = 5] = "SOUNDCLOUD"; - QueryType[QueryType["SPOTIFY_SONG"] = 6] = "SPOTIFY_SONG"; - QueryType[QueryType["SPOTIFY_ALBUM"] = 7] = "SPOTIFY_ALBUM"; - QueryType[QueryType["SPOTIFY_PLAYLIST"] = 8] = "SPOTIFY_PLAYLIST"; - QueryType[QueryType["FACEBOOK"] = 9] = "FACEBOOK"; - QueryType[QueryType["VIMEO"] = 10] = "VIMEO"; - QueryType[QueryType["ARBITRARY"] = 11] = "ARBITRARY"; - QueryType[QueryType["REVERBNATION"] = 12] = "REVERBNATION"; - QueryType[QueryType["YOUTUBE_SEARCH"] = 13] = "YOUTUBE_SEARCH"; - QueryType[QueryType["YOUTUBE_VIDEO"] = 14] = "YOUTUBE_VIDEO"; - QueryType[QueryType["SOUNDCLOUD_SEARCH"] = 15] = "SOUNDCLOUD_SEARCH"; -})(QueryType = exports.QueryType || (exports.QueryType = {})); -/** - * The queue repeat mode. This can be one of: - * - OFF - * - TRACK - * - QUEUE - * - AUTOPLAY - * @typedef {number} QueueRepeatMode - */ -var QueueRepeatMode; -(function (QueueRepeatMode) { - QueueRepeatMode[QueueRepeatMode["OFF"] = 0] = "OFF"; - QueueRepeatMode[QueueRepeatMode["TRACK"] = 1] = "TRACK"; - QueueRepeatMode[QueueRepeatMode["QUEUE"] = 2] = "QUEUE"; - QueueRepeatMode[QueueRepeatMode["AUTOPLAY"] = 3] = "AUTOPLAY"; -})(QueueRepeatMode = exports.QueueRepeatMode || (exports.QueueRepeatMode = {})); diff --git a/helpers/Music/dist/utils/AudioFilters.d.ts b/helpers/Music/dist/utils/AudioFilters.d.ts deleted file mode 100644 index 471e9108..00000000 --- a/helpers/Music/dist/utils/AudioFilters.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { FiltersName } from "../types/types"; -declare class AudioFilters { - constructor(); - static get filters(): Record; - static get(name: K): Record[K]; - static has(name: K): boolean; - static [Symbol.iterator](): IterableIterator<{ - name: FiltersName; - value: string; - }>; - static get names(): (keyof import("../types/types").QueueFilters)[]; - static get length(): number; - static toString(): string; - /** - * Create ffmpeg args from the specified filters name - * @param filter The filter name - * @returns - */ - static create(filters?: K[]): string; - /** - * Defines audio filter - * @param filterName The name of the filter - * @param value The ffmpeg args - */ - static define(filterName: string, value: string): void; - /** - * Defines multiple audio filters - * @param filtersArray Array of filters containing the filter name and ffmpeg args - */ - static defineBulk(filtersArray: { - name: string; - value: string; - }[]): void; -} -export default AudioFilters; -export { AudioFilters }; diff --git a/helpers/Music/dist/utils/AudioFilters.js b/helpers/Music/dist/utils/AudioFilters.js deleted file mode 100644 index 8eac6b1d..00000000 --- a/helpers/Music/dist/utils/AudioFilters.js +++ /dev/null @@ -1,97 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.AudioFilters = void 0; -const bass = (g) => `bass=g=${g}:f=110:w=0.3`; -class AudioFilters { - constructor() { - return AudioFilters; - } - static get filters() { - return { - bassboost_low: bass(15), - bassboost: bass(20), - bassboost_high: bass(30), - "8D": "apulsator=hz=0.09", - vaporwave: "aresample=48000,asetrate=48000*0.8", - nightcore: "aresample=48000,asetrate=48000*1.25", - phaser: "aphaser=in_gain=0.4", - tremolo: "tremolo", - vibrato: "vibrato=f=6.5", - reverse: "areverse", - treble: "treble=g=5", - normalizer2: "dynaudnorm=g=101", - normalizer: "acompressor", - surrounding: "surround", - pulsator: "apulsator=hz=1", - subboost: "asubboost", - karaoke: "stereotools=mlev=0.03", - flanger: "flanger", - gate: "agate", - haas: "haas", - mcompand: "mcompand", - mono: "pan=mono|c0=.5*c0+.5*c1", - mstlr: "stereotools=mode=ms>lr", - mstrr: "stereotools=mode=ms>rr", - compressor: "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6", - expander: "compand=attacks=0:points=-80/-169|-54/-80|-49.5/-64.6|-41.1/-41.1|-25.8/-15|-10.8/-4.5|0/0|20/8.3", - softlimiter: "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8", - chorus: "chorus=0.7:0.9:55:0.4:0.25:2", - chorus2d: "chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3", - chorus3d: "chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3", - fadein: "afade=t=in:ss=0:d=10", - dim: `afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'"`, - earrape: "channelsplit,sidechaingate=level_in=64" - }; - } - static get(name) { - return this.filters[name]; - } - static has(name) { - return name in this.filters; - } - static *[Symbol.iterator]() { - for (const [k, v] of Object.entries(this.filters)) { - yield { name: k, value: v }; - } - } - static get names() { - return Object.keys(this.filters); - } - // @ts-expect-error AudioFilters.length - static get length() { - return this.names.length; - } - static toString() { - return this.names.map((m) => this[m]).join(","); // eslint-disable-line @typescript-eslint/no-explicit-any - } - /** - * Create ffmpeg args from the specified filters name - * @param filter The filter name - * @returns - */ - static create(filters) { - if (!filters || !Array.isArray(filters)) - return this.toString(); - return filters - .filter((predicate) => typeof predicate === "string") - .map((m) => this.get(m)) - .join(","); - } - /** - * Defines audio filter - * @param filterName The name of the filter - * @param value The ffmpeg args - */ - static define(filterName, value) { - this.filters[filterName] = value; - } - /** - * Defines multiple audio filters - * @param filtersArray Array of filters containing the filter name and ffmpeg args - */ - static defineBulk(filtersArray) { - filtersArray.forEach((arr) => this.define(arr.name, arr.value)); - } -} -exports.AudioFilters = AudioFilters; -exports.default = AudioFilters; diff --git a/helpers/Music/dist/utils/FFmpegStream.d.ts b/helpers/Music/dist/utils/FFmpegStream.d.ts deleted file mode 100644 index 18d19e14..00000000 --- a/helpers/Music/dist/utils/FFmpegStream.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/// -import type { Duplex, Readable } from "stream"; -export interface FFmpegStreamOptions { - fmt?: string; - encoderArgs?: string[]; - seek?: number; - skip?: boolean; -} -export declare function FFMPEG_ARGS_STRING(stream: string, fmt?: string): string[]; -export declare function FFMPEG_ARGS_PIPED(fmt?: string): string[]; -/** - * Creates FFmpeg stream - * @param stream The source stream - * @param options FFmpeg stream options - */ -export declare function createFFmpegStream(stream: Readable | Duplex | string, options?: FFmpegStreamOptions): Readable | Duplex; diff --git a/helpers/Music/dist/utils/FFmpegStream.js b/helpers/Music/dist/utils/FFmpegStream.js deleted file mode 100644 index 0a9325ae..00000000 --- a/helpers/Music/dist/utils/FFmpegStream.js +++ /dev/null @@ -1,53 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createFFmpegStream = exports.FFMPEG_ARGS_PIPED = exports.FFMPEG_ARGS_STRING = void 0; -const prism_media_1 = require("prism-media"); -function FFMPEG_ARGS_STRING(stream, fmt) { - // prettier-ignore - return [ - "-reconnect", "1", - "-reconnect_streamed", "1", - "-reconnect_delay_max", "5", - "-i", stream, - "-analyzeduration", "0", - "-loglevel", "0", - "-f", `${typeof fmt === "string" ? fmt : "s16le"}`, - "-ar", "48000", - "-ac", "2" - ]; -} -exports.FFMPEG_ARGS_STRING = FFMPEG_ARGS_STRING; -function FFMPEG_ARGS_PIPED(fmt) { - // prettier-ignore - return [ - "-analyzeduration", "0", - "-loglevel", "0", - "-f", `${typeof fmt === "string" ? fmt : "s16le"}`, - "-ar", "48000", - "-ac", "2" - ]; -} -exports.FFMPEG_ARGS_PIPED = FFMPEG_ARGS_PIPED; -/** - * Creates FFmpeg stream - * @param stream The source stream - * @param options FFmpeg stream options - */ -function createFFmpegStream(stream, options) { - if (options.skip && typeof stream !== "string") - return stream; - options ?? (options = {}); - const args = typeof stream === "string" ? FFMPEG_ARGS_STRING(stream, options.fmt) : FFMPEG_ARGS_PIPED(options.fmt); - if (!Number.isNaN(options.seek)) - args.unshift("-ss", String(options.seek)); - if (Array.isArray(options.encoderArgs)) - args.push(...options.encoderArgs); - const transcoder = new prism_media_1.FFmpeg({ shell: false, args }); - transcoder.on("close", () => transcoder.destroy()); - if (typeof stream !== "string") { - stream.on("error", () => transcoder.destroy()); - stream.pipe(transcoder); - } - return transcoder; -} -exports.createFFmpegStream = createFFmpegStream; diff --git a/helpers/Music/dist/utils/QueryResolver.d.ts b/helpers/Music/dist/utils/QueryResolver.d.ts deleted file mode 100644 index 759c80c9..00000000 --- a/helpers/Music/dist/utils/QueryResolver.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { QueryType } from "../types/types"; -declare class QueryResolver { - /** - * Query resolver - */ - private constructor(); - /** - * Resolves the given search query - * @param {string} query The query - * @returns {QueryType} - */ - static resolve(query: string): Promise; - /** - * Parses vimeo id from url - * @param {string} query The query - * @returns {string} - */ - static getVimeoID(query: string): Promise; -} -export { QueryResolver }; diff --git a/helpers/Music/dist/utils/QueryResolver.js b/helpers/Music/dist/utils/QueryResolver.js deleted file mode 100644 index d1618820..00000000 --- a/helpers/Music/dist/utils/QueryResolver.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.QueryResolver = void 0; -const tslib_1 = require("tslib"); -const types_1 = require("../types/types"); -const play_dl_1 = tslib_1.__importDefault(require("play-dl")); -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// scary things below *sigh* -const spotifySongRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/; -const spotifyPlaylistRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/; -const spotifyAlbumRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/; -const vimeoRegex = /(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)/; -const facebookRegex = /(https?:\/\/)(www\.|m\.)?(facebook|fb).com\/.*\/videos\/.*/; -const reverbnationRegex = /https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/; -const attachmentRegex = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/; -// scary things above *sigh* -class QueryResolver { - /** - * Query resolver - */ - constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function - /** - * Resolves the given search query - * @param {string} query The query - * @returns {QueryType} - */ - static async resolve(query) { - if (await play_dl_1.default.so_validate(query) === "track") - return types_1.QueryType.SOUNDCLOUD_TRACK; - if (await play_dl_1.default.so_validate(query) === "playlist" || query.includes("/sets/")) - return types_1.QueryType.SOUNDCLOUD_PLAYLIST; - if (play_dl_1.default.yt_validate(query) === "playlist") - return types_1.QueryType.YOUTUBE_PLAYLIST; - if (play_dl_1.default.yt_validate(query) === "video") - return types_1.QueryType.YOUTUBE_VIDEO; - if (spotifySongRegex.test(query)) - return types_1.QueryType.SPOTIFY_SONG; - if (spotifyPlaylistRegex.test(query)) - return types_1.QueryType.SPOTIFY_PLAYLIST; - if (spotifyAlbumRegex.test(query)) - return types_1.QueryType.SPOTIFY_ALBUM; - if (vimeoRegex.test(query)) - return types_1.QueryType.VIMEO; - if (facebookRegex.test(query)) - return types_1.QueryType.FACEBOOK; - if (reverbnationRegex.test(query)) - return types_1.QueryType.REVERBNATION; - if (attachmentRegex.test(query)) - return types_1.QueryType.ARBITRARY; - return types_1.QueryType.YOUTUBE_SEARCH; - } - /** - * Parses vimeo id from url - * @param {string} query The query - * @returns {string} - */ - static async getVimeoID(query) { - return await QueryResolver.resolve(query) === types_1.QueryType.VIMEO - ? query - .split("/") - .filter((x) => !!x) - .pop() - : null; - } -} -exports.QueryResolver = QueryResolver; diff --git a/helpers/Music/dist/utils/Util.d.ts b/helpers/Music/dist/utils/Util.d.ts deleted file mode 100644 index 3973e675..00000000 --- a/helpers/Music/dist/utils/Util.d.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { StageChannel, VoiceChannel } from "discord.js"; -import { TimeData } from "../types/types"; -declare class Util { - /** - * Utils - */ - private constructor(); - /** - * Creates duration string - * @param {object} durObj The duration object - * @returns {string} - */ - static durationString(durObj: Record): string; - /** - * Parses milliseconds to consumable time object - * @param {number} milliseconds The time in ms - * @returns {TimeData} - */ - static parseMS(milliseconds: number): TimeData; - /** - * Builds time code - * @param {TimeData} duration The duration object - * @returns {string} - */ - static buildTimeCode(duration: TimeData): string; - /** - * Picks last item of the given array - * @param {any[]} arr The array - * @returns {any} - */ - static last(arr: T[]): T; - /** - * Checks if the voice channel is empty - * @param {VoiceChannel|StageChannel} channel The voice channel - * @returns {boolean} - */ - static isVoiceEmpty(channel: VoiceChannel | StageChannel): boolean; - /** - * Safer require - * @param {string} id Node require id - * @returns {any} - */ - static require(id: string): any; - /** - * Asynchronous timeout - * @param {number} time The time in ms to wait - * @returns {Promise} - */ - static wait(time: number): Promise; - static noop(): void; - static getFetch(): Promise; -} -export { Util }; diff --git a/helpers/Music/dist/utils/Util.js b/helpers/Music/dist/utils/Util.js deleted file mode 100644 index d4758474..00000000 --- a/helpers/Music/dist/utils/Util.js +++ /dev/null @@ -1,133 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Util = void 0; -class Util { - /** - * Utils - */ - constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function - /** - * Creates duration string - * @param {object} durObj The duration object - * @returns {string} - */ - static durationString(durObj) { - return Object.values(durObj) - .map((m) => (isNaN(m) ? 0 : m)) - .join(":"); - } - /** - * Parses milliseconds to consumable time object - * @param {number} milliseconds The time in ms - * @returns {TimeData} - */ - static parseMS(milliseconds) { - const round = milliseconds > 0 ? Math.floor : Math.ceil; - return { - days: round(milliseconds / 86400000), - hours: round(milliseconds / 3600000) % 24, - minutes: round(milliseconds / 60000) % 60, - seconds: round(milliseconds / 1000) % 60 - }; - } - /** - * Builds time code - * @param {TimeData} duration The duration object - * @returns {string} - */ - static buildTimeCode(duration) { - const items = Object.keys(duration); - const required = ["days", "hours", "minutes", "seconds"]; - const parsed = items.filter((x) => required.includes(x)).map((m) => duration[m]); - const final = parsed - .slice(parsed.findIndex((x) => x !== 0)) - .map((x) => x.toString().padStart(2, "0")) - .join(":"); - return final.length <= 3 ? `0:${final.padStart(2, "0") || 0}` : final; - } - /** - * Picks last item of the given array - * @param {any[]} arr The array - * @returns {any} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - static last(arr) { - if (!Array.isArray(arr)) - return; - return arr[arr.length - 1]; - } - /** - * Checks if the voice channel is empty - * @param {VoiceChannel|StageChannel} channel The voice channel - * @returns {boolean} - */ - static isVoiceEmpty(channel) { - return channel.members.filter((member) => !member.user.bot).size === 0; - } - /** - * Safer require - * @param {string} id Node require id - * @returns {any} - */ - static require(id) { - try { - return require(id); - } - catch { - return null; - } - } - /** - * Asynchronous timeout - * @param {number} time The time in ms to wait - * @returns {Promise} - */ - static wait(time) { - return new Promise((r) => setTimeout(r, time).unref()); - } - static noop() { } // eslint-disable-line @typescript-eslint/no-empty-function - static async getFetch() { - if ("fetch" in globalThis) - return globalThis.fetch; - for (const lib of ["undici", "node-fetch"]) { - try { - return await Promise.resolve().then(() => __importStar(require(lib))).then((res) => res.fetch || res.default?.fetch || res.default); - } - catch { - try { - // eslint-disable-next-line - const res = require(lib); - if (res) - return res.fetch || res.default?.fetch || res.default; - } - catch { - // no? - } - } - } - } -} -exports.Util = Util; diff --git a/helpers/Music/package-lock.json b/helpers/Music/package-lock.json deleted file mode 100644 index d552eecd..00000000 --- a/helpers/Music/package-lock.json +++ /dev/null @@ -1,4577 +0,0 @@ -{ - "name": "music-player", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "music-player", - "version": "1.0.0", - "license": "NO LICENSE", - "dependencies": { - "@discordjs/voice": "^0.11.0", - "libsodium-wrappers": "^0.7.10", - "spotify-url-info": "^3.1.2", - "tiny-typed-emitter": "^2.1.0", - "tslib": "^2.4.0" - }, - "devDependencies": { - "@discordjs/ts-docgen": "^0.4.1", - "@favware/rollup-type-bundler": "^1.0.10", - "@types/node": "^18.6.3", - "@types/ws": "^8.5.3", - "@typescript-eslint/eslint-plugin": "^5.32.0", - "@typescript-eslint/parser": "^5.32.0", - "discord-api-types": "^0.37.0", - "discord.js": "^14.1.2", - "eslint": "^8.21.0", - "gen-esm-wrapper": "^1.1.3", - "husky": "^8.0.1", - "opusscript": "^0.0.8", - "prettier": "^2.7.1", - "rimraf": "^3.0.2", - "ts-node": "^10.9.1", - "typedoc": "^0.23.10", - "typescript": "^4.7.4" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "optional": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "optional": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "optional": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@discordjs/builders": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.2.0.tgz", - "integrity": "sha512-ARy4BUTMU+S0ZI6605NDqfWO+qZqV2d/xfY32z3hVSsd9IaAKJBZ1ILTZLy87oIjW8+gUpQmk9Kt0ZP9bmmd8Q==", - "dev": true, - "dependencies": { - "@sapphire/shapeshift": "^3.5.1", - "discord-api-types": "^0.37.3", - "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.1.0.tgz", - "integrity": "sha512-PQ2Bv6pnT7aGPCKWbvvNRww5tYCGpggIQVgpuF9TdDPeR6n6vQYxezXiLVOS9z2B62Dp4c+qepQ15SgJbLYtCQ==", - "dev": true, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/rest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.1.0.tgz", - "integrity": "sha512-yCrthRTQeUyNThQEpCk7bvQJlwQmz6kU0tf3dcWBv2WX3Bncl41x7Wc+v5b5OsIxfNYq38PvVtWircu9jtYZug==", - "dev": true, - "dependencies": { - "@discordjs/collection": "^1.0.1", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.3", - "file-type": "^17.1.6", - "tslib": "^2.4.0", - "undici": "^5.9.1" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/ts-docgen": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@discordjs/ts-docgen/-/ts-docgen-0.4.1.tgz", - "integrity": "sha512-T+GMJaWvISrEi3Rjg2Tfn1EZeido+SEBv3+393uFLK71koJvwlexAwjzOc0yKz6uanK4mUQyCp35vOIvWsQ1IQ==", - "dev": true, - "dependencies": { - "js-yaml": "^4.1.0", - "typedoc": "^0.22.15" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/typedoc": { - "version": "0.22.18", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz", - "integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==", - "dev": true, - "dependencies": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 12.10.0" - }, - "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" - } - }, - "node_modules/@discordjs/ts-docgen/node_modules/vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", - "dev": true - }, - "node_modules/@discordjs/voice": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.11.0.tgz", - "integrity": "sha512-6+9cj1dxzBJm7WJ9qyG2XZZQ8rcLl6x2caW0C0OxuTtMLAaEDntpb6lqMTFiBg/rDc4Rd59g1w0gJmib33CuHw==", - "dependencies": { - "@types/ws": "^8.5.3", - "discord-api-types": "^0.36.2", - "prism-media": "^1.3.4", - "tslib": "^2.4.0", - "ws": "^8.8.1" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/@discordjs/voice/node_modules/discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", - "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@favware/rollup-type-bundler": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@favware/rollup-type-bundler/-/rollup-type-bundler-1.0.11.tgz", - "integrity": "sha512-QhP2vLE2j1yR1iWz+ltyR3sEFHsXmgTq0X4lsBM6KEibLbfVFPGrP77kNPo3ZLzkmVprFrZOFLRLbqhQiGs0+Q==", - "dev": true, - "dependencies": { - "@sapphire/utilities": "^3.9.2", - "colorette": "^2.0.19", - "commander": "^9.4.0", - "js-yaml": "^4.1.0", - "rollup": "^2.78.1", - "rollup-plugin-dts": "^4.2.2", - "typescript": "^4.7.4" - }, - "bin": { - "rollup-type-bundler": "dist/cli.js", - "rtb": "dist/cli.js" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", - "dev": true, - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/shapeshift": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.6.0.tgz", - "integrity": "sha512-tu2WLRdo5wotHRvsCkspg3qMiP6ETC3Q1dns1Q5V6zKUki+1itq6AbhMwohF9ZcLoYqg+Y8LkgRRtVxxTQVTBQ==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "lodash.uniqwith": "^4.5.0" - }, - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/snowflake": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", - "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==", - "dev": true, - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@sapphire/utilities": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@sapphire/utilities/-/utilities-3.9.3.tgz", - "integrity": "sha512-7+ZjfbmRHqewmH32jpZfzrEuHpvTttTG7WjDl1GUtc4pkOMr0kYybrZmIEZYsUvF7PWzO0GrmOK2zWs3GuJo7g==", - "dev": true, - "engines": { - "node": ">=v14.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.7.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz", - "integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==" - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.2.tgz", - "integrity": "sha512-OwwR8LRwSnI98tdc2z7mJYgY60gf7I9ZfGjN5EjCwwns9bdTuQfAXcsjSB2wSQ/TVNYSGKf4kzVXbNGaZvwiXw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/type-utils": "5.36.2", - "@typescript-eslint/utils": "5.36.2", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.2.tgz", - "integrity": "sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/typescript-estree": "5.36.2", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz", - "integrity": "sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/visitor-keys": "5.36.2" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.2.tgz", - "integrity": "sha512-rPQtS5rfijUWLouhy6UmyNquKDPhQjKsaKH0WnY6hl/07lasj8gPaH2UD8xWkePn6SC+jW2i9c2DZVDnL+Dokw==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.36.2", - "@typescript-eslint/utils": "5.36.2", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.2.tgz", - "integrity": "sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz", - "integrity": "sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/visitor-keys": "5.36.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.2.tgz", - "integrity": "sha512-uNcopWonEITX96v9pefk9DC1bWMdkweeSsewJ6GeC7L6j2t0SJywisgkr9wUTtXk90fi2Eljj90HSHm3OGdGRg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/typescript-estree": "5.36.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz", - "integrity": "sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.36.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "node_modules/commander": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", - "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/discord-api-types": { - "version": "0.37.8", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.8.tgz", - "integrity": "sha512-uhol9KQ2moExZItMpuDMkf0R7sqqNHqcJBFN7S5iSdXBVCMRO7sC0GoyuRrv6ZDBYxoFU6nDy4dv0nld/aysqA==", - "dev": true - }, - "node_modules/discord.js": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", - "integrity": "sha512-CpIwoAAuELiHSgVKRMzsCADS6ZlJwAZ9RlvcJYdEgS00aW36dSvXyBgE+S3pigkc7G+jU6BEalMUWIJFveqrBQ==", - "dev": true, - "dependencies": { - "@discordjs/builders": "^1.2.0", - "@discordjs/collection": "^1.1.0", - "@discordjs/rest": "^1.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.3", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.0", - "undici": "^5.9.1", - "ws": "^8.8.1" - }, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", - "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.1", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", - "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-type": { - "version": "17.1.6", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", - "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", - "dev": true, - "dependencies": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0-alpha.9", - "token-types": "^5.0.0-alpha.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "node_modules/gen-esm-wrapper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gen-esm-wrapper/-/gen-esm-wrapper-1.1.3.tgz", - "integrity": "sha512-LNHZ+QpaCW/0VhABIbXn45V+P8kFvjjwuue9hbV23eOjuFVz6c0FE3z1XpLX9pSjLW7UmtCkXo5F9vhZWVs8oQ==", - "dev": true, - "dependencies": { - "is-valid-identifier": "^2.0.2" - }, - "bin": { - "gen-esm-wrapper": "gen-esm-wrapper.js" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/himalaya": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz", - "integrity": "sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==" - }, - "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-valid-identifier": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-valid-identifier/-/is-valid-identifier-2.0.2.tgz", - "integrity": "sha512-mpS5EGqXOwzXtKAg6I44jIAqeBfntFLxpAth1rrKbxtKyI6LPktyDYpHBI+tHlduhhX/SF26mFXmxQu995QVqg==", - "dev": true, - "dependencies": { - "assert": "^1.4.1" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "optional": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libsodium": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz", - "integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ==" - }, - "node_modules/libsodium-wrappers": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", - "integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==", - "dependencies": { - "libsodium": "^0.7.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "node_modules/lodash.uniqwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", - "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "node_modules/magic-string": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz", - "integrity": "sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/marked": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", - "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/opusscript": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.8.tgz", - "integrity": "sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==", - "devOptional": true - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prism-media": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.4.tgz", - "integrity": "sha512-eW7LXORkTCQznZs+eqe9VjGOrLBxcBPXgNyHXMTSRVhphvd/RrxgIR7WaWt4fkLuhshcdT5KHL88LAfcvS3f5g==", - "peerDependencies": { - "@discordjs/opus": "^0.8.0", - "ffmpeg-static": "^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0", - "node-opus": "^0.3.3", - "opusscript": "^0.0.8" - }, - "peerDependenciesMeta": { - "@discordjs/opus": { - "optional": true - }, - "ffmpeg-static": { - "optional": true - }, - "node-opus": { - "optional": true - }, - "opusscript": { - "optional": true - } - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "dependencies": { - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz", - "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-dts": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.2.2.tgz", - "integrity": "sha512-A3g6Rogyko/PXeKoUlkjxkP++8UDVpgA7C+Tdl77Xj4fgEaIjPSnxRmR53EzvoYy97VMVwLAOcWJudaVAuxneQ==", - "dev": true, - "dependencies": { - "magic-string": "^0.26.1" - }, - "engines": { - "node": ">=v12.22.11" - }, - "funding": { - "url": "https://github.com/sponsors/Swatinem" - }, - "optionalDependencies": { - "@babel/code-frame": "^7.16.7" - }, - "peerDependencies": { - "rollup": "^2.55", - "typescript": "^4.1" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shiki": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", - "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", - "dev": true, - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "^6.0.0" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/spotify-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-3.0.3.tgz", - "integrity": "sha512-mMstJ4dAMki6GbUjg94kp/h9ZH+7T7+ro/KUC00WVh+WKoLgMRrTKLkWMIwCZNO53Xa8DRHQw/6jwYtRZrVI3g==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/spotify-url-info": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.1.8.tgz", - "integrity": "sha512-XxDRxDtTd9p1X22+dWweqB2bf41UVRZgyvq8VmLyY4iuClR/4/LGWOqcqG/zh9BwLUtony4818QrJ2bp2tbUkg==", - "dependencies": { - "himalaya": "~1.1.0", - "spotify-uri": "~3.0.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tiny-typed-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", - "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dev": true, - "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/ts-mixer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", - "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==", - "dev": true - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedoc": { - "version": "0.23.14", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.14.tgz", - "integrity": "sha512-s2I+ZKBET38EctZvbXp2GooHrNaKjWZkrwGEK/sttnOGiKJqU0vHrsdcwLgKZGuo2aedNL3RRPj1LnAAeYscig==", - "dev": true, - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.0.19", - "minimatch": "^5.1.0", - "shiki": "^0.11.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undici": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz", - "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==", - "dev": true, - "engines": { - "node": ">=12.18" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", - "dev": true, - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", - "dev": true - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", - "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "optional": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", - "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", - "dev": true, - "optional": true - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "optional": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "optional": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "optional": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - } - }, - "@discordjs/builders": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.2.0.tgz", - "integrity": "sha512-ARy4BUTMU+S0ZI6605NDqfWO+qZqV2d/xfY32z3hVSsd9IaAKJBZ1ILTZLy87oIjW8+gUpQmk9Kt0ZP9bmmd8Q==", - "dev": true, - "requires": { - "@sapphire/shapeshift": "^3.5.1", - "discord-api-types": "^0.37.3", - "fast-deep-equal": "^3.1.3", - "ts-mixer": "^6.0.1", - "tslib": "^2.4.0" - } - }, - "@discordjs/collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.1.0.tgz", - "integrity": "sha512-PQ2Bv6pnT7aGPCKWbvvNRww5tYCGpggIQVgpuF9TdDPeR6n6vQYxezXiLVOS9z2B62Dp4c+qepQ15SgJbLYtCQ==", - "dev": true - }, - "@discordjs/rest": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.1.0.tgz", - "integrity": "sha512-yCrthRTQeUyNThQEpCk7bvQJlwQmz6kU0tf3dcWBv2WX3Bncl41x7Wc+v5b5OsIxfNYq38PvVtWircu9jtYZug==", - "dev": true, - "requires": { - "@discordjs/collection": "^1.0.1", - "@sapphire/async-queue": "^1.5.0", - "@sapphire/snowflake": "^3.2.2", - "discord-api-types": "^0.37.3", - "file-type": "^17.1.6", - "tslib": "^2.4.0", - "undici": "^5.9.1" - } - }, - "@discordjs/ts-docgen": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@discordjs/ts-docgen/-/ts-docgen-0.4.1.tgz", - "integrity": "sha512-T+GMJaWvISrEi3Rjg2Tfn1EZeido+SEBv3+393uFLK71koJvwlexAwjzOc0yKz6uanK4mUQyCp35vOIvWsQ1IQ==", - "dev": true, - "requires": { - "js-yaml": "^4.1.0", - "typedoc": "^0.22.15" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", - "dev": true, - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" - } - }, - "typedoc": { - "version": "0.22.18", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz", - "integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==", - "dev": true, - "requires": { - "glob": "^8.0.3", - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - } - }, - "vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", - "dev": true - } - } - }, - "@discordjs/voice": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.11.0.tgz", - "integrity": "sha512-6+9cj1dxzBJm7WJ9qyG2XZZQ8rcLl6x2caW0C0OxuTtMLAaEDntpb6lqMTFiBg/rDc4Rd59g1w0gJmib33CuHw==", - "requires": { - "@types/ws": "^8.5.3", - "discord-api-types": "^0.36.2", - "prism-media": "^1.3.4", - "tslib": "^2.4.0", - "ws": "^8.8.1" - }, - "dependencies": { - "discord-api-types": { - "version": "0.36.3", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz", - "integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg==" - } - } - }, - "@eslint/eslintrc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", - "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@favware/rollup-type-bundler": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@favware/rollup-type-bundler/-/rollup-type-bundler-1.0.11.tgz", - "integrity": "sha512-QhP2vLE2j1yR1iWz+ltyR3sEFHsXmgTq0X4lsBM6KEibLbfVFPGrP77kNPo3ZLzkmVprFrZOFLRLbqhQiGs0+Q==", - "dev": true, - "requires": { - "@sapphire/utilities": "^3.9.2", - "colorette": "^2.0.19", - "commander": "^9.4.0", - "js-yaml": "^4.1.0", - "rollup": "^2.78.1", - "rollup-plugin-dts": "^4.2.2", - "typescript": "^4.7.4" - } - }, - "@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/gitignore-to-minimatch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", - "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", - "dev": true - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sapphire/async-queue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz", - "integrity": "sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==", - "dev": true - }, - "@sapphire/shapeshift": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.6.0.tgz", - "integrity": "sha512-tu2WLRdo5wotHRvsCkspg3qMiP6ETC3Q1dns1Q5V6zKUki+1itq6AbhMwohF9ZcLoYqg+Y8LkgRRtVxxTQVTBQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "lodash.uniqwith": "^4.5.0" - } - }, - "@sapphire/snowflake": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.2.2.tgz", - "integrity": "sha512-ula2O0kpSZtX9rKXNeQMrHwNd7E4jPDJYUXmEGTFdMRfyfMw+FPyh04oKMjAiDuOi64bYgVkOV3MjK+loImFhQ==", - "dev": true - }, - "@sapphire/utilities": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@sapphire/utilities/-/utilities-3.9.3.tgz", - "integrity": "sha512-7+ZjfbmRHqewmH32jpZfzrEuHpvTttTG7WjDl1GUtc4pkOMr0kYybrZmIEZYsUvF7PWzO0GrmOK2zWs3GuJo7g==", - "dev": true - }, - "@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/node": { - "version": "18.7.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz", - "integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg==" - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.36.2.tgz", - "integrity": "sha512-OwwR8LRwSnI98tdc2z7mJYgY60gf7I9ZfGjN5EjCwwns9bdTuQfAXcsjSB2wSQ/TVNYSGKf4kzVXbNGaZvwiXw==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/type-utils": "5.36.2", - "@typescript-eslint/utils": "5.36.2", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.36.2.tgz", - "integrity": "sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/typescript-estree": "5.36.2", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz", - "integrity": "sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/visitor-keys": "5.36.2" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.36.2.tgz", - "integrity": "sha512-rPQtS5rfijUWLouhy6UmyNquKDPhQjKsaKH0WnY6hl/07lasj8gPaH2UD8xWkePn6SC+jW2i9c2DZVDnL+Dokw==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "5.36.2", - "@typescript-eslint/utils": "5.36.2", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.36.2.tgz", - "integrity": "sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz", - "integrity": "sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/visitor-keys": "5.36.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.36.2.tgz", - "integrity": "sha512-uNcopWonEITX96v9pefk9DC1bWMdkweeSsewJ6GeC7L6j2t0SJywisgkr9wUTtXk90fi2Eljj90HSHm3OGdGRg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.36.2", - "@typescript-eslint/types": "5.36.2", - "@typescript-eslint/typescript-estree": "5.36.2", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.36.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz", - "integrity": "sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.36.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "commander": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz", - "integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "discord-api-types": { - "version": "0.37.8", - "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.8.tgz", - "integrity": "sha512-uhol9KQ2moExZItMpuDMkf0R7sqqNHqcJBFN7S5iSdXBVCMRO7sC0GoyuRrv6ZDBYxoFU6nDy4dv0nld/aysqA==", - "dev": true - }, - "discord.js": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", - "integrity": "sha512-CpIwoAAuELiHSgVKRMzsCADS6ZlJwAZ9RlvcJYdEgS00aW36dSvXyBgE+S3pigkc7G+jU6BEalMUWIJFveqrBQ==", - "dev": true, - "requires": { - "@discordjs/builders": "^1.2.0", - "@discordjs/collection": "^1.1.0", - "@discordjs/rest": "^1.1.0", - "@sapphire/snowflake": "^3.2.2", - "@types/ws": "^8.5.3", - "discord-api-types": "^0.37.3", - "fast-deep-equal": "^3.1.3", - "lodash.snakecase": "^4.1.1", - "tslib": "^2.4.0", - "undici": "^5.9.1", - "ws": "^8.8.1" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", - "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.3.1", - "@humanwhocodes/config-array": "^0.10.4", - "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", - "@humanwhocodes/module-importer": "^1.0.1", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", - "globby": "^11.1.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-type": { - "version": "17.1.6", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz", - "integrity": "sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==", - "dev": true, - "requires": { - "readable-web-to-node-stream": "^3.0.2", - "strtok3": "^7.0.0-alpha.9", - "token-types": "^5.0.0-alpha.2" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "gen-esm-wrapper": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gen-esm-wrapper/-/gen-esm-wrapper-1.1.3.tgz", - "integrity": "sha512-LNHZ+QpaCW/0VhABIbXn45V+P8kFvjjwuue9hbV23eOjuFVz6c0FE3z1XpLX9pSjLW7UmtCkXo5F9vhZWVs8oQ==", - "dev": true, - "requires": { - "is-valid-identifier": "^2.0.2" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "himalaya": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz", - "integrity": "sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==" - }, - "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", - "dev": true - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-valid-identifier": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-valid-identifier/-/is-valid-identifier-2.0.2.tgz", - "integrity": "sha512-mpS5EGqXOwzXtKAg6I44jIAqeBfntFLxpAth1rrKbxtKyI6LPktyDYpHBI+tHlduhhX/SF26mFXmxQu995QVqg==", - "dev": true, - "requires": { - "assert": "^1.4.1" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "optional": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "libsodium": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz", - "integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ==" - }, - "libsodium-wrappers": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", - "integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==", - "requires": { - "libsodium": "^0.7.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "lodash.uniqwith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniqwith/-/lodash.uniqwith-4.5.0.tgz", - "integrity": "sha512-7lYL8bLopMoy4CTICbxygAUq6CdRJ36vFc80DucPueUee+d5NBRxz3FdT9Pes/HEx5mPoT9jwnsEJWz1N7uq7Q==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, - "magic-string": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz", - "integrity": "sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "marked": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.0.tgz", - "integrity": "sha512-+Z6KDjSPa6/723PQYyc1axYZpYYpDnECDaU6hkaf5gqBieBkMKYReL5hteF2QizhlMbgbo8umXl/clZ67+GlsA==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "opusscript": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.8.tgz", - "integrity": "sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==", - "devOptional": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "peek-readable": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz", - "integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true - }, - "prism-media": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.4.tgz", - "integrity": "sha512-eW7LXORkTCQznZs+eqe9VjGOrLBxcBPXgNyHXMTSRVhphvd/RrxgIR7WaWt4fkLuhshcdT5KHL88LAfcvS3f5g==", - "requires": {} - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", - "dev": true, - "requires": { - "readable-stream": "^3.6.0" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz", - "integrity": "sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA==", - "dev": true, - "requires": { - "fsevents": "~2.3.2" - } - }, - "rollup-plugin-dts": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.2.2.tgz", - "integrity": "sha512-A3g6Rogyko/PXeKoUlkjxkP++8UDVpgA7C+Tdl77Xj4fgEaIjPSnxRmR53EzvoYy97VMVwLAOcWJudaVAuxneQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "magic-string": "^0.26.1" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shiki": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", - "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", - "dev": true, - "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "^6.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spotify-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-3.0.3.tgz", - "integrity": "sha512-mMstJ4dAMki6GbUjg94kp/h9ZH+7T7+ro/KUC00WVh+WKoLgMRrTKLkWMIwCZNO53Xa8DRHQw/6jwYtRZrVI3g==" - }, - "spotify-url-info": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.1.8.tgz", - "integrity": "sha512-XxDRxDtTd9p1X22+dWweqB2bf41UVRZgyvq8VmLyY4iuClR/4/LGWOqcqG/zh9BwLUtony4818QrJ2bp2tbUkg==", - "requires": { - "himalaya": "~1.1.0", - "spotify-uri": "~3.0.3" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "strtok3": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz", - "integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==", - "dev": true, - "requires": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "tiny-typed-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", - "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "token-types": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz", - "integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==", - "dev": true, - "requires": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - } - }, - "ts-mixer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz", - "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg==", - "dev": true - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typedoc": { - "version": "0.23.14", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.14.tgz", - "integrity": "sha512-s2I+ZKBET38EctZvbXp2GooHrNaKjWZkrwGEK/sttnOGiKJqU0vHrsdcwLgKZGuo2aedNL3RRPj1LnAAeYscig==", - "dev": true, - "requires": { - "lunr": "^2.3.9", - "marked": "^4.0.19", - "minimatch": "^5.1.0", - "shiki": "^0.11.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true - }, - "undici": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.10.0.tgz", - "integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", - "dev": true - }, - "vscode-textmate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", - "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", - "requires": {} - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/helpers/Music/package.json b/helpers/Music/package.json deleted file mode 100644 index d80e6a49..00000000 --- a/helpers/Music/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "music-player", - "version": "1.0.0", - "description": "music player", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "files": [ - "dist/" - ], - "module": "dist/index.mjs", - "exports": { - ".": { - "require": "./dist/index.js", - "import": "./dist/index.mjs" - }, - "./smoothVolume": "./dist/smoothVolume.js", - "./src/*": "./dist/*", - "./dist/*": "./dist/*" - }, - "scripts": { - "dev": "cd examples/test && ts-node index.ts", - "build": "rimraf dist && tsc && npm run build:esm", - "build:check": "tsc --noEmit --incremental false", - "prepublishOnly": "rollup-type-bundler -e stream", - "build:esm": "gen-esm-wrapper ./dist/index.js ./dist/index.mjs", - "format": "prettier --write \"src/**/*.ts\"", - "docs": "typedoc --json docs/typedoc.json src/index.ts", - "postdocs": "node scripts/docgen.js", - "lint": "eslint src --ext .ts", - "prepare": "husky install", - "lint:fix": "eslint src --ext .ts --fix" - }, - "author": "Jonny_Bro", - "license": "NO LICENSE", - "dependencies": { - "@discordjs/voice": "^0.11.0", - "libsodium-wrappers": "^0.7.10", - "spotify-url-info": "^3.1.2", - "tiny-typed-emitter": "^2.1.0", - "tslib": "^2.4.0" - }, - "devDependencies": { - "@discordjs/ts-docgen": "^0.4.1", - "@favware/rollup-type-bundler": "^1.0.10", - "@types/node": "^18.6.3", - "@types/ws": "^8.5.3", - "@typescript-eslint/eslint-plugin": "^5.32.0", - "@typescript-eslint/parser": "^5.32.0", - "discord-api-types": "^0.37.0", - "discord.js": "^14.1.2", - "eslint": "^8.21.0", - "gen-esm-wrapper": "^1.1.3", - "husky": "^8.0.1", - "opusscript": "^0.0.8", - "prettier": "^2.7.1", - "rimraf": "^3.0.2", - "ts-node": "^10.9.1", - "typedoc": "^0.23.10", - "typescript": "^4.7.4" - } -} diff --git a/helpers/Music/src/Player.ts b/helpers/Music/src/Player.ts deleted file mode 100644 index aa938703..00000000 --- a/helpers/Music/src/Player.ts +++ /dev/null @@ -1,607 +0,0 @@ -import { Client, Collection, GuildResolvable, Snowflake, User, VoiceState, IntentsBitField } from "discord.js"; -import { TypedEmitter as EventEmitter } from "tiny-typed-emitter"; -import { Queue } from "./Structures/Queue"; -import { VoiceUtils } from "./VoiceInterface/VoiceUtils"; -import { PlayerEvents, PlayerOptions, QueryType, SearchOptions, PlayerInitOptions, PlayerSearchResult, PlaylistInitData } from "./types/types"; -import Track from "./Structures/Track"; -import play, { SoundCloudPlaylist, YouTubePlayList } from "play-dl"; -import Spotify from "spotify-url-info"; -import { QueryResolver } from "./utils/QueryResolver"; -import { Util } from "./utils/Util"; -import { PlayerError, ErrorStatusCode } from "./Structures/PlayerError"; -import { Playlist } from "./Structures/Playlist"; -import { ExtractorModel } from "./Structures/ExtractorModel"; -import { generateDependencyReport } from "@discordjs/voice"; - -class Player extends EventEmitter { - public readonly client: Client; - public readonly options: PlayerInitOptions = { - autoRegisterExtractor: true, - connectionTimeout: 20000 - }; - public readonly queues = new Collection(); - public readonly voiceUtils = new VoiceUtils(); - public readonly extractors = new Collection(); - public requiredEvents = ["error", "connectionError"] as string[]; - - /** - * Creates new Discord Player - * @param {Client} client The Discord Client - * @param {PlayerInitOptions} [options] The player init options - */ - constructor(client: Client, options: PlayerInitOptions = {}) { - super(); - - /** - * The discord.js client - * @type {Client} - */ - this.client = client; - - if (this.client?.options?.intents && !new IntentsBitField(this.client?.options?.intents).has(IntentsBitField.Flags.GuildVoiceStates)) { - throw new PlayerError('client is missing "GuildVoiceStates" intent'); - } - - /** - * The extractors collection - * @type {ExtractorModel} - */ - this.options = Object.assign(this.options, options); - - this.client.on("voiceStateUpdate", this._handleVoiceState.bind(this)); - - if (this.options?.autoRegisterExtractor) { - let nv: any; // eslint-disable-line @typescript-eslint/no-explicit-any - - if ((nv = Util.require("@discord-player/extractor"))) { - ["Attachment", "Facebook", "Reverbnation", "Vimeo"].forEach((ext) => void this.use(ext, nv[ext])); - } - } - } - - /** - * Handles voice state update - * @param {VoiceState} oldState The old voice state - * @param {VoiceState} newState The new voice state - * @returns {void} - * @private - */ - private _handleVoiceState(oldState: VoiceState, newState: VoiceState): void { - const queue = this.getQueue(oldState.guild.id); - if (!queue || !queue.connection) return; - - if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) { - try { - queue.destroy(); - } catch { - /* noop */ - } - return void this.emit("botDisconnect", queue); - } - - if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (!oldState.serverMute && newState.serverMute) { - // state.serverMute can be null - queue.setPaused(!!newState.serverMute); - } else if (!oldState.suppress && newState.suppress) { - // state.suppress can be null - queue.setPaused(!!newState.suppress); - if (newState.suppress) { - newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop); - } - } - } - - if (oldState.channelId === newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (!oldState.serverMute && newState.serverMute) { - // state.serverMute can be null - queue.setPaused(!!newState.serverMute); - } else if (!oldState.suppress && newState.suppress) { - // state.suppress can be null - queue.setPaused(!!newState.suppress); - if (newState.suppress) { - newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop); - } - } - } - - if (queue.connection && !newState.channelId && oldState.channelId === queue.connection.channel.id) { - if (!Util.isVoiceEmpty(queue.connection.channel)) return; - const timeout = setTimeout(() => { - if (!Util.isVoiceEmpty(queue.connection.channel)) return; - if (!this.queues.has(queue.guild.id)) return; - if (queue.options.leaveOnEmpty) queue.destroy(true); - this.emit("channelEmpty", queue); - }, queue.options.leaveOnEmptyCooldown || 0).unref(); - queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout); - } - - if (queue.connection && newState.channelId && newState.channelId === queue.connection.channel.id) { - const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`); - const channelEmpty = Util.isVoiceEmpty(queue.connection.channel); - if (!channelEmpty && emptyTimeout) { - clearTimeout(emptyTimeout); - queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`); - } - } - - if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId && newState.member.id === newState.guild.members.me.id) { - if (queue.connection && newState.member.id === newState.guild.members.me.id) queue.connection.channel = newState.channel; - const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`); - const channelEmpty = Util.isVoiceEmpty(queue.connection.channel); - if (!channelEmpty && emptyTimeout) { - clearTimeout(emptyTimeout); - queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`); - } else { - const timeout = setTimeout(() => { - if (queue.connection && !Util.isVoiceEmpty(queue.connection.channel)) return; - if (!this.queues.has(queue.guild.id)) return; - if (queue.options.leaveOnEmpty) queue.destroy(true); - this.emit("channelEmpty", queue); - }, queue.options.leaveOnEmptyCooldown || 0).unref(); - queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout); - } - } - } - - /** - * Creates a queue for a guild if not available, else returns existing queue - * @param {GuildResolvable} guild The guild - * @param {PlayerOptions} queueInitOptions Queue init options - * @returns {Queue} - */ - createQueue(guild: GuildResolvable, queueInitOptions: PlayerOptions & { metadata?: T } = {}): Queue { - guild = this.client.guilds.resolve(guild); - if (!guild) throw new PlayerError("Unknown Guild", ErrorStatusCode.UNKNOWN_GUILD); - if (this.queues.has(guild.id)) return this.queues.get(guild.id) as Queue; - - const _meta = queueInitOptions.metadata; - delete queueInitOptions["metadata"]; - queueInitOptions.volumeSmoothness ??= 0.08; - const queue = new Queue(this, guild, queueInitOptions); - queue.metadata = _meta; - this.queues.set(guild.id, queue); - - return queue as Queue; - } - - /** - * Returns the queue if available - * @param {GuildResolvable} guild The guild id - * @returns {Queue} - */ - getQueue(guild: GuildResolvable) { - guild = this.client.guilds.resolve(guild); - if (!guild) throw new PlayerError("Unknown Guild", ErrorStatusCode.UNKNOWN_GUILD); - return this.queues.get(guild.id) as Queue; - } - - /** - * Deletes a queue and returns deleted queue object - * @param {GuildResolvable} guild The guild id to remove - * @returns {Queue} - */ - deleteQueue(guild: GuildResolvable) { - guild = this.client.guilds.resolve(guild); - if (!guild) throw new PlayerError("Unknown Guild", ErrorStatusCode.UNKNOWN_GUILD); - const prev = this.getQueue(guild); - - try { - prev.destroy(); - } catch {} // eslint-disable-line no-empty - this.queues.delete(guild.id); - - return prev; - } - - /** - * @typedef {object} PlayerSearchResult - * @property {Playlist} [playlist] The playlist (if any) - * @property {Track[]} tracks The tracks - */ - /** - * Search tracks - * @param {string|Track} query The search query - * @param {SearchOptions} options The search options - * @returns {Promise} - */ - async search(query: string | Track, options: SearchOptions): Promise { - if (query instanceof Track) return { playlist: query.playlist || null, tracks: [query] }; - if (!options) throw new PlayerError("DiscordPlayer#search needs search options!", ErrorStatusCode.INVALID_ARG_TYPE); - options.requestedBy = this.client.users.resolve(options.requestedBy); - if (!("searchEngine" in options)) options.searchEngine = QueryType.AUTO; - if (typeof options.searchEngine === "string" && this.extractors.has(options.searchEngine)) { - const extractor = this.extractors.get(options.searchEngine); - if (!extractor.validate(query)) return { playlist: null, tracks: [] }; - const data = await extractor.handle(query); - if (data && data.data.length) { - const playlist = !data.playlist - ? null - : new Playlist(this, { - ...data.playlist, - tracks: [] - }); - - const tracks = data.data.map( - (m) => - new Track(this, { - ...m, - requestedBy: options.requestedBy as User, - duration: Util.buildTimeCode(Util.parseMS(m.duration)), - playlist: playlist - }) - ); - - if (playlist) playlist.tracks = tracks; - - return { playlist: playlist, tracks: tracks }; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - for (const [_, extractor] of this.extractors) { - if (options.blockExtractor) break; - if (!extractor.validate(query)) continue; - const data = await extractor.handle(query); - if (data && data.data.length) { - const playlist = !data.playlist - ? null - : new Playlist(this, { - ...data.playlist, - tracks: [] - }); - - const tracks = data.data.map( - (m) => - new Track(this, { - ...m, - requestedBy: options.requestedBy as User, - duration: Util.buildTimeCode(Util.parseMS(m.duration)), - playlist: playlist - }) - ); - - if (playlist) playlist.tracks = tracks; - - return { playlist: playlist, tracks: tracks }; - } - } - - const qt = options.searchEngine === QueryType.AUTO ? await QueryResolver.resolve(query) : options.searchEngine; - switch (qt) { - case QueryType.YOUTUBE_VIDEO: { - const info = await play.video_info(query).catch(Util.noop); - if (!info) return { playlist: null, tracks: [] }; - - const track = new Track(this, { - title: info.video_details.title, - description: info.video_details.description, - author: info.video_details.channel?.name, - url: info.video_details.url, - requestedBy: options.requestedBy as User, - thumbnail: Util.last(info.video_details.thumbnails)?.url, - views: info.video_details.views || 0, - duration: Util.buildTimeCode(Util.parseMS(info.video_details.durationInSec * 1000)), - source: "youtube", - raw: info - }); - - return { playlist: null, tracks: [track] }; - } - case QueryType.YOUTUBE_SEARCH: { - const videos = await play.search(query, { - limit: 10, - source: { youtube: "video" } - }).catch(Util.noop); - if (!videos) return { playlist: null, tracks: [] }; - - const tracks = videos.map(m => { - (m as any).source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any - return new Track(this, { - title: m.title, - description: m.description, - author: m.channel?.name, - url: m.url, - requestedBy: options.requestedBy as User, - thumbnail: Util.last(m.thumbnails).url, - views: m.views, - duration: m.durationRaw, - source: "youtube", - raw: m - }); - }); - - return { playlist: null, tracks, searched: true }; - } - case QueryType.SOUNDCLOUD_TRACK: - case QueryType.SOUNDCLOUD_SEARCH: { - const result = await QueryResolver.resolve(query) === QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await play.search(query, { - limit: 5, - source: { soundcloud: "tracks" } - }).catch(() => []); - if (!result || !result.length) return { playlist: null, tracks: [] }; - const res: Track[] = []; - - for (const r of result) { - const trackInfo = await play.soundcloud(r.url).catch(Util.noop); - if (!trackInfo) continue; - - const track = new Track(this, { - title: trackInfo.name, - url: trackInfo.url, - duration: Util.buildTimeCode(Util.parseMS(trackInfo.durationInMs)), - description: "", - thumbnail: trackInfo.user.thumbnail, - views: 0, - author: trackInfo.user.name, - requestedBy: options.requestedBy, - source: "soundcloud", - engine: trackInfo - }); - - res.push(track); - } - - return { playlist: null, tracks: res }; - } - case QueryType.SPOTIFY_SONG: { - const spotifyData = await Spotify(await Util.getFetch()) - .getData(query) - .catch(Util.noop); - if (!spotifyData) return { playlist: null, tracks: [] }; - const spotifyTrack = new Track(this, { - title: spotifyData.name, - description: spotifyData.description ?? "", - author: spotifyData.artists[0]?.name ?? "Unknown Artist", - url: spotifyData.external_urls?.spotify ?? query, - thumbnail: - spotifyData.album?.images[0]?.url ?? spotifyData.preview_url?.length - ? `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}` - : "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util.buildTimeCode(Util.parseMS(spotifyData.duration_ms)), - views: 0, - requestedBy: options.requestedBy, - source: "spotify" - }); - - return { playlist: null, tracks: [spotifyTrack] }; - } - case QueryType.SPOTIFY_PLAYLIST: - case QueryType.SPOTIFY_ALBUM: { - const spotifyPlaylist = await Spotify(await Util.getFetch()) - .getData(query) - .catch(Util.noop); - if (!spotifyPlaylist) return { playlist: null, tracks: [] }; - - const playlist = new Playlist(this, { - title: spotifyPlaylist.name ?? spotifyPlaylist.title, - description: spotifyPlaylist.description ?? "", - thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - type: spotifyPlaylist.type, - source: "spotify", - author: - spotifyPlaylist.type !== "playlist" - ? { - name: spotifyPlaylist.artists[0]?.name ?? "Unknown Artist", - url: spotifyPlaylist.artists[0]?.external_urls?.spotify ?? null - } - : { - name: spotifyPlaylist.owner?.display_name ?? spotifyPlaylist.owner?.id ?? "Unknown Artist", - url: spotifyPlaylist.owner?.external_urls?.spotify ?? null - }, - tracks: [], - id: spotifyPlaylist.id, - url: spotifyPlaylist.external_urls?.spotify ?? query, - rawPlaylist: spotifyPlaylist - }); - - if (spotifyPlaylist.type !== "playlist") { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - playlist.tracks = spotifyPlaylist.tracks.items.map((m: any) => { - const data = new Track(this, { - title: m.name ?? "", - description: m.description ?? "", - author: m.artists[0]?.name ?? "Unknown Artist", - url: m.external_urls?.spotify ?? query, - thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util.buildTimeCode(Util.parseMS(m.duration_ms)), - views: 0, - requestedBy: options.requestedBy as User, - playlist, - source: "spotify" - }); - - return data; - }) as Track[]; - } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - playlist.tracks = spotifyPlaylist.tracks.items.map((m: any) => { - const data = new Track(this, { - title: m.track.name ?? "", - description: m.track.description ?? "", - author: m.track.artists?.[0]?.name ?? "Unknown Artist", - url: m.track.external_urls?.spotify ?? query, - thumbnail: m.track.album?.images?.[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg", - duration: Util.buildTimeCode(Util.parseMS(m.track.duration_ms)), - views: 0, - requestedBy: options.requestedBy as User, - playlist, - source: "spotify" - }); - - return data; - }) as Track[]; - } - - return { playlist: playlist, tracks: playlist.tracks }; - } - case QueryType.SOUNDCLOUD_PLAYLIST: { - const data = await play.soundcloud(query).catch(Util.noop) as unknown as SoundCloudPlaylist; - if (!data) return { playlist: null, tracks: [] }; - - const res = new Playlist(this, { - title: data.name, - description: "", - thumbnail: "https://soundcloud.com/pwa-icon-192.png", - type: "playlist", - source: "soundcloud", - author: { - name: data.user.name ?? "Unknown Owner", - url: data.user.url - }, - tracks: [], - id: `${data.id}`, // stringified - url: data.url, - rawPlaylist: data - }); - - const songs = await data.all_tracks(); - for (const song of songs) { - const track = new Track(this, { - title: song.name, - description: "", - author: song.publisher.name ?? "Unknown Publisher", - url: song.url, - thumbnail: song.thumbnail, - duration: Util.buildTimeCode(Util.parseMS(song.durationInMs)), - views: 0, - requestedBy: options.requestedBy, - playlist: res, - source: "soundcloud", - engine: song - }); - res.tracks.push(track); - } - - return { playlist: res, tracks: res.tracks }; - } - case QueryType.YOUTUBE_PLAYLIST: { - const ytpl = await play.playlist_info(query, { incomplete: true }).catch(Util.noop) as unknown as YouTubePlayList; - if (!ytpl) return { playlist: null, tracks: [] }; - - const playlist: Playlist = new Playlist(this, { - title: ytpl.title, - thumbnail: ytpl.thumbnail as unknown as string, - description: "", - type: "playlist", - source: "youtube", - author: { - name: ytpl.channel.name, - url: ytpl.channel.url - }, - tracks: [], - id: ytpl.id, - url: ytpl.url, - rawPlaylist: ytpl - }); - - const videos = await ytpl.all_videos(); - playlist.tracks = videos.map(video => - new Track(this, { - title: video.title, - description: video.description, - author: video.channel?.name, - url: video.url, - requestedBy: options.requestedBy as User, - thumbnail: Util.last(video.thumbnails).url, - views: video.views, - duration: video.durationRaw, - raw: video, - playlist: playlist, - source: "youtube" - })); - - return { playlist: playlist, tracks: playlist.tracks }; - } - default: - return { playlist: null, tracks: [] }; - } - } - - /** - * Registers extractor - * @param {string} extractorName The extractor name - * @param {ExtractorModel|any} extractor The extractor object - * @param {boolean} [force=false] Overwrite existing extractor with this name (if available) - * @returns {ExtractorModel} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - use(extractorName: string, extractor: ExtractorModel | any, force = false): ExtractorModel { - if (!extractorName) throw new PlayerError("Cannot use unknown extractor!", ErrorStatusCode.UNKNOWN_EXTRACTOR); - if (this.extractors.has(extractorName) && !force) return this.extractors.get(extractorName); - if (extractor instanceof ExtractorModel) { - this.extractors.set(extractorName, extractor); - return extractor; - } - - for (const method of ["validate", "getInfo"]) { - if (typeof extractor[method] !== "function") throw new PlayerError("Invalid extractor data!", ErrorStatusCode.INVALID_EXTRACTOR); - } - - const model = new ExtractorModel(extractorName, extractor); - this.extractors.set(model.name, model); - - return model; - } - - /** - * Removes registered extractor - * @param {string} extractorName The extractor name - * @returns {ExtractorModel} - */ - unuse(extractorName: string) { - if (!this.extractors.has(extractorName)) throw new PlayerError(`Cannot find extractor "${extractorName}"`, ErrorStatusCode.UNKNOWN_EXTRACTOR); - const prev = this.extractors.get(extractorName); - this.extractors.delete(extractorName); - return prev; - } - - /** - * Generates a report of the dependencies used by the `@discordjs/voice` module. Useful for debugging. - * @returns {string} - */ - scanDeps() { - const line = "-".repeat(50); - const depsReport = generateDependencyReport(); - const extractorReport = this.extractors - .map((m) => { - return `${m.name} :: ${m.version || "0.1.0"}`; - }) - .join("\n"); - return `${depsReport}\n${line}\nLoaded Extractors:\n${extractorReport || "None"}`; - } - - emit(eventName: U, ...args: Parameters): boolean { - if (this.requiredEvents.includes(eventName) && !super.eventNames().includes(eventName)) { - // eslint-disable-next-line no-console - console.error(...args); - process.emitWarning(`[DiscordPlayerWarning] Unhandled "${eventName}" event! Events ${this.requiredEvents.map((m) => `"${m}"`).join(", ")} must have event listeners!`); - return false; - } else { - return super.emit(eventName, ...args); - } - } - - /** - * Resolves queue - * @param {GuildResolvable|Queue} queueLike Queue like object - * @returns {Queue} - */ - resolveQueue(queueLike: GuildResolvable | Queue): Queue { - return this.getQueue(queueLike instanceof Queue ? queueLike.guild : queueLike); - } - - *[Symbol.iterator]() { - yield* Array.from(this.queues.values()); - } - - /** - * Creates `Playlist` instance - * @param data The data to initialize a playlist - */ - createPlaylist(data: PlaylistInitData) { - return new Playlist(this, data); - } -} - -export { Player }; diff --git a/helpers/Music/src/Structures/ExtractorModel.ts b/helpers/Music/src/Structures/ExtractorModel.ts deleted file mode 100644 index dc816180..00000000 --- a/helpers/Music/src/Structures/ExtractorModel.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { ExtractorModelData } from "../types/types"; - -class ExtractorModel { - name: string; - private _raw: any; // eslint-disable-line @typescript-eslint/no-explicit-any - - /** - * Model for raw Discord Player extractors - * @param {string} extractorName Name of the extractor - * @param {object} data Extractor object - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - constructor(extractorName: string, data: any) { - /** - * The extractor name - * @type {string} - */ - this.name = extractorName; - - /** - * The raw model - * @name ExtractorModel#_raw - * @type {any} - * @private - */ - Object.defineProperty(this, "_raw", { value: data, configurable: false, writable: false, enumerable: false }); - } - - /** - * Method to handle requests from `Player.play()` - * @param {string} query Query to handle - * @returns {Promise} - */ - async handle(query: string): Promise { - const data = await this._raw.getInfo(query); - if (!data) return null; - - return { - playlist: data.playlist ?? null, - data: - (data.info as Omit["data"])?.map((m) => ({ - title: m.title as string, - duration: m.duration as number, - thumbnail: m.thumbnail as string, - engine: m.engine, - views: m.views as number, - author: m.author as string, - description: m.description as string, - url: m.url as string, - source: m.source || "arbitrary" - })) ?? [] - }; - } - - /** - * Method used by Discord Player to validate query with this extractor - * @param {string} query The query to validate - * @returns {boolean} - */ - validate(query: string): boolean { - return Boolean(this._raw.validate(query)); - } - - /** - * The extractor version - * @type {string} - */ - get version(): string { - return this._raw.version ?? "0.0.0"; - } -} - -export { ExtractorModel }; diff --git a/helpers/Music/src/Structures/PlayerError.ts b/helpers/Music/src/Structures/PlayerError.ts deleted file mode 100644 index da36da6f..00000000 --- a/helpers/Music/src/Structures/PlayerError.ts +++ /dev/null @@ -1,53 +0,0 @@ -export enum ErrorStatusCode { - STREAM_ERROR = "StreamError", - AUDIO_PLAYER_ERROR = "AudioPlayerError", - PLAYER_ERROR = "PlayerError", - NO_AUDIO_RESOURCE = "NoAudioResource", - UNKNOWN_GUILD = "UnknownGuild", - INVALID_ARG_TYPE = "InvalidArgType", - UNKNOWN_EXTRACTOR = "UnknownExtractor", - INVALID_EXTRACTOR = "InvalidExtractor", - INVALID_CHANNEL_TYPE = "InvalidChannelType", - INVALID_TRACK = "InvalidTrack", - UNKNOWN_REPEAT_MODE = "UnknownRepeatMode", - TRACK_NOT_FOUND = "TrackNotFound", - NO_CONNECTION = "NoConnection", - DESTROYED_QUEUE = "DestroyedQueue" -} - -export class PlayerError extends Error { - message: string; - statusCode: ErrorStatusCode; - createdAt = new Date(); - - constructor(message: string, code: ErrorStatusCode = ErrorStatusCode.PLAYER_ERROR) { - super(); - - this.message = `[${code}] ${message}`; - this.statusCode = code; - this.name = code; - - Error.captureStackTrace(this); - } - - get createdTimestamp() { - return this.createdAt.getTime(); - } - - valueOf() { - return this.statusCode; - } - - toJSON() { - return { - stack: this.stack, - code: this.statusCode, - message: this.message, - created: this.createdTimestamp - }; - } - - toString() { - return this.stack; - } -} diff --git a/helpers/Music/src/Structures/Playlist.ts b/helpers/Music/src/Structures/Playlist.ts deleted file mode 100644 index d76dd668..00000000 --- a/helpers/Music/src/Structures/Playlist.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { Player } from "../Player"; -import { Track } from "./Track"; -import { PlaylistInitData, PlaylistJSON, TrackJSON, TrackSource } from "../types/types"; - -class Playlist { - public readonly player: Player; - public tracks: Track[]; - public title: string; - public description: string; - public thumbnail: string; - public type: "album" | "playlist"; - public source: TrackSource; - public author: { - name: string; - url: string; - }; - public id: string; - public url: string; - public readonly rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any - - /** - * Playlist constructor - * @param {Player} player The player - * @param {PlaylistInitData} data The data - */ - constructor(player: Player, data: PlaylistInitData) { - /** - * The player - * @name Playlist#player - * @type {Player} - * @readonly - */ - this.player = player; - - /** - * The tracks in this playlist - * @name Playlist#tracks - * @type {Track[]} - */ - this.tracks = data.tracks ?? []; - - /** - * The author of this playlist - * @name Playlist#author - * @type {object} - */ - this.author = data.author; - - /** - * The description - * @name Playlist#description - * @type {string} - */ - this.description = data.description; - - /** - * The thumbnail of this playlist - * @name Playlist#thumbnail - * @type {string} - */ - this.thumbnail = data.thumbnail; - - /** - * The playlist type: - * - `album` - * - `playlist` - * @name Playlist#type - * @type {string} - */ - this.type = data.type; - - /** - * The source of this playlist: - * - `youtube` - * - `soundcloud` - * - `spotify` - * - `arbitrary` - * @name Playlist#source - * @type {string} - */ - this.source = data.source; - - /** - * The playlist id - * @name Playlist#id - * @type {string} - */ - this.id = data.id; - - /** - * The playlist url - * @name Playlist#url - * @type {string} - */ - this.url = data.url; - - /** - * The playlist title - * @type {string} - */ - this.title = data.title; - - /** - * @name Playlist#rawPlaylist - * @type {any} - * @readonly - */ - } - - *[Symbol.iterator]() { - yield* this.tracks; - } - - /** - * JSON representation of this playlist - * @param {boolean} [withTracks=true] If it should build json with tracks - * @returns {PlaylistJSON} - */ - toJSON(withTracks = true) { - const payload = { - id: this.id, - url: this.url, - title: this.title, - description: this.description, - thumbnail: this.thumbnail, - type: this.type, - source: this.source, - author: this.author, - tracks: [] as TrackJSON[] - }; - - if (withTracks) payload.tracks = this.tracks.map((m) => m.toJSON(true)); - - return payload as PlaylistJSON; - } -} - -export { Playlist }; diff --git a/helpers/Music/src/Structures/Queue.ts b/helpers/Music/src/Structures/Queue.ts deleted file mode 100644 index f55d836a..00000000 --- a/helpers/Music/src/Structures/Queue.ts +++ /dev/null @@ -1,776 +0,0 @@ -import { Collection, Guild, StageChannel, VoiceChannel, SnowflakeUtil, GuildChannelResolvable, ChannelType } from "discord.js"; -import { Player } from "../Player"; -import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher"; -import Track from "./Track"; -import { PlayerOptions, PlayerProgressbarOptions, PlayOptions, QueueFilters, QueueRepeatMode, TrackSource } from "../types/types"; -import { AudioResource, StreamType } from "@discordjs/voice"; -import play from "play-dl"; -import { Util } from "../utils/Util"; -import AudioFilters from "../utils/AudioFilters"; -import { PlayerError, ErrorStatusCode } from "./PlayerError"; -import type { Readable } from "stream"; -import { VolumeTransformer } from "../VoiceInterface/VolumeTransformer"; -import { createFFmpegStream } from "../utils/FFmpegStream"; - -class Queue { - public readonly guild: Guild; - public readonly player: Player; - public connection: StreamDispatcher; - public tracks: Track[] = []; - public previousTracks: Track[] = []; - public options: PlayerOptions; - public playing = false; - public metadata?: T = null; - public repeatMode: QueueRepeatMode = 0; - public readonly id = SnowflakeUtil.generate().toString(); - private _streamTime = 0; - public _cooldownsTimeout = new Collection(); - private _activeFilters: any[] = []; // eslint-disable-line @typescript-eslint/no-explicit-any - private _filtersUpdate = false; - #lastVolume = 0; - #destroyed = false; - public onBeforeCreateStream: (track: Track, source: TrackSource, queue: Queue) => Promise = null; - - /** - * Queue constructor - * @param {Player} player The player that instantiated this queue - * @param {Guild} guild The guild that instantiated this queue - * @param {PlayerOptions} [options] Player options for the queue - */ - constructor(player: Player, guild: Guild, options: PlayerOptions = {}) { - /** - * The player that instantiated this queue - * @type {Player} - * @readonly - */ - this.player = player; - - /** - * The guild that instantiated this queue - * @type {Guild} - * @readonly - */ - this.guild = guild; - - /** - * The player options for this queue - * @type {PlayerOptions} - */ - this.options = {}; - - /** - * Queue repeat mode - * @type {QueueRepeatMode} - * @name Queue#repeatMode - */ - - /** - * Queue metadata - * @type {any} - * @name Queue#metadata - */ - - /** - * Previous tracks - * @type {Track[]} - * @name Queue#previousTracks - */ - - /** - * Regular tracks - * @type {Track[]} - * @name Queue#tracks - */ - - /** - * The connection - * @type {StreamDispatcher} - * @name Queue#connection - */ - - /** - * The ID of this queue - * @type {Snowflake} - * @name Queue#id - */ - - Object.assign( - this.options, - { - leaveOnEnd: true, - leaveOnStop: true, - leaveOnEmpty: true, - leaveOnEmptyCooldown: 1000, - autoSelfDeaf: true, - ytdlOptions: { - highWaterMark: 1 << 25 - }, - initialVolume: 100, - bufferingTimeout: 3000, - spotifyBridge: true, - disableVolume: false - } as PlayerOptions, - options - ); - - if ("onBeforeCreateStream" in this.options) this.onBeforeCreateStream = this.options.onBeforeCreateStream; - - this.player.emit("debug", this, `Queue initialized:\n\n${this.player.scanDeps()}`); - } - - /** - * Returns current track - * @type {Track} - */ - get current() { - if (this.#watchDestroyed()) return; - return this.connection.audioResource?.metadata ?? this.tracks[0]; - } - - /** - * If this queue is destroyed - * @type {boolean} - */ - get destroyed() { - return this.#destroyed; - } - - /** - * Returns current track - * @returns {Track} - */ - nowPlaying() { - if (this.#watchDestroyed()) return; - return this.current; - } - - /** - * Connects to a voice channel - * @param {GuildChannelResolvable} channel The voice/stage channel - * @returns {Promise} - */ - async connect(channel: GuildChannelResolvable) { - if (this.#watchDestroyed()) return; - const _channel = this.guild.channels.resolve(channel) as StageChannel | VoiceChannel; - if (![ChannelType.GuildStageVoice, ChannelType.GuildVoice].includes(_channel?.type)) - throw new PlayerError(`Channel type must be GuildVoice or GuildStageVoice, got ${_channel?.type}!`, ErrorStatusCode.INVALID_ARG_TYPE); - const connection = await this.player.voiceUtils.connect(_channel, { - deaf: this.options.autoSelfDeaf - }); - this.connection = connection; - - if (_channel.type === ChannelType.GuildStageVoice) { - await _channel.guild.members.me.voice.setSuppressed(false).catch(async () => { - return await _channel.guild.members.me.voice.setRequestToSpeak(true).catch(Util.noop); - }); - } - - this.connection.on("error", (err) => { - if (this.#watchDestroyed(false)) return; - this.player.emit("connectionError", this, err); - }); - this.connection.on("debug", (msg) => { - if (this.#watchDestroyed(false)) return; - this.player.emit("debug", this, msg); - }); - - this.player.emit("connectionCreate", this, this.connection); - - this.connection.on("start", (resource) => { - if (this.#watchDestroyed(false)) return; - this.playing = true; - if (!this._filtersUpdate) this.player.emit("trackStart", this, resource?.metadata ?? this.current); - this._filtersUpdate = false; - }); - - this.connection.on("finish", async (resource) => { - if (this.#watchDestroyed(false)) return; - this.playing = false; - if (this._filtersUpdate) return; - this._streamTime = 0; - if (resource?.metadata) this.previousTracks.push(resource.metadata); - - this.player.emit("trackEnd", this, resource.metadata); - - if (!this.tracks.length && this.repeatMode === QueueRepeatMode.OFF) { - if (this.options.leaveOnEnd) this.destroy(); - this.player.emit("queueEnd", this); - } else if (!this.tracks.length && this.repeatMode === QueueRepeatMode.AUTOPLAY) { - this._handleAutoplay(Util.last(this.previousTracks)); - } else { - if (this.repeatMode === QueueRepeatMode.TRACK) return void this.play(Util.last(this.previousTracks), { immediate: true }); - if (this.repeatMode === QueueRepeatMode.QUEUE) this.tracks.push(Util.last(this.previousTracks)); - const nextTrack = this.tracks.shift(); - this.play(nextTrack, { immediate: true }); - return; - } - }); - - return this; - } - - /** - * Destroys this queue - * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy - * @returns {void} - */ - destroy(disconnect = this.options.leaveOnStop) { - if (this.#watchDestroyed()) return; - if (this.connection) this.connection.end(); - if (disconnect) this.connection?.disconnect(); - this.player.queues.delete(this.guild.id); - this.player.voiceUtils.cache.delete(this.guild.id); - this.#destroyed = true; - } - - /** - * Skips current track - * @returns {boolean} - */ - skip() { - if (this.#watchDestroyed()) return; - if (!this.connection) return false; - this._filtersUpdate = false; - this.connection.end(); - return true; - } - - /** - * Adds single track to the queue - * @param {Track} track The track to add - * @returns {void} - */ - addTrack(track: Track) { - if (this.#watchDestroyed()) return; - if (!(track instanceof Track)) throw new PlayerError("invalid track", ErrorStatusCode.INVALID_TRACK); - this.tracks.push(track); - this.player.emit("trackAdd", this, track); - } - - /** - * Adds multiple tracks to the queue - * @param {Track[]} tracks Array of tracks to add - */ - addTracks(tracks: Track[]) { - if (this.#watchDestroyed()) return; - if (!tracks.every((y) => y instanceof Track)) throw new PlayerError("invalid track", ErrorStatusCode.INVALID_TRACK); - this.tracks.push(...tracks); - this.player.emit("tracksAdd", this, tracks); - } - - /** - * Sets paused state - * @param {boolean} paused The paused state - * @returns {boolean} - */ - setPaused(paused?: boolean) { - if (this.#watchDestroyed()) return; - if (!this.connection) return false; - return paused ? this.connection.pause(true) : this.connection.resume(); - } - - /** - * Sets bitrate - * @param {number|auto} bitrate bitrate to set - * @returns {void} - */ - setBitrate(bitrate: number | "auto") { - if (this.#watchDestroyed()) return; - if (!this.connection?.audioResource?.encoder) return; - if (bitrate === "auto") bitrate = this.connection.channel?.bitrate ?? 64000; - this.connection.audioResource.encoder.setBitrate(bitrate); - } - - /** - * Sets volume - * @param {number} amount The volume amount - * @returns {boolean} - */ - setVolume(amount: number) { - if (this.#watchDestroyed()) return; - if (!this.connection) return false; - this.#lastVolume = amount; - this.options.initialVolume = amount; - return this.connection.setVolume(amount); - } - /** - * Sets repeat mode - * @param {QueueRepeatMode} mode The repeat mode - * @returns {boolean} - */ - setRepeatMode(mode: QueueRepeatMode) { - if (this.#watchDestroyed()) return; - if (![QueueRepeatMode.OFF, QueueRepeatMode.QUEUE, QueueRepeatMode.TRACK, QueueRepeatMode.AUTOPLAY].includes(mode)) - throw new PlayerError(`Unknown repeat mode "${mode}"!`, ErrorStatusCode.UNKNOWN_REPEAT_MODE); - if (mode === this.repeatMode) return false; - this.repeatMode = mode; - return true; - } - - /** - * The current volume amount - * @type {number} - */ - get volume() { - if (this.#watchDestroyed()) return; - if (!this.connection) return 100; - return this.connection.volume; - } - - set volume(amount: number) { - this.setVolume(amount); - } - - /** - * The stream time of this queue - * @type {number} - */ - get streamTime() { - if (this.#watchDestroyed()) return; - if (!this.connection) return 0; - const playbackTime = this._streamTime + this.connection.streamTime; - const NC = this._activeFilters.includes("nightcore") ? 1.25 : null; - const VW = this._activeFilters.includes("vaporwave") ? 0.8 : null; - - if (NC && VW) return playbackTime * (NC + VW); - return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime; - } - - set streamTime(time: number) { - if (this.#watchDestroyed()) return; - this.seek(time); - } - - /** - * Returns enabled filters - * @returns {AudioFilters} - */ - getFiltersEnabled() { - if (this.#watchDestroyed()) return; - return AudioFilters.names.filter((x) => this._activeFilters.includes(x)); - } - - /** - * Returns disabled filters - * @returns {AudioFilters} - */ - getFiltersDisabled() { - if (this.#watchDestroyed()) return; - return AudioFilters.names.filter((x) => !this._activeFilters.includes(x)); - } - - /** - * Sets filters - * @param {QueueFilters} filters Queue filters - * @returns {Promise} - */ - async setFilters(filters?: QueueFilters) { - if (this.#watchDestroyed()) return; - if (!filters || !Object.keys(filters).length) { - // reset filters - const streamTime = this.streamTime; - this._activeFilters = []; - return await this.play(this.current, { - immediate: true, - filtersUpdate: true, - seek: streamTime, - encoderArgs: [] - }); - } - - const _filters: any[] = []; // eslint-disable-line @typescript-eslint/no-explicit-any - - for (const filter in filters) { - if (filters[filter as keyof QueueFilters] === true) _filters.push(filter); - } - - if (this._activeFilters.join("") === _filters.join("")) return; - - const newFilters = AudioFilters.create(_filters).trim(); - const streamTime = this.streamTime; - this._activeFilters = _filters; - - return await this.play(this.current, { - immediate: true, - filtersUpdate: true, - seek: streamTime, - encoderArgs: !_filters.length ? undefined : ["-af", newFilters] - }); - } - - /** - * Seeks to the given time - * @param {number} position The position - * @returns {boolean} - */ - async seek(position: number) { - if (this.#watchDestroyed()) return; - if (!this.playing || !this.current) return false; - if (position < 1) position = 0; - if (position >= this.current.durationMS) return this.skip(); - - await this.play(this.current, { - immediate: true, - filtersUpdate: true, // to stop events - seek: position - }); - - return true; - } - - /** - * Plays previous track - * @returns {Promise} - */ - async back() { - if (this.#watchDestroyed()) return; - const prev = this.previousTracks[this.previousTracks.length - 2]; // because last item is the current track - if (!prev) throw new PlayerError("Could not find previous track", ErrorStatusCode.TRACK_NOT_FOUND); - - return await this.play(prev, { immediate: true }); - } - - /** - * Clear this queue - */ - clear() { - if (this.#watchDestroyed()) return; - this.tracks = []; - this.previousTracks = []; - } - - /** - * Stops the player - * @returns {void} - */ - stop() { - if (this.#watchDestroyed()) return; - return this.destroy(); - } - - /** - * Shuffles this queue - * @returns {boolean} - */ - shuffle() { - if (this.#watchDestroyed()) return; - if (!this.tracks.length || this.tracks.length < 2) return false; - - for (let i = this.tracks.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]]; - } - - return true; - } - - /** - * Removes a track from the queue - * @param {Track|string|number} track The track to remove - * @returns {Track} - */ - remove(track: Track | string | number) { - if (this.#watchDestroyed()) return; - let trackFound: Track = null; - if (typeof track === "number") { - trackFound = this.tracks[track]; - if (trackFound) { - this.tracks = this.tracks.filter((t) => t.id !== trackFound.id); - } - } else { - trackFound = this.tracks.find((s) => s.id === (track instanceof Track ? track.id : track)); - if (trackFound) { - this.tracks = this.tracks.filter((s) => s.id !== trackFound.id); - } - } - - return trackFound; - } - - /** - * Returns the index of the specified track. If found, returns the track index else returns -1. - * @param {number|Track|string} track The track - * @returns {number} - */ - getTrackPosition(track: number | Track | string) { - if (this.#watchDestroyed()) return; - if (typeof track === "number") return this.tracks[track] != null ? track : -1; - return this.tracks.findIndex((pred) => pred.id === (track instanceof Track ? track.id : track)); - } - - /** - * Jumps to particular track - * @param {Track|number} track The track - * @returns {void} - */ - jump(track: Track | number): void { - if (this.#watchDestroyed()) return; - const foundTrack = this.remove(track); - if (!foundTrack) throw new PlayerError("Track not found", ErrorStatusCode.TRACK_NOT_FOUND); - - this.tracks.splice(0, 0, foundTrack); - - return void this.skip(); - } - - /** - * Jumps to particular track, removing other tracks on the way - * @param {Track|number} track The track - * @returns {void} - */ - skipTo(track: Track | number): void { - if (this.#watchDestroyed()) return; - const trackIndex = this.getTrackPosition(track); - const removedTrack = this.remove(track); - if (!removedTrack) throw new PlayerError("Track not found", ErrorStatusCode.TRACK_NOT_FOUND); - - this.tracks.splice(0, trackIndex, removedTrack); - - return void this.skip(); - } - - /** - * Inserts the given track to specified index - * @param {Track} track The track to insert - * @param {number} [index=0] The index where this track should be - */ - insert(track: Track, index = 0) { - if (this.#watchDestroyed()) return; - if (!track || !(track instanceof Track)) throw new PlayerError("track must be the instance of Track", ErrorStatusCode.INVALID_TRACK); - if (typeof index !== "number" || index < 0 || !Number.isFinite(index)) throw new PlayerError(`Invalid index "${index}"`, ErrorStatusCode.INVALID_ARG_TYPE); - - this.tracks.splice(index, 0, track); - - this.player.emit("trackAdd", this, track); - } - - /** - * @typedef {object} PlayerTimestamp - * @property {string} current The current progress - * @property {string} end The total time - * @property {number} progress Progress in % - */ - - /** - * Returns player stream timestamp - * @returns {PlayerTimestamp} - */ - getPlayerTimestamp() { - if (this.#watchDestroyed()) return; - const currentStreamTime = this.streamTime; - const totalTime = this.current.durationMS; - - const currentTimecode = Util.buildTimeCode(Util.parseMS(currentStreamTime)); - const endTimecode = Util.buildTimeCode(Util.parseMS(totalTime)); - - return { - current: currentTimecode, - end: endTimecode, - progress: Math.round((currentStreamTime / totalTime) * 100) - }; - } - - /** - * Creates progress bar string - * @param {PlayerProgressbarOptions} options The progress bar options - * @returns {string} - */ - createProgressBar(options: PlayerProgressbarOptions = { timecodes: true }) { - if (this.#watchDestroyed()) return; - const length = typeof options.length === "number" ? (options.length <= 0 || options.length === Infinity ? 15 : options.length) : 15; - - const index = Math.round((this.streamTime / this.current.durationMS) * length); - const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "🔘"; - const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "▬"; - - if (index >= 1 && index <= length) { - const bar = line.repeat(length - 1).split(""); - bar.splice(index, 0, indicator); - if (options.timecodes) { - const timestamp = this.getPlayerTimestamp(); - return `${timestamp.current} ┃ ${bar.join("")} ┃ ${timestamp.end}`; - } else { - return `${bar.join("")}`; - } - } else { - if (options.timecodes) { - const timestamp = this.getPlayerTimestamp(); - return `${timestamp.current} ┃ ${indicator}${line.repeat(length - 1)} ┃ ${timestamp.end}`; - } else { - return `${indicator}${line.repeat(length - 1)}`; - } - } - } - - /** - * Total duration - * @type {Number} - */ - get totalTime(): number { - if (this.#watchDestroyed()) return; - return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0; - } - - /** - * Play stream in a voice/stage channel - * @param {Track} [src] The track to play (if empty, uses first track from the queue) - * @param {PlayOptions} [options] The options - * @returns {Promise} - */ - async play(src?: Track, options: PlayOptions = {}): Promise { - if (this.#watchDestroyed(false)) return; - if (!this.connection || !this.connection.voiceConnection) throw new PlayerError("Voice connection is not available, use .connect()!", ErrorStatusCode.NO_CONNECTION); - if (src && (this.playing || this.tracks.length) && !options.immediate) return this.addTrack(src); - const track = options.filtersUpdate && !options.immediate ? src || this.current : src ?? this.tracks.shift(); - if (!track) return; - - this.player.emit("debug", this, "Received play request"); - - if (!options.filtersUpdate) { - this.previousTracks = this.previousTracks.filter((x) => x.id !== track.id); - this.previousTracks.push(track); - } - - let stream = null; - const hasCustomDownloader = typeof this.onBeforeCreateStream === "function"; - - if (["youtube", "spotify"].includes(track.raw.source)) { - let spotifyResolved = false; - if (this.options.spotifyBridge && track.raw.source === "spotify" && !track.raw.engine) { - track.raw.engine = await play.search(`${track.author} ${track.title}`, { source: { youtube: "video" } }) - .then(res => res[0].url) - .catch(() => null); - spotifyResolved = true; - } - - const url = track.raw.source === "spotify" ? track.raw.engine : track.url; - if (!url) return void this.play(this.tracks.shift(), { immediate: true }); - - if (hasCustomDownloader) { - stream = (await this.onBeforeCreateStream(track, spotifyResolved ? "youtube" : track.raw.source, this)) || null; - } - - if (!stream) { - stream = (await play.stream(url, { discordPlayerCompatibility: true })).stream; - } - } else { - const arbitraryStream = (hasCustomDownloader && (await this.onBeforeCreateStream(track, track.raw.source || track.raw.engine, this))) || null; - stream = - arbitraryStream || (track.raw.source === "soundcloud" && typeof track.raw.engine?.downloadProgressive === "function") - ? await track.raw.engine.downloadProgressive() - : typeof track.raw.engine === "function" - ? await track.raw.engine() - : track.raw.engine; - } - - const ffmpegStream = createFFmpegStream(stream, { - encoderArgs: options.encoderArgs || [], - seek: options.seek ? options.seek / 1000 : 0, - fmt: "s16le" - }).on("error", (err) => { - if (!`${err}`.toLowerCase().includes("premature close")) this.player.emit("error", this, err); - }); - - const resource: AudioResource = this.connection.createStream(ffmpegStream, { - type: StreamType.Raw, - data: track, - disableVolume: Boolean(this.options.disableVolume) - }); - - if (options.seek) this._streamTime = options.seek; - this._filtersUpdate = options.filtersUpdate; - - const volumeTransformer = resource.volume as VolumeTransformer; - if (volumeTransformer && typeof this.options.initialVolume === "number") Reflect.set(volumeTransformer, "volume", Math.pow(this.options.initialVolume / 100, 1.660964)); - if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") { - if (typeof volumeTransformer.setSmoothness === "function") volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0); - } - - setTimeout(() => { - this.connection.playStream(resource); - }, this.#getBufferingTimeout()).unref(); - } - - /** - * Private method to handle autoplay - * @param {Track} track The source track to find its similar track for autoplay - * @returns {Promise} - * @private - */ - private async _handleAutoplay(track: Track): Promise { - if (this.#watchDestroyed()) return; - if (!track || ![track.source, track.raw?.source].includes("youtube")) { - if (this.options.leaveOnEnd) this.destroy(); - return void this.player.emit("queueEnd", this); - } - const info = await play.video_info(track.url) - .catch(Util.noop); - if (!info) { - if (this.options.leaveOnEnd) this.destroy(); - return void this.player.emit("queueEnd", this); - } - - const randomRelated = await play.video_info(info.related_videos[0]); - const nextTrack = new Track(this.player, { - title: randomRelated.video_details.title, - url: randomRelated.video_details.url, - duration: randomRelated.video_details.durationRaw ? Util.buildTimeCode(Util.parseMS(randomRelated.video_details.durationInSec * 1000)) : "0:00", - description: "", - thumbnail: Util.last(randomRelated.video_details.thumbnails).url, - views: randomRelated.video_details.views, - author: randomRelated.video_details.channel.name, - requestedBy: track.requestedBy, - source: "youtube" - }); - - this.play(nextTrack, { immediate: true }); - } - - *[Symbol.iterator]() { - if (this.#watchDestroyed()) return; - yield* this.tracks; - } - - /** - * JSON representation of this queue - * @returns {object} - */ - toJSON() { - if (this.#watchDestroyed()) return; - return { - id: this.id, - guild: this.guild.id, - voiceChannel: this.connection?.channel?.id, - options: this.options, - tracks: this.tracks.map((m) => m.toJSON()) - }; - } - - /** - * String representation of this queue - * @returns {string} - */ - toString() { - if (this.#watchDestroyed()) return; - if (!this.tracks.length) return "No songs available to display!"; - return `**Upcoming Songs:**\n${this.tracks.map((m, i) => `${i + 1}. **${m.title}**`).join("\n")}`; - } - - #watchDestroyed(emit = true) { - if (this.#destroyed) { - if (emit) this.player.emit("error", this, new PlayerError("Cannot use destroyed queue", ErrorStatusCode.DESTROYED_QUEUE)); - return true; - } - - return false; - } - - #getBufferingTimeout() { - const timeout = this.options.bufferingTimeout; - - if (isNaN(timeout) || timeout < 0 || !Number.isFinite(timeout)) return 1000; - return timeout; - } -} - -export { Queue }; diff --git a/helpers/Music/src/Structures/Track.ts b/helpers/Music/src/Structures/Track.ts deleted file mode 100644 index fd14275b..00000000 --- a/helpers/Music/src/Structures/Track.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { User, escapeMarkdown, SnowflakeUtil } from "discord.js"; -import { Player } from "../Player"; -import { RawTrackData, TrackJSON } from "../types/types"; -import { Playlist } from "./Playlist"; -import { Queue } from "./Queue"; - -class Track { - public player!: Player; - public title!: string; - public description!: string; - public author!: string; - public url!: string; - public thumbnail!: string; - public duration!: string; - public views!: number; - public requestedBy!: User; - public playlist?: Playlist; - public readonly raw: RawTrackData = {} as RawTrackData; - public readonly id = SnowflakeUtil.generate().toString(); - - /** - * Track constructor - * @param {Player} player The player that instantiated this Track - * @param {RawTrackData} data Track data - */ - constructor(player: Player, data: RawTrackData) { - /** - * The player that instantiated this Track - * @name Track#player - * @type {Player} - * @readonly - */ - Object.defineProperty(this, "player", { value: player, enumerable: false }); - - /** - * Title of this track - * @name Track#title - * @type {string} - */ - - /** - * Description of this track - * @name Track#description - * @type {string} - */ - - /** - * Author of this track - * @name Track#author - * @type {string} - */ - - /** - * URL of this track - * @name Track#url - * @type {string} - */ - - /** - * Thumbnail of this track - * @name Track#thumbnail - * @type {string} - */ - - /** - * Duration of this track - * @name Track#duration - * @type {string} - */ - - /** - * Views count of this track - * @name Track#views - * @type {number} - */ - - /** - * Person who requested this track - * @name Track#requestedBy - * @type {User} - */ - - /** - * If this track belongs to playlist - * @name Track#fromPlaylist - * @type {boolean} - */ - - /** - * Raw track data - * @name Track#raw - * @type {RawTrackData} - */ - - /** - * The track id - * @name Track#id - * @type {Snowflake} - * @readonly - */ - - /** - * The playlist which track belongs - * @name Track#playlist - * @type {Playlist} - */ - - void this._patch(data); - } - - private _patch(data: RawTrackData) { - this.title = escapeMarkdown(data.title ?? ""); - this.description = data.description ?? ""; - this.author = data.author ?? ""; - this.url = data.url ?? ""; - this.thumbnail = data.thumbnail ?? ""; - this.duration = data.duration ?? ""; - this.views = data.views ?? 0; - this.requestedBy = data.requestedBy; - this.playlist = data.playlist; - - // raw - Object.defineProperty(this, "raw", { value: Object.assign({}, { source: data.raw?.source ?? data.source }, data.raw ?? data), enumerable: false }); - } - - /** - * The queue in which this track is located - * @type {Queue} - */ - get queue(): Queue { - return this.player.queues.find((q) => q.tracks.some((ab) => ab.id === this.id)); - } - - /** - * The track duration in millisecond - * @type {number} - */ - get durationMS(): number { - const times = (n: number, t: number) => { - let tn = 1; - for (let i = 0; i < t; i++) tn *= n; - return t <= 0 ? 1000 : tn * 1000; - }; - - return this.duration - .split(":") - .reverse() - .map((m, i) => parseInt(m) * times(60, i)) - .reduce((a, c) => a + c, 0); - } - - /** - * Returns source of this track - * @type {TrackSource} - */ - get source() { - return this.raw.source ?? "arbitrary"; - } - - /** - * String representation of this track - * @returns {string} - */ - toString(): string { - return `${this.title} by ${this.author}`; - } - - /** - * Raw JSON representation of this track - * @returns {TrackJSON} - */ - toJSON(hidePlaylist?: boolean) { - return { - id: this.id, - title: this.title, - description: this.description, - author: this.author, - url: this.url, - thumbnail: this.thumbnail, - duration: this.duration, - durationMS: this.durationMS, - views: this.views, - requestedBy: this.requestedBy?.id, - playlist: hidePlaylist ? null : this.playlist?.toJSON() ?? null - } as TrackJSON; - } -} - -export default Track; - -export { Track }; diff --git a/helpers/Music/src/VoiceInterface/StreamDispatcher.ts b/helpers/Music/src/VoiceInterface/StreamDispatcher.ts deleted file mode 100644 index e8566fc2..00000000 --- a/helpers/Music/src/VoiceInterface/StreamDispatcher.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { - AudioPlayer, - AudioPlayerError, - AudioPlayerStatus, - AudioResource, - createAudioPlayer, - createAudioResource, - entersState, - StreamType, - VoiceConnection, - VoiceConnectionStatus, - VoiceConnectionDisconnectReason -} from "@discordjs/voice"; -import { StageChannel, VoiceChannel } from "discord.js"; -import { Duplex, Readable } from "stream"; -import { TypedEmitter as EventEmitter } from "tiny-typed-emitter"; -import Track from "../Structures/Track"; -import { Util } from "../utils/Util"; -import { PlayerError, ErrorStatusCode } from "../Structures/PlayerError"; - -export interface VoiceEvents { - /* eslint-disable @typescript-eslint/no-explicit-any */ - error: (error: AudioPlayerError) => any; - debug: (message: string) => any; - start: (resource: AudioResource) => any; - finish: (resource: AudioResource) => any; - /* eslint-enable @typescript-eslint/no-explicit-any */ -} - -class StreamDispatcher extends EventEmitter { - public readonly voiceConnection: VoiceConnection; - public readonly audioPlayer: AudioPlayer; - public channel: VoiceChannel | StageChannel; - public audioResource?: AudioResource; - private readyLock = false; - public paused: boolean; - - /** - * Creates new connection object - * @param {VoiceConnection} connection The connection - * @param {VoiceChannel|StageChannel} channel The connected channel - * @private - */ - constructor(connection: VoiceConnection, channel: VoiceChannel | StageChannel, public readonly connectionTimeout: number = 20000) { - super(); - - /** - * The voice connection - * @type {VoiceConnection} - */ - this.voiceConnection = connection; - - /** - * The audio player - * @type {AudioPlayer} - */ - this.audioPlayer = createAudioPlayer(); - - /** - * The voice channel - * @type {VoiceChannel|StageChannel} - */ - this.channel = channel; - - /** - * The paused state - * @type {boolean} - */ - this.paused = false; - - this.voiceConnection.on("stateChange", async (_, newState) => { - if (newState.status === VoiceConnectionStatus.Disconnected) { - if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) { - try { - await entersState(this.voiceConnection, VoiceConnectionStatus.Connecting, this.connectionTimeout); - } catch { - try { - this.voiceConnection.destroy(); - } catch (err) { - this.emit("error", err as AudioPlayerError); - } - } - } else if (this.voiceConnection.rejoinAttempts < 5) { - await Util.wait((this.voiceConnection.rejoinAttempts + 1) * 5000); - this.voiceConnection.rejoin(); - } else { - try { - this.voiceConnection.destroy(); - } catch (err) { - this.emit("error", err as AudioPlayerError); - } - } - } else if (newState.status === VoiceConnectionStatus.Destroyed) { - this.end(); - } else if (!this.readyLock && (newState.status === VoiceConnectionStatus.Connecting || newState.status === VoiceConnectionStatus.Signalling)) { - this.readyLock = true; - try { - await entersState(this.voiceConnection, VoiceConnectionStatus.Ready, this.connectionTimeout); - } catch { - if (this.voiceConnection.state.status !== VoiceConnectionStatus.Destroyed) { - try { - this.voiceConnection.destroy(); - } catch (err) { - this.emit("error", err as AudioPlayerError); - } - } - } finally { - this.readyLock = false; - } - } - }); - - this.audioPlayer.on("stateChange", (oldState, newState) => { - if (newState.status === AudioPlayerStatus.Playing) { - if (!this.paused) return void this.emit("start", this.audioResource); - } else if (newState.status === AudioPlayerStatus.Idle && oldState.status !== AudioPlayerStatus.Idle) { - if (!this.paused) { - void this.emit("finish", this.audioResource); - this.audioResource = null; - } - } - }); - - this.audioPlayer.on("debug", (m) => void this.emit("debug", m)); - this.audioPlayer.on("error", (error) => void this.emit("error", error)); - this.voiceConnection.subscribe(this.audioPlayer); - } - - /** - * Creates stream - * @param {Readable|Duplex|string} src The stream source - * @param {object} [ops] Options - * @returns {AudioResource} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - createStream(src: Readable | Duplex | string, ops?: { type?: StreamType; data?: any; disableVolume?: boolean }) { - this.audioResource = createAudioResource(src, { - inputType: ops?.type ?? StreamType.Arbitrary, - metadata: ops?.data, - // eslint-disable-next-line no-extra-boolean-cast - inlineVolume: !Boolean(ops?.disableVolume) - }); - - return this.audioResource; - } - - /** - * The player status - * @type {AudioPlayerStatus} - */ - get status() { - return this.audioPlayer.state.status; - } - - /** - * Disconnects from voice - * @returns {void} - */ - disconnect() { - try { - this.audioPlayer.stop(true); - this.voiceConnection.destroy(); - } catch {} // eslint-disable-line no-empty - } - - /** - * Stops the player - * @returns {void} - */ - end() { - this.audioPlayer.stop(); - } - - /** - * Pauses the stream playback - * @param {boolean} [interpolateSilence=false] If true, the player will play 5 packets of silence after pausing to prevent audio glitches. - * @returns {boolean} - */ - pause(interpolateSilence?: boolean) { - const success = this.audioPlayer.pause(interpolateSilence); - this.paused = success; - return success; - } - - /** - * Resumes the stream playback - * @returns {boolean} - */ - resume() { - const success = this.audioPlayer.unpause(); - this.paused = !success; - return success; - } - - /** - * Play stream - * @param {AudioResource} [resource=this.audioResource] The audio resource to play - * @returns {Promise} - */ - async playStream(resource: AudioResource = this.audioResource) { - if (!resource) throw new PlayerError("Audio resource is not available!", ErrorStatusCode.NO_AUDIO_RESOURCE); - if (resource.ended) return void this.emit("error", new PlayerError("Cannot play a resource that has already ended.") as unknown as AudioPlayerError); - if (!this.audioResource) this.audioResource = resource; - if (this.voiceConnection.state.status !== VoiceConnectionStatus.Ready) { - try { - await entersState(this.voiceConnection, VoiceConnectionStatus.Ready, this.connectionTimeout); - } catch (err) { - return void this.emit("error", err as AudioPlayerError); - } - } - - try { - this.audioPlayer.play(resource); - } catch (e) { - this.emit("error", e as AudioPlayerError); - } - - return this; - } - - /** - * Sets playback volume - * @param {number} value The volume amount - * @returns {boolean} - */ - setVolume(value: number) { - if (!this.audioResource?.volume || isNaN(value) || value < 0 || value > Infinity) return false; - - this.audioResource.volume.setVolumeLogarithmic(value / 100); - return true; - } - - /** - * The current volume - * @type {number} - */ - get volume() { - if (!this.audioResource?.volume) return 100; - const currentVol = this.audioResource.volume.volume; - return Math.round(Math.pow(currentVol, 1 / 1.660964) * 100); - } - - /** - * The playback time - * @type {number} - */ - get streamTime() { - if (!this.audioResource) return 0; - return this.audioResource.playbackDuration; - } -} - -export { StreamDispatcher as StreamDispatcher }; diff --git a/helpers/Music/src/VoiceInterface/VoiceUtils.ts b/helpers/Music/src/VoiceInterface/VoiceUtils.ts deleted file mode 100644 index ec7a99d0..00000000 --- a/helpers/Music/src/VoiceInterface/VoiceUtils.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { VoiceChannel, StageChannel, Collection, Snowflake } from "discord.js"; -import { DiscordGatewayAdapterCreator, joinVoiceChannel, VoiceConnection } from "@discordjs/voice"; -import { StreamDispatcher } from "./StreamDispatcher"; - -class VoiceUtils { - public cache: Collection; - - /** - * The voice utils - * @private - */ - constructor() { - /** - * The cache where voice utils stores stream managers - * @type {Collection} - */ - this.cache = new Collection(); - } - - /** - * Joins a voice channel, creating basic stream dispatch manager - * @param {StageChannel|VoiceChannel} channel The voice channel - * @param {object} [options] Join options - * @returns {Promise} - */ - public async connect( - channel: VoiceChannel | StageChannel, - options?: { - deaf?: boolean; - maxTime?: number; - } - ): Promise { - const conn = await this.join(channel, options); - const sub = new StreamDispatcher(conn, channel, options.maxTime); - this.cache.set(channel.guild.id, sub); - return sub; - } - - /** - * Joins a voice channel - * @param {StageChannel|VoiceChannel} [channel] The voice/stage channel to join - * @param {object} [options] Join options - * @returns {VoiceConnection} - */ - public async join( - channel: VoiceChannel | StageChannel, - options?: { - deaf?: boolean; - maxTime?: number; - } - ) { - const conn = joinVoiceChannel({ - guildId: channel.guild.id, - channelId: channel.id, - adapterCreator: channel.guild.voiceAdapterCreator as unknown as DiscordGatewayAdapterCreator, - selfDeaf: Boolean(options.deaf) - }); - - return conn; - } - - /** - * Disconnects voice connection - * @param {VoiceConnection} connection The voice connection - * @returns {void} - */ - public disconnect(connection: VoiceConnection | StreamDispatcher) { - if (connection instanceof StreamDispatcher) return connection.voiceConnection.destroy(); - return connection.destroy(); - } - - /** - * Returns Discord Player voice connection - * @param {Snowflake} guild The guild id - * @returns {StreamDispatcher} - */ - public getConnection(guild: Snowflake) { - return this.cache.get(guild); - } -} - -export { VoiceUtils }; diff --git a/helpers/Music/src/VoiceInterface/VolumeTransformer.ts b/helpers/Music/src/VoiceInterface/VolumeTransformer.ts deleted file mode 100644 index b493dd1e..00000000 --- a/helpers/Music/src/VoiceInterface/VolumeTransformer.ts +++ /dev/null @@ -1,144 +0,0 @@ -// prism's volume transformer with smooth volume support - -import { Transform, TransformOptions } from "stream"; - -export interface VolumeTransformerOptions extends TransformOptions { - type?: "s16le" | "s16be" | "s32le" | "s32be"; - smoothness?: number; - volume?: number; -} - -export class VolumeTransformer extends Transform { - private _bits: number; - private _smoothing: number; - private _bytes: number; - private _extremum: number; - private _chunk: Buffer; - public volume: number; - private _targetVolume: number; - public type: "s16le" | "s32le" | "s16be" | "s32be"; - constructor(options: VolumeTransformerOptions = {}) { - super(options); - switch (options.type) { - case "s16le": - this._readInt = (buffer, index) => buffer.readInt16LE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt16LE(int, index); - this._bits = 16; - break; - case "s16be": - this._readInt = (buffer, index) => buffer.readInt16BE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt16BE(int, index); - this._bits = 16; - break; - case "s32le": - this._readInt = (buffer, index) => buffer.readInt32LE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt32LE(int, index); - this._bits = 32; - break; - case "s32be": - this._readInt = (buffer, index) => buffer.readInt32BE(index); - this._writeInt = (buffer, int, index) => buffer.writeInt32BE(int, index); - this._bits = 32; - break; - default: - throw new Error("VolumeTransformer type should be one of s16le, s16be, s32le, s32be"); - } - this.type = options.type; - this._bytes = this._bits / 8; - this._extremum = Math.pow(2, this._bits - 1); - this.volume = Number.isNaN(options.volume) ? 1 : Number(options.volume); - if (!Number.isFinite(this.volume)) this.volume = 1; - this._targetVolume = this.volume; - this._chunk = Buffer.alloc(0); - this._smoothing = options.smoothness || 0; - } - - _readInt(buffer: Buffer, index: number) { - return index; - } - _writeInt(buffer: Buffer, int: number, index: number) { - return index; - } - - _applySmoothness() { - if (this.volume < this._targetVolume) { - this.volume = this.volume + this._smoothing >= this._targetVolume ? this._targetVolume : this.volume + this._smoothing; - } else if (this.volume > this._targetVolume) { - this.volume = this.volume - this._smoothing <= this._targetVolume ? this._targetVolume : this.volume - this._smoothing; - } - } - - _transform(chunk: Buffer, encoding: BufferEncoding, done: () => unknown) { - if (this.smoothingEnabled() && this.volume !== this._targetVolume) this._applySmoothness(); - - if (this.volume === 1) { - this.push(chunk); - return done(); - } - - const { _bytes, _extremum } = this; - - chunk = this._chunk = Buffer.concat([this._chunk, chunk]); - if (chunk.length < _bytes) return done(); - - const complete = Math.floor(chunk.length / _bytes) * _bytes; - - for (let i = 0; i < complete; i += _bytes) { - const int = Math.min(_extremum - 1, Math.max(-_extremum, Math.floor(this.volume * this._readInt(chunk, i)))); - this._writeInt(chunk, int, i); - } - - this._chunk = chunk.slice(complete); - this.push(chunk.slice(0, complete)); - return done(); - } - - _destroy(err: Error, cb: (error: Error) => void) { - super._destroy(err, cb); - this._chunk = null; - } - - setVolume(volume: number) { - if (Number.isNaN(volume)) volume = 1; - if (typeof volume !== "number") volume = Number(volume); - if (!Number.isFinite(volume)) volume = volume < 0 ? 0 : 1; - this._targetVolume = volume; - if (this._smoothing <= 0) this.volume = volume; - } - - setVolumeDecibels(db: number) { - this.setVolume(Math.pow(10, db / 20)); - } - - setVolumeLogarithmic(value: number) { - this.setVolume(Math.pow(value, 1.660964)); - } - - get volumeDecibels() { - return Math.log10(this.volume) * 20; - } - - get volumeLogarithmic() { - return Math.pow(this.volume, 1 / 1.660964); - } - - get smoothness() { - return this._smoothing; - } - - setSmoothness(smoothness: number) { - this._smoothing = smoothness; - } - - smoothingEnabled() { - return Number.isFinite(this._smoothing) && this._smoothing > 0; - } - - get hasSmoothness() { - return true; - } - - static get hasSmoothing() { - return true; - } -} diff --git a/helpers/Music/src/index.ts b/helpers/Music/src/index.ts deleted file mode 100644 index c3c1d1d9..00000000 --- a/helpers/Music/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -// try applying smooth volume patch on load -import "./smoothVolume"; - -export { AudioFilters } from "./utils/AudioFilters"; -export { ExtractorModel } from "./Structures/ExtractorModel"; -export { Playlist } from "./Structures/Playlist"; -export { Player } from "./Player"; -export { PlayerError, ErrorStatusCode } from "./Structures/PlayerError"; -export { QueryResolver } from "./utils/QueryResolver"; -export { Queue } from "./Structures/Queue"; -export { Track } from "./Structures/Track"; -export { VoiceUtils } from "./VoiceInterface/VoiceUtils"; -export { VoiceEvents, StreamDispatcher } from "./VoiceInterface/StreamDispatcher"; -export { Util } from "./utils/Util"; -export * from "./types/types"; -export * from "./utils/FFmpegStream"; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -export const version: string = require(`${__dirname}/../package.json`).version; diff --git a/helpers/Music/src/smoothVolume.ts b/helpers/Music/src/smoothVolume.ts deleted file mode 100644 index d7c6af78..00000000 --- a/helpers/Music/src/smoothVolume.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { VolumeTransformer as VolumeTransformerMock } from "./VoiceInterface/VolumeTransformer"; - -try { - // eslint-disable-next-line - const mod = require("prism-media") as typeof import("prism-media") & { VolumeTransformer: typeof VolumeTransformerMock }; - - if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") { - Reflect.set(mod, "VolumeTransformer", VolumeTransformerMock); - } -} catch { - /* do nothing */ -} diff --git a/helpers/Music/src/types/types.ts b/helpers/Music/src/types/types.ts deleted file mode 100644 index 2fb72dbf..00000000 --- a/helpers/Music/src/types/types.ts +++ /dev/null @@ -1,485 +0,0 @@ -import { Snowflake, User, UserResolvable } from "discord.js"; -import { Readable, Duplex } from "stream"; -import { Queue } from "../Structures/Queue"; -import Track from "../Structures/Track"; -import { Playlist } from "../Structures/Playlist"; -import { StreamDispatcher } from "../VoiceInterface/StreamDispatcher"; - -export type FiltersName = keyof QueueFilters; - -export interface PlayerSearchResult { - playlist: Playlist | null; - tracks: Track[]; - searched?: boolean; -} - -/** - * @typedef {AudioFilters} QueueFilters - */ -export interface QueueFilters { - bassboost_low?: boolean; - bassboost?: boolean; - bassboost_high?: boolean; - "8D"?: boolean; - vaporwave?: boolean; - nightcore?: boolean; - phaser?: boolean; - tremolo?: boolean; - vibrato?: boolean; - reverse?: boolean; - treble?: boolean; - normalizer?: boolean; - normalizer2?: boolean; - surrounding?: boolean; - pulsator?: boolean; - subboost?: boolean; - karaoke?: boolean; - flanger?: boolean; - gate?: boolean; - haas?: boolean; - mcompand?: boolean; - mono?: boolean; - mstlr?: boolean; - mstrr?: boolean; - compressor?: boolean; - expander?: boolean; - softlimiter?: boolean; - chorus?: boolean; - chorus2d?: boolean; - chorus3d?: boolean; - fadein?: boolean; - dim?: boolean; - earrape?: boolean; -} - -/** - * The track source: - * - soundcloud - * - youtube - * - spotify - * - arbitrary - * @typedef {string} TrackSource - */ -export type TrackSource = "soundcloud" | "youtube" | "spotify" | "arbitrary"; - -/** - * @typedef {object} RawTrackData - * @property {string} title The title - * @property {string} description The description - * @property {string} author The author - * @property {string} url The url - * @property {string} thumbnail The thumbnail - * @property {string} duration The duration - * @property {number | boolean} views The views - * @property {User} requestedBy The user who requested this track - * @property {Playlist} [playlist] The playlist - * @property {TrackSource} [source="arbitrary"] The source - * @property {any} [engine] The engine - * @property {boolean} [live] If this track is live - * @property {any} [raw] The raw data - */ -export interface RawTrackData { - title: string; - description: string; - author: string; - url: string; - thumbnail: string; - duration: string; - views: number; - requestedBy: User; - playlist?: Playlist; - source?: TrackSource; - engine?: any; // eslint-disable-line @typescript-eslint/no-explicit-any - live?: boolean; - raw?: any; // eslint-disable-line @typescript-eslint/no-explicit-any -} - -/** - * @typedef {object} TimeData - * @property {number} days Time in days - * @property {number} hours Time in hours - * @property {number} minutes Time in minutes - * @property {number} seconds Time in seconds - */ -export interface TimeData { - days: number; - hours: number; - minutes: number; - seconds: number; -} - -/** - * @typedef {object} PlayerProgressbarOptions - * @property {boolean} [timecodes] If it should render time codes - * @property {boolean} [queue] If it should create progress bar for the whole queue - * @property {number} [length] The bar length - * @property {string} [line] The bar track - * @property {string} [indicator] The indicator - */ -export interface PlayerProgressbarOptions { - timecodes?: boolean; - length?: number; - line?: string; - indicator?: string; - queue?: boolean; -} - -/** - * @typedef {object} PlayerOptions - * @property {boolean} [leaveOnEnd=true] If it should leave on end - * @property {boolean} [leaveOnStop=true] If it should leave on stop - * @property {boolean} [leaveOnEmpty=true] If it should leave on empty - * @property {number} [leaveOnEmptyCooldown=1000] The cooldown in ms - * @property {boolean} [autoSelfDeaf=true] If it should set the bot in deaf mode - * @property {YTDLDownloadOptions} [ytdlOptions] The youtube download options - * @property {number} [initialVolume=100] The initial player volume - * @property {number} [bufferingTimeout=3000] Buffering timeout for the stream - * @property {boolean} [spotifyBridge=true] If player should bridge spotify source to youtube - * @property {boolean} [disableVolume=false] If player should disable inline volume - * @property {number} [volumeSmoothness=0] The volume transition smoothness between volume changes (lower the value to get better result) - * Setting this or leaving this empty will disable this effect. Example: `volumeSmoothness: 0.1` - * @property {Function} [onBeforeCreateStream] Runs before creating stream - */ -export interface PlayerOptions { - leaveOnEnd?: boolean; - leaveOnStop?: boolean; - leaveOnEmpty?: boolean; - leaveOnEmptyCooldown?: number; - autoSelfDeaf?: boolean; - initialVolume?: number; - bufferingTimeout?: number; - spotifyBridge?: boolean; - disableVolume?: boolean; - volumeSmoothness?: number; - onBeforeCreateStream?: (track: Track, source: TrackSource, queue: Queue) => Promise; -} - -/** - * @typedef {object} ExtractorModelData - * @property {object} [playlist] The playlist info (if any) - * @property {string} [playlist.title] The playlist title - * @property {string} [playlist.description] The playlist description - * @property {string} [playlist.thumbnail] The playlist thumbnail - * @property {album|playlist} [playlist.type] The playlist type: `album` | `playlist` - * @property {TrackSource} [playlist.source] The playlist source - * @property {object} [playlist.author] The playlist author - * @property {string} [playlist.author.name] The author name - * @property {string} [playlist.author.url] The author url - * @property {string} [playlist.id] The playlist id - * @property {string} [playlist.url] The playlist url - * @property {any} [playlist.rawPlaylist] The raw data - * @property {ExtractorData[]} data The data - */ - -/** - * @typedef {object} ExtractorData - * @property {string} title The title - * @property {number} duration The duration - * @property {string} thumbnail The thumbnail - * @property {string|Readable|Duplex} engine The stream engine - * @property {number} views The views count - * @property {string} author The author - * @property {string} description The description - * @property {string} url The url - * @property {string} [version] The extractor version - * @property {TrackSource} [source="arbitrary"] The source - */ -export interface ExtractorModelData { - playlist?: { - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - id: string; - url: string; - rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any - }; - data: { - title: string; - duration: number; - thumbnail: string; - engine: string | Readable | Duplex; - views: number; - author: string; - description: string; - url: string; - version?: string; - source?: TrackSource; - }[]; -} - -/** - * The search query type - * This can be one of: - * - AUTO - * - YOUTUBE - * - YOUTUBE_PLAYLIST - * - SOUNDCLOUD_TRACK - * - SOUNDCLOUD_PLAYLIST - * - SOUNDCLOUD - * - SPOTIFY_SONG - * - SPOTIFY_ALBUM - * - SPOTIFY_PLAYLIST - * - FACEBOOK - * - VIMEO - * - ARBITRARY - * - REVERBNATION - * - YOUTUBE_SEARCH - * - YOUTUBE_VIDEO - * - SOUNDCLOUD_SEARCH - * @typedef {number} QueryType - */ -export enum QueryType { - AUTO, - YOUTUBE, - YOUTUBE_PLAYLIST, - SOUNDCLOUD_TRACK, - SOUNDCLOUD_PLAYLIST, - SOUNDCLOUD, - SPOTIFY_SONG, - SPOTIFY_ALBUM, - SPOTIFY_PLAYLIST, - FACEBOOK, - VIMEO, - ARBITRARY, - REVERBNATION, - YOUTUBE_SEARCH, - YOUTUBE_VIDEO, - SOUNDCLOUD_SEARCH -} - -/** - * Emitted when bot gets disconnected from a voice channel - * @event Player#botDisconnect - * @param {Queue} queue The queue - */ - -/** - * Emitted when the voice channel is empty - * @event Player#channelEmpty - * @param {Queue} queue The queue - */ - -/** - * Emitted when bot connects to a voice channel - * @event Player#connectionCreate - * @param {Queue} queue The queue - * @param {StreamDispatcher} connection The discord player connection object - */ - -/** - * Debug information - * @event Player#debug - * @param {Queue} queue The queue - * @param {string} message The message - */ - -/** - * Emitted on error - * This event should handled properly otherwise it may crash your process! - * @event Player#error - * @param {Queue} queue The queue - * @param {Error} error The error - */ - -/** - * Emitted on connection error. Sometimes stream errors are emitted here as well. - * @event Player#connectionError - * @param {Queue} queue The queue - * @param {Error} error The error - */ - -/** - * Emitted when queue ends - * @event Player#queueEnd - * @param {Queue} queue The queue - */ - -/** - * Emitted when a single track is added - * @event Player#trackAdd - * @param {Queue} queue The queue - * @param {Track} track The track - */ - -/** - * Emitted when multiple tracks are added - * @event Player#tracksAdd - * @param {Queue} queue The queue - * @param {Track[]} tracks The tracks - */ - -/** - * Emitted when a track starts playing - * @event Player#trackStart - * @param {Queue} queue The queue - * @param {Track} track The track - */ - -/** - * Emitted when a track ends - * @event Player#trackEnd - * @param {Queue} queue The queue - * @param {Track} track The track - */ - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export interface PlayerEvents { - botDisconnect: (queue: Queue) => any; - channelEmpty: (queue: Queue) => any; - connectionCreate: (queue: Queue, connection: StreamDispatcher) => any; - debug: (queue: Queue, message: string) => any; - error: (queue: Queue, error: Error) => any; - connectionError: (queue: Queue, error: Error) => any; - queueEnd: (queue: Queue) => any; - trackAdd: (queue: Queue, track: Track) => any; - tracksAdd: (queue: Queue, track: Track[]) => any; - trackStart: (queue: Queue, track: Track) => any; - trackEnd: (queue: Queue, track: Track) => any; -} - -/* eslint-enable @typescript-eslint/no-explicit-any */ - -/** - * @typedef {object} PlayOptions - * @property {boolean} [filtersUpdate=false] If this play was triggered for filters update - * @property {string[]} [encoderArgs=[]] FFmpeg args passed to encoder - * @property {number} [seek] Time to seek to before playing - * @property {boolean} [immediate=false] If it should start playing the provided track immediately - */ -export interface PlayOptions { - filtersUpdate?: boolean; - encoderArgs?: string[]; - seek?: number; - immediate?: boolean; -} - -/** - * @typedef {object} SearchOptions - * @property {UserResolvable} requestedBy The user who requested this search - * @property {QueryType|string} [searchEngine=QueryType.AUTO] The query search engine, can be extractor name to target specific one (custom) - * @property {boolean} [blockExtractor=false] If it should block custom extractors - */ -export interface SearchOptions { - requestedBy: UserResolvable; - searchEngine?: QueryType | string; - blockExtractor?: boolean; -} - -/** - * The queue repeat mode. This can be one of: - * - OFF - * - TRACK - * - QUEUE - * - AUTOPLAY - * @typedef {number} QueueRepeatMode - */ -export enum QueueRepeatMode { - OFF = 0, - TRACK = 1, - QUEUE = 2, - AUTOPLAY = 3 -} - -/** - * @typedef {object} PlaylistInitData - * @property {Track[]} tracks The tracks of this playlist - * @property {string} title The playlist title - * @property {string} description The description - * @property {string} thumbnail The thumbnail - * @property {album|playlist} type The playlist type: `album` | `playlist` - * @property {TrackSource} source The playlist source - * @property {object} author The playlist author - * @property {string} [author.name] The author name - * @property {string} [author.url] The author url - * @property {string} id The playlist id - * @property {string} url The playlist url - * @property {any} [rawPlaylist] The raw playlist data - */ -export interface PlaylistInitData { - tracks: Track[]; - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - id: string; - url: string; - rawPlaylist?: any; // eslint-disable-line @typescript-eslint/no-explicit-any -} - -/** - * @typedef {object} TrackJSON - * @property {string} title The track title - * @property {string} description The track description - * @property {string} author The author - * @property {string} url The url - * @property {string} thumbnail The thumbnail - * @property {string} duration The duration - * @property {number} durationMS The duration in ms - * @property {number} views The views count - * @property {Snowflake} requestedBy The id of the user who requested this track - * @property {PlaylistJSON} [playlist] The playlist info (if any) - */ -export interface TrackJSON { - id: Snowflake; - title: string; - description: string; - author: string; - url: string; - thumbnail: string; - duration: string; - durationMS: number; - views: number; - requestedBy: Snowflake; - playlist?: PlaylistJSON; -} - -/** - * @typedef {object} PlaylistJSON - * @property {string} id The playlist id - * @property {string} url The playlist url - * @property {string} title The playlist title - * @property {string} description The playlist description - * @property {string} thumbnail The thumbnail - * @property {album|playlist} type The playlist type: `album` | `playlist` - * @property {TrackSource} source The track source - * @property {object} author The playlist author - * @property {string} [author.name] The author name - * @property {string} [author.url] The author url - * @property {TrackJSON[]} tracks The tracks data (if any) - */ -export interface PlaylistJSON { - id: string; - url: string; - title: string; - description: string; - thumbnail: string; - type: "album" | "playlist"; - source: TrackSource; - author: { - name: string; - url: string; - }; - tracks: TrackJSON[]; -} - -/** - * @typedef {object} PlayerInitOptions - * @property {boolean} [autoRegisterExtractor=true] If it should automatically register `@discord-player/extractor` - * @property {YTDLDownloadOptions} [ytdlOptions] The options passed to `ytdl-core` - * @property {number} [connectionTimeout=20000] The voice connection timeout - */ -export interface PlayerInitOptions { - autoRegisterExtractor?: boolean; - connectionTimeout?: number; -} \ No newline at end of file diff --git a/helpers/Music/src/utils/AudioFilters.ts b/helpers/Music/src/utils/AudioFilters.ts deleted file mode 100644 index b3770640..00000000 --- a/helpers/Music/src/utils/AudioFilters.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { FiltersName } from "../types/types"; - -const bass = (g: number) => `bass=g=${g}:f=110:w=0.3`; - -class AudioFilters { - public constructor() { - return AudioFilters; - } - - public static get filters(): Record { - return { - bassboost_low: bass(15), - bassboost: bass(20), - bassboost_high: bass(30), - "8D": "apulsator=hz=0.09", - vaporwave: "aresample=48000,asetrate=48000*0.8", - nightcore: "aresample=48000,asetrate=48000*1.25", - phaser: "aphaser=in_gain=0.4", - tremolo: "tremolo", - vibrato: "vibrato=f=6.5", - reverse: "areverse", - treble: "treble=g=5", - normalizer2: "dynaudnorm=g=101", - normalizer: "acompressor", - surrounding: "surround", - pulsator: "apulsator=hz=1", - subboost: "asubboost", - karaoke: "stereotools=mlev=0.03", - flanger: "flanger", - gate: "agate", - haas: "haas", - mcompand: "mcompand", - mono: "pan=mono|c0=.5*c0+.5*c1", - mstlr: "stereotools=mode=ms>lr", - mstrr: "stereotools=mode=ms>rr", - compressor: "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6", - expander: "compand=attacks=0:points=-80/-169|-54/-80|-49.5/-64.6|-41.1/-41.1|-25.8/-15|-10.8/-4.5|0/0|20/8.3", - softlimiter: "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8", - chorus: "chorus=0.7:0.9:55:0.4:0.25:2", - chorus2d: "chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3", - chorus3d: "chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3", - fadein: "afade=t=in:ss=0:d=10", - dim: `afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'"`, - earrape: "channelsplit,sidechaingate=level_in=64" - }; - } - - public static get(name: K) { - return this.filters[name]; - } - - public static has(name: K) { - return name in this.filters; - } - - public static *[Symbol.iterator](): IterableIterator<{ name: FiltersName; value: string }> { - for (const [k, v] of Object.entries(this.filters)) { - yield { name: k as FiltersName, value: v as string }; - } - } - - public static get names() { - return Object.keys(this.filters) as FiltersName[]; - } - - // @ts-expect-error AudioFilters.length - public static get length() { - return this.names.length; - } - - public static toString() { - return this.names.map((m) => (this as any)[m]).join(","); // eslint-disable-line @typescript-eslint/no-explicit-any - } - - /** - * Create ffmpeg args from the specified filters name - * @param filter The filter name - * @returns - */ - public static create(filters?: K[]) { - if (!filters || !Array.isArray(filters)) return this.toString(); - return filters - .filter((predicate) => typeof predicate === "string") - .map((m) => this.get(m)) - .join(","); - } - - /** - * Defines audio filter - * @param filterName The name of the filter - * @param value The ffmpeg args - */ - public static define(filterName: string, value: string) { - this.filters[filterName as FiltersName] = value; - } - - /** - * Defines multiple audio filters - * @param filtersArray Array of filters containing the filter name and ffmpeg args - */ - public static defineBulk(filtersArray: { name: string; value: string }[]) { - filtersArray.forEach((arr) => this.define(arr.name, arr.value)); - } -} - -export default AudioFilters; -export { AudioFilters }; diff --git a/helpers/Music/src/utils/FFmpegStream.ts b/helpers/Music/src/utils/FFmpegStream.ts deleted file mode 100644 index 9f49b283..00000000 --- a/helpers/Music/src/utils/FFmpegStream.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { FFmpeg } from "prism-media"; -import type { Duplex, Readable } from "stream"; - -export interface FFmpegStreamOptions { - fmt?: string; - encoderArgs?: string[]; - seek?: number; - skip?: boolean; -} - -export function FFMPEG_ARGS_STRING(stream: string, fmt?: string) { - // prettier-ignore - return [ - "-reconnect", "1", - "-reconnect_streamed", "1", - "-reconnect_delay_max", "5", - "-i", stream, - "-analyzeduration", "0", - "-loglevel", "0", - "-f", `${typeof fmt === "string" ? fmt : "s16le"}`, - "-ar", "48000", - "-ac", "2" - ]; -} - -export function FFMPEG_ARGS_PIPED(fmt?: string) { - // prettier-ignore - return [ - "-analyzeduration", "0", - "-loglevel", "0", - "-f", `${typeof fmt === "string" ? fmt : "s16le"}`, - "-ar", "48000", - "-ac", "2" - ]; -} - -/** - * Creates FFmpeg stream - * @param stream The source stream - * @param options FFmpeg stream options - */ -export function createFFmpegStream(stream: Readable | Duplex | string, options?: FFmpegStreamOptions) { - if (options.skip && typeof stream !== "string") return stream; - options ??= {}; - const args = typeof stream === "string" ? FFMPEG_ARGS_STRING(stream, options.fmt) : FFMPEG_ARGS_PIPED(options.fmt); - - if (!Number.isNaN(options.seek)) args.unshift("-ss", String(options.seek)); - if (Array.isArray(options.encoderArgs)) args.push(...options.encoderArgs); - - const transcoder = new FFmpeg({ shell: false, args }); - transcoder.on("close", () => transcoder.destroy()); - - if (typeof stream !== "string") { - stream.on("error", () => transcoder.destroy()); - stream.pipe(transcoder); - } - - return transcoder; -} diff --git a/helpers/Music/src/utils/QueryResolver.ts b/helpers/Music/src/utils/QueryResolver.ts deleted file mode 100644 index fc6c2b2b..00000000 --- a/helpers/Music/src/utils/QueryResolver.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { QueryType } from "../types/types"; -import play from "play-dl"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment - -// scary things below *sigh* -const spotifySongRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/; -const spotifyPlaylistRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/; -const spotifyAlbumRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/; -const vimeoRegex = /(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)/; -const facebookRegex = /(https?:\/\/)(www\.|m\.)?(facebook|fb).com\/.*\/videos\/.*/; -const reverbnationRegex = /https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/; -const attachmentRegex = - /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/; -// scary things above *sigh* - -class QueryResolver { - /** - * Query resolver - */ - private constructor() {} // eslint-disable-line @typescript-eslint/no-empty-function - - /** - * Resolves the given search query - * @param {string} query The query - * @returns {QueryType} - */ - static async resolve(query: string): Promise { - if (await play.so_validate(query) === "track") return QueryType.SOUNDCLOUD_TRACK; - if (await play.so_validate(query) === "playlist" || query.includes("/sets/")) return QueryType.SOUNDCLOUD_PLAYLIST; - if (play.yt_validate(query) === "playlist") return QueryType.YOUTUBE_PLAYLIST; - if (play.yt_validate(query) === "video") return QueryType.YOUTUBE_VIDEO; - if (spotifySongRegex.test(query)) return QueryType.SPOTIFY_SONG; - if (spotifyPlaylistRegex.test(query)) return QueryType.SPOTIFY_PLAYLIST; - if (spotifyAlbumRegex.test(query)) return QueryType.SPOTIFY_ALBUM; - if (vimeoRegex.test(query)) return QueryType.VIMEO; - if (facebookRegex.test(query)) return QueryType.FACEBOOK; - if (reverbnationRegex.test(query)) return QueryType.REVERBNATION; - if (attachmentRegex.test(query)) return QueryType.ARBITRARY; - - return QueryType.YOUTUBE_SEARCH; - } - - /** - * Parses vimeo id from url - * @param {string} query The query - * @returns {string} - */ - static async getVimeoID(query: string): Promise { - return await QueryResolver.resolve(query) === QueryType.VIMEO - ? query - .split("/") - .filter((x) => !!x) - .pop() - : null; - } -} - -export { QueryResolver }; diff --git a/helpers/Music/src/utils/Util.ts b/helpers/Music/src/utils/Util.ts deleted file mode 100644 index f173feeb..00000000 --- a/helpers/Music/src/utils/Util.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { StageChannel, VoiceChannel } from "discord.js"; -import { TimeData } from "../types/types"; - -class Util { - /** - * Utils - */ - private constructor() {} // eslint-disable-line @typescript-eslint/no-empty-function - - /** - * Creates duration string - * @param {object} durObj The duration object - * @returns {string} - */ - static durationString(durObj: Record) { - return Object.values(durObj) - .map((m) => (isNaN(m) ? 0 : m)) - .join(":"); - } - - /** - * Parses milliseconds to consumable time object - * @param {number} milliseconds The time in ms - * @returns {TimeData} - */ - static parseMS(milliseconds: number) { - const round = milliseconds > 0 ? Math.floor : Math.ceil; - - return { - days: round(milliseconds / 86400000), - hours: round(milliseconds / 3600000) % 24, - minutes: round(milliseconds / 60000) % 60, - seconds: round(milliseconds / 1000) % 60 - } as TimeData; - } - - /** - * Builds time code - * @param {TimeData} duration The duration object - * @returns {string} - */ - static buildTimeCode(duration: TimeData) { - const items = Object.keys(duration); - const required = ["days", "hours", "minutes", "seconds"]; - - const parsed = items.filter((x) => required.includes(x)).map((m) => duration[m as keyof TimeData]); - const final = parsed - .slice(parsed.findIndex((x) => x !== 0)) - .map((x) => x.toString().padStart(2, "0")) - .join(":"); - - return final.length <= 3 ? `0:${final.padStart(2, "0") || 0}` : final; - } - - /** - * Picks last item of the given array - * @param {any[]} arr The array - * @returns {any} - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - static last(arr: T[]): T { - if (!Array.isArray(arr)) return; - return arr[arr.length - 1]; - } - - /** - * Checks if the voice channel is empty - * @param {VoiceChannel|StageChannel} channel The voice channel - * @returns {boolean} - */ - static isVoiceEmpty(channel: VoiceChannel | StageChannel) { - return channel.members.filter((member) => !member.user.bot).size === 0; - } - - /** - * Safer require - * @param {string} id Node require id - * @returns {any} - */ - static require(id: string) { - try { - return require(id); - } catch { - return null; - } - } - - /** - * Asynchronous timeout - * @param {number} time The time in ms to wait - * @returns {Promise} - */ - static wait(time: number) { - return new Promise((r) => setTimeout(r, time).unref()); - } - - static noop() {} // eslint-disable-line @typescript-eslint/no-empty-function - - static async getFetch() { - if ("fetch" in globalThis) return globalThis.fetch; - for (const lib of ["undici", "node-fetch"]) { - try { - return await import(lib).then((res) => res.fetch || res.default?.fetch || res.default); - } catch { - try { - // eslint-disable-next-line - const res = require(lib); - if (res) return res.fetch || res.default?.fetch || res.default; - } catch { - // no? - } - } - } - } -} - -export { Util }; diff --git a/helpers/Music/tsconfig.json b/helpers/Music/tsconfig.json deleted file mode 100644 index 0476f759..00000000 --- a/helpers/Music/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "commonjs", - "declaration": true, - "outDir": "./dist", - "strict": true, - "strictNullChecks": false, - "esModuleInterop": true, - "pretty": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "importHelpers": true - }, - "include": [ - "src/**/*" - ] -} diff --git a/package-lock.json b/package-lock.json index ff2f326f..0f977d58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "cron": "^2.1.0", "discord-api-types": "^0.37.5", "discord-giveaways": "^6.0.1", + "discord-player-play-dl": "^5.3.2", "discord.js": "^14.3.0", "ejs": "^3.1.3", "express": "^4.17.1", @@ -1478,6 +1479,19 @@ "discord.js": ">=14.0.0" } }, + "node_modules/discord-player-play-dl": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/discord-player-play-dl/-/discord-player-play-dl-5.3.2.tgz", + "integrity": "sha512-KBoQddJst0Xj8qFxikHCLlbHAVup5tDp+aE5rQIY5rG4t/D9As9LHKoiXIKnrjAfa9y4QvQeTMGJWDRYYBabsQ==", + "dependencies": { + "@discordjs/voice": "^0.11.0", + "libsodium-wrappers": "^0.7.10", + "play-dl": "^1.9.5", + "spotify-url-info": "^3.1.2", + "tiny-typed-emitter": "^2.1.0", + "tslib": "^2.4.0" + } + }, "node_modules/discord.js": { "version": "14.3.0", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", @@ -2485,6 +2499,11 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, + "node_modules/himalaya": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz", + "integrity": "sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==" + }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -2886,6 +2905,19 @@ "node": ">= 0.8.0" } }, + "node_modules/libsodium": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz", + "integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ==" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", + "integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==", + "dependencies": { + "libsodium": "^0.7.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4230,6 +4262,26 @@ "memory-pager": "^1.0.2" } }, + "node_modules/spotify-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-3.0.3.tgz", + "integrity": "sha512-mMstJ4dAMki6GbUjg94kp/h9ZH+7T7+ro/KUC00WVh+WKoLgMRrTKLkWMIwCZNO53Xa8DRHQw/6jwYtRZrVI3g==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/spotify-url-info": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.1.8.tgz", + "integrity": "sha512-XxDRxDtTd9p1X22+dWweqB2bf41UVRZgyvq8VmLyY4iuClR/4/LGWOqcqG/zh9BwLUtony4818QrJ2bp2tbUkg==", + "dependencies": { + "himalaya": "~1.1.0", + "spotify-uri": "~3.0.3" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -5784,6 +5836,19 @@ "serialize-javascript": "^6.0.0" } }, + "discord-player-play-dl": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/discord-player-play-dl/-/discord-player-play-dl-5.3.2.tgz", + "integrity": "sha512-KBoQddJst0Xj8qFxikHCLlbHAVup5tDp+aE5rQIY5rG4t/D9As9LHKoiXIKnrjAfa9y4QvQeTMGJWDRYYBabsQ==", + "requires": { + "@discordjs/voice": "^0.11.0", + "libsodium-wrappers": "^0.7.10", + "play-dl": "^1.9.5", + "spotify-url-info": "^3.1.2", + "tiny-typed-emitter": "^2.1.0", + "tslib": "^2.4.0" + } + }, "discord.js": { "version": "14.3.0", "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.3.0.tgz", @@ -6561,6 +6626,11 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, + "himalaya": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.0.tgz", + "integrity": "sha512-LLase1dHCRMel68/HZTFft0N0wti0epHr3nNY7ynpLbyZpmrKMQ8YIpiOV77TM97cNpC8Wb2n6f66IRggwdWPw==" + }, "html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -6847,6 +6917,19 @@ "type-check": "~0.4.0" } }, + "libsodium": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.10.tgz", + "integrity": "sha512-eY+z7hDrDKxkAK+QKZVNv92A5KYkxfvIshtBJkmg5TSiCnYqZP3i9OO9whE79Pwgm4jGaoHgkM4ao/b9Cyu4zQ==" + }, + "libsodium-wrappers": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz", + "integrity": "sha512-pO3F1Q9NPLB/MWIhehim42b/Fwb30JNScCNh8TcQ/kIc+qGLQch8ag8wb0keK3EP5kbGakk1H8Wwo7v+36rNQg==", + "requires": { + "libsodium": "^0.7.0" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7802,6 +7885,20 @@ "memory-pager": "^1.0.2" } }, + "spotify-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-3.0.3.tgz", + "integrity": "sha512-mMstJ4dAMki6GbUjg94kp/h9ZH+7T7+ro/KUC00WVh+WKoLgMRrTKLkWMIwCZNO53Xa8DRHQw/6jwYtRZrVI3g==" + }, + "spotify-url-info": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.1.8.tgz", + "integrity": "sha512-XxDRxDtTd9p1X22+dWweqB2bf41UVRZgyvq8VmLyY4iuClR/4/LGWOqcqG/zh9BwLUtony4818QrJ2bp2tbUkg==", + "requires": { + "himalaya": "~1.1.0", + "spotify-uri": "~3.0.3" + } + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", diff --git a/package.json b/package.json index b656befa..d1bf5e22 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "cron": "^2.1.0", "discord-api-types": "^0.37.5", "discord-giveaways": "^6.0.1", + "discord-player-play-dl": "^5.3.2", "discord.js": "^14.3.0", "ejs": "^3.1.3", "express": "^4.17.1",