distube 4.1.1 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -29
- package/dist/index.d.ts +804 -510
- package/dist/index.js +568 -465
- package/dist/index.js.map +1 -1
- package/package.json +40 -64
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/index.ts","../src/type.ts","../src/constant.ts","../src/struct/DisTubeError.ts","../src/struct/TaskQueue.ts","../src/struct/Playlist.ts","../src/struct/SearchResult.ts","../src/struct/Song.ts","../src/core/DisTubeBase.ts","../src/core/DisTubeVoice.ts","../src/core/DisTubeStream.ts","../src/core/DisTubeHandler.ts","../src/core/DisTubeOptions.ts","../src/core/manager/BaseManager.ts","../src/core/manager/GuildIdManager.ts","../src/core/manager/DisTubeVoiceManager.ts","../src/core/manager/FilterManager.ts","../src/core/manager/QueueManager.ts","../src/struct/Queue.ts","../src/struct/Plugin.ts","../src/struct/CustomPlugin.ts","../src/struct/ExtractorPlugin.ts","../src/util.ts","../src/plugin/DirectLink.ts","../src/DisTube.ts"],"sourcesContent":["{\n \"name\": \"distube\",\n \"version\": \"4.1.1\",\n \"description\": \"A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": \"./dist/index.js\",\n \"directories\": {\n \"lib\": \"src\",\n \"test\": \"tests\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"test\": \"jest\",\n \"docs\": \"docgen -s src/**/*.ts -o docs.json -c pages/index.yml -g -j jsdoc.config.json\",\n \"lint\": \"prettier --check . && eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prettier\": \"prettier --write \\\"**/*.{ts,json,yml,yaml,md}\\\"\",\n \"build\": \"tsup\",\n \"build:check\": \"tsc --noEmit\",\n \"update\": \"ncu -u && yarn up '**' -R\",\n \"postinstall\": \"husky install\",\n \"prepublishOnly\": \"yarn lint && yarn test\",\n \"prepack\": \"yarn build && pinst --disable\",\n \"postpack\": \"pinst --enable\",\n \"dev:add-docs-to-worktree\": \"git worktree add --track -b docs docs origin/docs\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/skick1234/DisTube.git\"\n },\n \"keywords\": [\n \"youtube\",\n \"music\",\n \"discord\",\n \"discordjs\",\n \"bot\",\n \"distube\",\n \"queue\",\n \"musicbot\",\n \"discord-music-bot\",\n \"music-bot\",\n \"discord-js\"\n ],\n \"author\": \"Skick (https://github.com/skick1234)\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/skick1234/DisTube/issues\"\n },\n \"funding\": [\n {\n \"type\": \"individual\",\n \"url\": \"https://paypal.me/Skickkk\"\n },\n {\n \"type\": \"patreon\",\n \"url\": \"https://patreon.com/DisTube\"\n }\n ],\n \"homepage\": \"https://distube.js.org/\",\n \"dependencies\": {\n \"@distube/ytdl-core\": \"^4.13.2\",\n \"@distube/ytpl\": \"^1.2.1\",\n \"@distube/ytsr\": \"^1.2.0\",\n \"prism-media\": \"npm:@distube/prism-media@latest\",\n \"tiny-typed-emitter\": \"^2.1.0\",\n \"tough-cookie\": \"^4.1.3\",\n \"tslib\": \"^2.6.2\",\n \"undici\": \"^5.27.2\"\n },\n \"devDependencies\": {\n \"@babel/core\": \"^7.23.2\",\n \"@babel/plugin-proposal-class-properties\": \"^7.18.6\",\n \"@babel/plugin-proposal-object-rest-spread\": \"^7.20.7\",\n \"@babel/plugin-transform-private-methods\": \"^7.22.5\",\n \"@babel/preset-env\": \"^7.23.2\",\n \"@babel/preset-typescript\": \"^7.23.2\",\n \"@commitlint/cli\": \"^18.2.0\",\n \"@commitlint/config-conventional\": \"^18.1.0\",\n \"@discordjs/voice\": \"^0.16.0\",\n \"@distubejs/docgen\": \"distubejs/docgen\",\n \"@types/jest\": \"^29.5.8\",\n \"@types/node\": \"^20.9.0\",\n \"@types/tough-cookie\": \"^4.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^6.10.0\",\n \"@typescript-eslint/parser\": \"^6.10.0\",\n \"babel-jest\": \"^29.7.0\",\n \"discord.js\": \"^14.13.0\",\n \"eslint\": \"^8.53.0\",\n \"eslint-config-distube\": \"^1.6.4\",\n \"eslint-config-prettier\": \"^9.0.0\",\n \"eslint-plugin-deprecation\": \"^2.0.0\",\n \"eslint-plugin-jsdoc\": \"^46.8.2\",\n \"husky\": \"^8.0.3\",\n \"jest\": \"^29.7.0\",\n \"jsdoc-babel\": \"^0.5.0\",\n \"nano-staged\": \"^0.8.0\",\n \"npm-check-updates\": \"^16.14.6\",\n \"pinst\": \"^3.0.0\",\n \"prettier\": \"^3.0.3\",\n \"tsup\": \"^7.2.0\",\n \"typescript\": \"^5.2.2\"\n },\n \"peerDependencies\": {\n \"@discordjs/opus\": \"*\",\n \"@discordjs/voice\": \"*\",\n \"discord.js\": \"14\"\n },\n \"peerDependenciesMeta\": {\n \"@discordjs/opus\": {\n \"optional\": true\n }\n },\n \"nano-staged\": {\n \"*.ts\": [\n \"prettier --write\",\n \"eslint\"\n ],\n \"*.{json,yml,yaml,md}\": [\n \"prettier --write\"\n ]\n },\n \"engines\": {\n \"node\": \">=16.9.0\"\n },\n \"packageManager\": \"yarn@3.6.1\"\n}\n","export * from \"./type\";\nexport * from \"./constant\";\nexport * from \"./struct\";\nexport * from \"./util\";\nexport * from \"./core\";\nexport * from \"./plugin\";\nexport { DisTube, DisTube as default, version } from \"./DisTube\";\n","import type ytdl from \"@distube/ytdl-core\";\nimport type {\n Guild,\n GuildMember,\n GuildTextBasedChannel,\n Interaction,\n Message,\n Snowflake,\n VoiceBasedChannel,\n VoiceState,\n} from \"discord.js\";\nimport type { CustomPlugin, DisTubeVoice, ExtractorPlugin, Playlist, Queue, SearchResult, Song } from \".\";\nimport type { Cookie } from \"@distube/ytdl-core\";\n\nexport type Awaitable<T = any> = T | PromiseLike<T>;\n\nexport type DisTubeVoiceEvents = {\n disconnect: (error?: Error) => Awaitable;\n error: (error: Error) => Awaitable;\n finish: () => Awaitable;\n};\n\nexport type DisTubeEvents = {\n error: [channel: GuildTextBasedChannel | undefined, error: Error];\n addList: [queue: Queue, playlist: Playlist];\n addSong: [queue: Queue, song: Song];\n playSong: [queue: Queue, song: Song];\n finishSong: [queue: Queue, song: Song];\n empty: [queue: Queue];\n finish: [queue: Queue];\n initQueue: [queue: Queue];\n noRelated: [queue: Queue];\n disconnect: [queue: Queue];\n deleteQueue: [queue: Queue];\n searchCancel: [message: Message<true>, query: string];\n searchNoResult: [message: Message<true>, query: string];\n searchDone: [message: Message<true>, answer: Message<true>, query: string];\n searchInvalidAnswer: [message: Message<true>, answer: Message<true>, query: string];\n searchResult: [message: Message<true>, results: SearchResult[], query: string];\n};\n\nexport type TypedDisTubeEvents = {\n [K in keyof DisTubeEvents]: (...args: DisTubeEvents[K]) => Awaitable;\n};\n\n/**\n * An FFmpeg audio filter object\n * ```\n * {\n * name: \"bassboost\",\n * value: \"bass=g=10\"\n * }\n * ```\n * @typedef {Object} Filter\n * @prop {string} name Name of the filter\n * @prop {string} value FFmpeg audio filter(s)\n */\nexport interface Filter {\n name: string;\n value: string;\n}\n\n/**\n * Data that resolves to give an FFmpeg audio filter. This can be:\n * - A name of a default filters or custom filters (`string`)\n * - A {@link Filter} object\n * @typedef {string|Filter} FilterResolvable\n * @see {@link defaultFilters}\n * @see {@link DisTubeOptions|DisTubeOptions.customFilters}\n */\nexport type FilterResolvable = string | Filter;\n\n/**\n * FFmpeg Filters\n * ```\n * {\n * \"Filter Name\": \"Filter Value\",\n * \"bassboost\": \"bass=g=10\"\n * }\n * ```\n * @typedef {Object.<string, string>} Filters\n * @see {@link defaultFilters}\n */\nexport type Filters = Record<string, string>;\n\n/**\n * DisTube options.\n * @typedef {Object} DisTubeOptions\n * @prop {Array<CustomPlugin|ExtractorPlugin>} [plugins] DisTube plugins.\n * @prop {boolean} [emitNewSongOnly=false] Whether or not emitting {@link DisTube#event:playSong} event\n * when looping a song or next song is the same as the previous one\n * @prop {boolean} [leaveOnEmpty=true] Whether or not leaving voice channel\n * if the voice channel is empty after {@link DisTubeOptions}.emptyCooldown seconds.\n * @prop {boolean} [leaveOnFinish=false] Whether or not leaving voice channel when the queue ends.\n * @prop {boolean} [leaveOnStop=true] Whether or not leaving voice channel after using {@link DisTube#stop} function.\n * @prop {boolean} [savePreviousSongs=true] Whether or not saving the previous songs of the queue\n * and enable {@link DisTube#previous} method\n * @prop {number} [searchSongs=0] Limit of search results emits in {@link DisTube#event:searchResult} event\n * when {@link DisTube#play} method executed. If `searchSongs <= 1`, play the first result\n * @prop {Cookie[]|string} [youtubeCookie] YouTube cookies. Guide: {@link https://distube.js.org/#/docs/DisTube/main/general/cookie YouTube Cookies}\n * @prop {Filters} [customFilters] Override {@link defaultFilters} or add more ffmpeg filters.\n * @prop {ytdl.getInfoOptions} [ytdlOptions] `ytdl-core` get info options\n * @prop {number} [searchCooldown=60] Built-in search cooldown in seconds (When searchSongs is bigger than 0)\n * @prop {number} [emptyCooldown=60] Built-in leave on empty cooldown in seconds (When leaveOnEmpty is true)\n * @prop {boolean} [nsfw=false] Whether or not playing age-restricted content\n * and disabling safe search in non-NSFW channel.\n * @prop {boolean} [emitAddListWhenCreatingQueue=true] Whether or not emitting `addList` event when creating a new Queue\n * @prop {boolean} [emitAddSongWhenCreatingQueue=true] Whether or not emitting `addSong` event when creating a new Queue\n * @prop {boolean} [joinNewVoiceChannel=true] Whether or not joining the new voice channel\n * when using {@link DisTube#play} method\n * @prop {StreamType} [streamType=StreamType.OPUS] Decide the {@link DisTubeStream#type} will be used\n * (Not the same as {@link DisTubeStream#type})\n * @prop {boolean} [directLink=true] Whether or not playing a song with direct link\n */\nexport type DisTubeOptions = {\n plugins?: (CustomPlugin | ExtractorPlugin)[];\n emitNewSongOnly?: boolean;\n leaveOnFinish?: boolean;\n leaveOnStop?: boolean;\n leaveOnEmpty?: boolean;\n emptyCooldown?: number;\n savePreviousSongs?: boolean;\n searchSongs?: number;\n searchCooldown?: number;\n youtubeCookie?: Cookie[] | string;\n customFilters?: Filters;\n ytdlOptions?: ytdl.downloadOptions;\n nsfw?: boolean;\n emitAddSongWhenCreatingQueue?: boolean;\n emitAddListWhenCreatingQueue?: boolean;\n joinNewVoiceChannel?: boolean;\n streamType?: StreamType;\n directLink?: boolean;\n};\n\n/**\n * Data that can be resolved to give a guild id string. This can be:\n * - A guild id string | a guild {@link https://discord.js.org/#/docs/main/stable/class/Snowflake|Snowflake}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Guild|Guild}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Message|Message}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/BaseGuildVoiceChannel|BaseGuildVoiceChannel}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/BaseGuildTextChannel|BaseGuildTextChannel}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/VoiceState|VoiceState}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/GuildMember|GuildMember}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Interaction|Interaction}\n * - A {@link DisTubeVoice}\n * - A {@link Queue}\n * @typedef {\n * Discord.Snowflake|\n * Discord.Guild|\n * Discord.Message|\n * Discord.BaseGuildVoiceChannel|\n * Discord.BaseGuildTextChannel|\n * Discord.VoiceState|\n * Discord.GuildMember|\n * Discord.Interaction|\n * DisTubeVoice|\n * Queue|\n * string\n * } GuildIdResolvable\n */\nexport type GuildIdResolvable =\n | Queue\n | DisTubeVoice\n | Snowflake\n | Message\n | GuildTextBasedChannel\n | VoiceBasedChannel\n | VoiceState\n | Guild\n | GuildMember\n | Interaction\n | string;\n\nexport interface OtherSongInfo {\n src: string;\n id?: string;\n title?: string;\n name?: string;\n is_live?: boolean;\n isLive?: boolean;\n _duration_raw?: string | number;\n duration?: string | number;\n webpage_url?: string;\n url: string;\n thumbnail?: string;\n related?: RelatedSong[];\n view_count?: string | number;\n views?: string | number;\n like_count?: string | number;\n likes?: string | number;\n dislike_count?: string | number;\n dislikes?: string | number;\n repost_count?: string | number;\n reposts?: string | number;\n uploader?: string | { name: string; url: string };\n uploader_url?: string;\n age_limit?: string | number;\n chapters?: Chapter[];\n age_restricted?: boolean;\n}\n\nexport interface Chapter {\n title: string;\n start_time: number;\n}\n\nexport interface PlaylistInfo {\n source: string;\n member?: GuildMember;\n songs: Song[];\n name?: string;\n url?: string;\n thumbnail?: string;\n /** @deprecated */\n title?: string;\n /** @deprecated */\n webpage_url?: string;\n}\n\nexport type RelatedSong = Omit<Song, \"related\">;\n\n/**\n * @typedef {Object} PlayHandlerOptions\n * @prop {Discord.BaseGuildTextChannel} [options.textChannel] The default text channel of the queue\n * @prop {boolean} [options.skip=false] Skip the playing song (if exists) and play the added playlist instantly\n * @prop {number} [options.position=0] Position of the song/playlist to add to the queue,\n * <= 0 to add to the end of the queue.\n */\nexport type PlayHandlerOptions = {\n skip?: boolean;\n position?: number;\n textChannel?: GuildTextBasedChannel;\n};\n\n/**\n * @typedef {Object} PlayOptions\n * @prop {Discord.GuildMember} [member] Requested user (default is your bot)\n * @prop {Discord.BaseGuildTextChannel} [textChannel] Default {@link Queue#textChannel}\n * @prop {boolean} [skip=false]\n * Skip the playing song (if exists) and play the added song/playlist if `position` is 1.\n * If `position` is defined and not equal to 1, it will skip to the next song instead of the added song\n * @prop {number} [position=0] Position of the song/playlist to add to the queue,\n * <= 0 to add to the end of the queue.\n * @prop {Discord.Message} [message] Called message (For built-in search events. If this is a {@link https://developer.mozilla.org/en-US/docs/Glossary/Falsy|falsy value}, it will play the first result instead)\n * @prop {*} [metadata] Optional metadata that can be attached to the song/playlist will be played,\n * This is useful for identification purposes when the song/playlist is passed around in events.\n * See {@link Song#metadata} or {@link Playlist#metadata}\n */\nexport interface PlayOptions extends PlayHandlerOptions, ResolveOptions<any> {\n message?: Message;\n}\n\n/**\n * @typedef {Object} ResolveOptions\n * @prop {Discord.GuildMember} [member] Requested user\n * @prop {*} [metadata] Metadata\n */\nexport interface ResolveOptions<T = unknown> {\n member?: GuildMember;\n metadata?: T;\n}\n\n/**\n * @typedef {ResolveOptions} ResolvePlaylistOptions\n * @prop {string} [source] Source of the playlist\n */\nexport interface ResolvePlaylistOptions<T = unknown> extends ResolveOptions<T> {\n source?: string;\n}\n\n/**\n * @typedef {Object} CustomPlaylistOptions\n * @prop {Discord.GuildMember} [member] A guild member creating the playlist\n * @prop {Object} [properties] Additional properties such as `name`\n * @prop {boolean} [parallel=true] Whether or not fetch the songs in parallel\n * @prop {*} [metadata] Metadata\n */\nexport interface CustomPlaylistOptions {\n member?: GuildMember;\n properties?: Record<string, any>;\n parallel?: boolean;\n metadata?: any;\n}\n\n/**\n * The repeat mode of a {@link Queue}\n * * `DISABLED` = 0\n * * `SONG` = 1\n * * `QUEUE` = 2\n * @typedef {number} RepeatMode\n */\nexport enum RepeatMode {\n DISABLED,\n SONG,\n QUEUE,\n}\n\n/**\n * All available plugin types:\n * * `CUSTOM` = `\"custom\"`: {@link CustomPlugin}\n * * `EXTRACTOR` = `\"extractor\"`: {@link ExtractorPlugin}\n * @typedef {\"custom\"|\"extractor\"} PluginType\n */\nexport enum PluginType {\n CUSTOM = \"custom\",\n EXTRACTOR = \"extractor\",\n}\n\n/**\n * Search result types:\n * * `VIDEO` = `\"video\"`\n * * `PLAYLIST` = `\"playlist\"`\n * @typedef {\"video\"|\"playlist\"} SearchResultType\n */\nexport enum SearchResultType {\n VIDEO = \"video\",\n PLAYLIST = \"playlist\",\n}\n\n/**\n * Stream types:\n * * `OPUS` = `0` (Better quality, use more resources - **Recommended**)\n * * `RAW` = `1` (Better performance, use less resources)\n * @typedef {number} StreamType\n * @type {StreamType}\n */\nexport enum StreamType {\n OPUS,\n RAW,\n}\n\n/**\n * @typedef {Object} Events\n * @prop {string} ERROR error\n * @prop {string} ADD_LIST addList\n * @prop {string} ADD_SONG addSong\n * @prop {string} PLAY_SONG playSong\n * @prop {string} FINISH_SONG finishSong\n * @prop {string} EMPTY empty\n * @prop {string} FINISH finish\n * @prop {string} INIT_QUEUE initQueue\n * @prop {string} NO_RELATED noRelated\n * @prop {string} DISCONNECT disconnect\n * @prop {string} DELETE_QUEUE deleteQueue\n * @prop {string} SEARCH_CANCEL searchCancel\n * @prop {string} SEARCH_NO_RESULT searchNoResult\n * @prop {string} SEARCH_DONE searchDone\n * @prop {string} SEARCH_INVALID_ANSWER searchInvalidAnswer\n * @prop {string} SEARCH_RESULT searchResult\n */\nexport enum Events {\n ERROR = \"error\",\n ADD_LIST = \"addList\",\n ADD_SONG = \"addSong\",\n PLAY_SONG = \"playSong\",\n FINISH_SONG = \"finishSong\",\n EMPTY = \"empty\",\n FINISH = \"finish\",\n INIT_QUEUE = \"initQueue\",\n NO_RELATED = \"noRelated\",\n DISCONNECT = \"disconnect\",\n DELETE_QUEUE = \"deleteQueue\",\n SEARCH_CANCEL = \"searchCancel\",\n SEARCH_NO_RESULT = \"searchNoResult\",\n SEARCH_DONE = \"searchDone\",\n SEARCH_INVALID_ANSWER = \"searchInvalidAnswer\",\n SEARCH_RESULT = \"searchResult\",\n}\n","import { StreamType } from \".\";\nimport type { Filters } from \".\";\n\n/**\n * Default DisTube audio filters.\n * @typedef {Object} defaultFilters\n * @prop {string} 3d 3d\n * @prop {string} bassboost bassboost\n * @prop {string} echo echo\n * @prop {string} karaoke karaoke\n * @prop {string} nightcore nightcore\n * @prop {string} vaporwave vaporwave\n * @prop {string} flanger flanger\n * @prop {string} gate gate\n * @prop {string} haas haas\n * @prop {string} reverse reverse\n * @prop {string} surround surround\n * @prop {string} mcompand mcompand\n * @prop {string} phaser phaser\n * @prop {string} tremolo tremolo\n * @prop {string} earwax earwax\n */\nexport const defaultFilters: Filters = {\n \"3d\": \"apulsator=hz=0.125\",\n bassboost: \"bass=g=10\",\n echo: \"aecho=0.8:0.9:1000:0.3\",\n flanger: \"flanger\",\n gate: \"agate\",\n haas: \"haas\",\n karaoke: \"stereotools=mlev=0.1\",\n nightcore: \"asetrate=48000*1.25,aresample=48000,bass=g=5\",\n reverse: \"areverse\",\n vaporwave: \"asetrate=48000*0.8,aresample=48000,atempo=1.1\",\n mcompand: \"mcompand\",\n phaser: \"aphaser\",\n tremolo: \"tremolo\",\n surround: \"surround\",\n earwax: \"earwax\",\n};\n\nexport const defaultOptions = {\n plugins: [],\n emitNewSongOnly: false,\n leaveOnEmpty: true,\n leaveOnFinish: false,\n leaveOnStop: true,\n savePreviousSongs: true,\n searchSongs: 0,\n ytdlOptions: {},\n searchCooldown: 60,\n emptyCooldown: 60,\n nsfw: false,\n emitAddSongWhenCreatingQueue: true,\n emitAddListWhenCreatingQueue: true,\n joinNewVoiceChannel: true,\n streamType: StreamType.OPUS,\n directLink: true,\n};\n","import { inspect } from \"node:util\";\n\nconst ERROR_MESSAGES = {\n INVALID_TYPE: (expected: (number | string) | readonly (number | string)[], got: any, name?: string) =>\n `Expected ${\n Array.isArray(expected) ? expected.map(e => (typeof e === \"number\" ? e : `'${e}'`)).join(\" or \") : `'${expected}'`\n }${name ? ` for '${name}'` : \"\"}, but got ${inspect(got)} (${typeof got})`,\n NUMBER_COMPARE: (name: string, expected: string, value: number) => `'${name}' must be ${expected} ${value}`,\n EMPTY_ARRAY: (name: string) => `'${name}' is an empty array`,\n EMPTY_FILTERED_ARRAY: (name: string, type: string) => `There is no valid '${type}' in the '${name}' array`,\n EMPTY_STRING: (name: string) => `'${name}' string must not be empty`,\n INVALID_KEY: (obj: string, key: string) => `'${key}' does not need to be provided in ${obj}`,\n MISSING_KEY: (obj: string, key: string) => `'${key}' needs to be provided in ${obj}`,\n MISSING_KEYS: (obj: string, key: string[], all: boolean) =>\n `${key.map(k => `'${k}'`).join(all ? \" and \" : \" or \")} need to be provided in ${obj}`,\n\n MISSING_INTENTS: (i: string) => `${i} intent must be provided for the Client`,\n DISABLED_OPTION: (o: string) => `DisTubeOptions.${o} is disabled`,\n ENABLED_OPTION: (o: string) => `DisTubeOptions.${o} is enabled`,\n\n NOT_IN_VOICE: \"User is not in any voice channel\",\n VOICE_FULL: \"The voice channel is full\",\n VOICE_CONNECT_FAILED: (s: number) => `Cannot connect to the voice channel after ${s} seconds`,\n VOICE_MISSING_PERMS: \"I do not have permission to join this voice channel\",\n VOICE_RECONNECT_FAILED: \"Cannot reconnect to the voice channel\",\n VOICE_DIFFERENT_GUILD: \"Cannot join a voice channel in a different guild\",\n VOICE_DIFFERENT_CLIENT: \"Cannot join a voice channel created by a different client\",\n\n NO_QUEUE: \"There is no playing queue in this guild\",\n QUEUE_EXIST: \"This guild has a Queue already\",\n PAUSED: \"The queue has been paused already\",\n RESUMED: \"The queue has been playing already\",\n NO_PREVIOUS: \"There is no previous song in this queue\",\n NO_UP_NEXT: \"There is no up next song\",\n NO_SONG_POSITION: \"Does not have any song at this position\",\n NO_PLAYING: \"There is no playing song in the queue\",\n\n NO_RESULT: \"No result found\",\n NO_RELATED: \"Cannot find any related songs\",\n CANNOT_PLAY_RELATED: \"Cannot play the related song\",\n UNAVAILABLE_VIDEO: \"This video is unavailable\",\n UNPLAYABLE_FORMATS: \"No playable format found\",\n NON_NSFW: \"Cannot play age-restricted content in non-NSFW channel\",\n NOT_SUPPORTED_URL: \"This url is not supported\",\n CANNOT_RESOLVE_SONG: (t: any) => `Cannot resolve ${inspect(t)} to a Song`,\n NO_VALID_SONG: \"'songs' array does not have any valid Song, SearchResult or url\",\n EMPTY_FILTERED_PLAYLIST:\n \"There is no valid video in the playlist\\n\" +\n \"Maybe age-restricted contents is filtered because you are in non-NSFW channel\",\n EMPTY_PLAYLIST: \"There is no valid video in the playlist\",\n};\n\ntype ErrorMessage = typeof ERROR_MESSAGES;\ntype ErrorCode = keyof ErrorMessage;\ntype StaticErrorCode = { [K in ErrorCode]-?: ErrorMessage[K] extends string ? K : never }[ErrorCode];\ntype TemplateErrorCode = Exclude<keyof typeof ERROR_MESSAGES, StaticErrorCode>;\n\nconst haveCode = (code: string): code is ErrorCode => Object.keys(ERROR_MESSAGES).includes(code);\nconst parseMessage = (m: string | ((...x: any) => string), ...args: any) => (typeof m === \"string\" ? m : m(...args));\nconst getErrorMessage = (code: string, ...args: any): string =>\n haveCode(code) ? parseMessage(ERROR_MESSAGES[code], ...args) : args[0];\nexport class DisTubeError<T extends string> extends Error {\n errorCode: string;\n constructor(code: StaticErrorCode);\n constructor(code: T extends TemplateErrorCode ? T : never, ...args: Parameters<ErrorMessage[typeof code]>);\n constructor(code: TemplateErrorCode, _: never);\n constructor(code: T extends ErrorCode ? \"This is built-in error code\" : T, message: string);\n constructor(code: string, ...args: any) {\n super(getErrorMessage(code, ...args));\n\n this.errorCode = code;\n if (Error.captureStackTrace) Error.captureStackTrace(this, DisTubeError);\n }\n\n override get name() {\n return `DisTubeError [${this.errorCode}]`;\n }\n\n get code() {\n return this.errorCode;\n }\n}\n","class Task {\n resolve!: () => void;\n promise: Promise<void>;\n resolveInfo: boolean;\n constructor(resolveInfo: boolean) {\n this.resolveInfo = resolveInfo;\n this.promise = new Promise<void>(res => {\n this.resolve = res;\n });\n }\n}\n\n/**\n * Task queuing system\n * @private\n */\nexport class TaskQueue {\n /**\n * The task array\n * @type {Task[]}\n * @private\n */\n #tasks: Task[] = [];\n\n /**\n * Waits for last task finished and queues a new task\n * @param {boolean} [resolveInfo=false] Whether the task is a resolving info task\n * @returns {Promise<void>}\n */\n public queuing(resolveInfo = false): Promise<void> {\n const next = this.remaining ? this.#tasks[this.#tasks.length - 1].promise : Promise.resolve();\n this.#tasks.push(new Task(resolveInfo));\n return next;\n }\n\n /**\n * Removes the finished task and processes the next task\n */\n public resolve(): void {\n this.#tasks.shift()?.resolve();\n }\n\n /**\n * The remaining number of tasks\n * @type {number}\n */\n public get remaining(): number {\n return this.#tasks.length;\n }\n\n /**\n * Whether or not having a resolving info task\n * @type {boolean}\n */\n public get hasResolveTask(): boolean {\n return this.#tasks.some(t => t.resolveInfo);\n }\n}\n","import { DisTubeError, formatDuration, isMemberInstance, isRecord } from \"..\";\nimport type { PlaylistInfo, Song } from \"..\";\nimport type { GuildMember } from \"discord.js\";\n\n/**\n * Class representing a playlist.\n * @prop {string} source Playlist source\n * @template T - The type for the metadata (if any) of the playlist\n */\nexport class Playlist<T = unknown> implements PlaylistInfo {\n source!: string;\n songs!: Song[];\n name!: string;\n #metadata!: T;\n #member?: GuildMember;\n url?: string;\n thumbnail?: string;\n [x: string]: any;\n /**\n * Create a playlist\n * @param {Song[]|PlaylistInfo} playlist Playlist\n * @param {Object} [options] Optional options\n * @param {Discord.GuildMember} [options.member] Requested user\n * @param {Object} [options.properties] Custom properties\n * @param {T} [options.metadata] Playlist metadata\n */\n constructor(\n playlist: Song[] | PlaylistInfo,\n options: {\n member?: GuildMember;\n properties?: Record<string, any>;\n metadata?: T;\n } = {},\n ) {\n const { member, properties, metadata } = options;\n\n if (\n typeof playlist !== \"object\" ||\n (!Array.isArray(playlist) && [\"source\", \"songs\"].some(key => !(key in playlist)))\n ) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Array<Song>\", \"PlaylistInfo\"], playlist, \"playlist\");\n }\n if (typeof properties !== \"undefined\" && !isRecord<any>(properties)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", properties, \"properties\");\n }\n\n if (Array.isArray(playlist)) {\n /**\n * The source of the playlist\n * @type {string}\n */\n this.source = \"youtube\";\n if (!playlist.length) throw new DisTubeError(\"EMPTY_PLAYLIST\");\n /**\n * Playlist songs.\n * @type {Array<Song>}\n */\n this.songs = playlist;\n /**\n * Playlist name.\n * @type {string}\n */\n this.name = this.songs[0].name\n ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.`\n : `${this.songs.length} songs playlist`;\n this.thumbnail = this.songs[0].thumbnail;\n this.member = member;\n } else {\n this.source = playlist.source.toLowerCase();\n if (!Array.isArray(playlist.songs) || !playlist.songs.length) throw new DisTubeError(\"EMPTY_PLAYLIST\");\n this.songs = playlist.songs;\n this.name =\n playlist.name ||\n // eslint-disable-next-line deprecation/deprecation\n playlist.title ||\n (this.songs[0].name\n ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.`\n : `${this.songs.length} songs playlist`);\n /**\n * Playlist URL.\n * @type {string}\n */\n // eslint-disable-next-line deprecation/deprecation\n this.url = playlist.url || playlist.webpage_url;\n /**\n * Playlist thumbnail.\n * @type {string?}\n */\n this.thumbnail = playlist.thumbnail || this.songs[0].thumbnail;\n this.member = member || playlist.member;\n }\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.playlist = this));\n if (properties) for (const [key, value] of Object.entries(properties)) this[key] = value;\n /**\n * Optional metadata that can be used to identify the playlist.\n * @type {T}\n */\n this.metadata = metadata as T;\n }\n\n /**\n * Playlist duration in second.\n * @type {number}\n */\n get duration() {\n return this.songs.reduce((prev, next) => prev + next.duration, 0);\n }\n\n /**\n * Formatted duration string `hh:mm:ss`.\n * @type {string}\n */\n get formattedDuration() {\n return formatDuration(this.duration);\n }\n\n /**\n * User requested.\n * @type {Discord.GuildMember?}\n */\n get member() {\n return this.#member;\n }\n\n set member(member: GuildMember | undefined) {\n if (!isMemberInstance(member)) return;\n this.#member = member;\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.member = this.member));\n }\n\n /**\n * User requested.\n * @type {Discord.User?}\n */\n get user() {\n return this.member?.user;\n }\n\n get metadata() {\n return this.#metadata;\n }\n\n set metadata(metadata: T) {\n this.#metadata = metadata;\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.metadata = metadata));\n }\n}\n","import { DisTubeError, SearchResultType, formatDuration, toSecond } from \"..\";\nimport type { Playlist, Video } from \"@distube/ytsr\";\n\n/**\n * A abstract class representing a search result.\n * @abstract\n * @private\n */\nabstract class ISearchResult {\n source: \"youtube\";\n abstract type: SearchResultType;\n id: string;\n name: string;\n url: string;\n uploader: {\n name?: string;\n url?: string;\n };\n\n /**\n * Create a search result\n * @param {Object} info ytsr result\n */\n constructor(info: Video | Playlist) {\n /**\n * The source of the search result\n * @type {\"youtube\"}\n */\n this.source = \"youtube\";\n /**\n * YouTube video or playlist id\n * @type {string}\n */\n this.id = info.id;\n /**\n * Video or playlist title.\n * @type {string}\n */\n this.name = info.name;\n /**\n * Video or playlist URL.\n * @type {string}\n */\n this.url = info.url;\n /**\n * Video or playlist uploader\n * @type {Object}\n * @prop {string?} name Uploader name\n * @prop {string?} url Uploader url\n */\n this.uploader = {\n name: undefined,\n url: undefined,\n };\n }\n}\n\n/**\n * A class representing a video search result.\n * @extends ISearchResult\n */\nexport class SearchResultVideo extends ISearchResult {\n type: SearchResultType.VIDEO;\n views: number;\n isLive: boolean;\n duration: number;\n formattedDuration: string;\n thumbnail: string;\n constructor(info: Video) {\n super(info);\n if (info.type !== \"video\") throw new DisTubeError(\"INVALID_TYPE\", \"video\", info.type, \"type\");\n /**\n * Type of SearchResult\n * @type {SearchResultType.VIDEO}\n */\n this.type = SearchResultType.VIDEO;\n /**\n * Video views count\n * @type {number}\n */\n this.views = info.views;\n /**\n * Indicates if the video is an active live.\n * @type {boolean}\n */\n this.isLive = info.isLive;\n /**\n * Video duration.\n * @type {number}\n */\n this.duration = this.isLive ? 0 : toSecond(info.duration);\n /**\n * Formatted duration string `hh:mm:ss` or `mm:ss`.\n * @type {string}\n */\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n /**\n * Video thumbnail.\n * @type {string}\n */\n this.thumbnail = info.thumbnail;\n this.uploader = {\n name: info.author?.name,\n url: info.author?.url,\n };\n }\n}\n\n/**\n * A video or playlist search result\n * @typedef {SearchResultVideo|SearchResultPlaylist} SearchResult\n */\nexport type SearchResult = SearchResultVideo | SearchResultPlaylist;\n\n/**\n * A class representing a playlist search result.\n * @extends ISearchResult\n */\nexport class SearchResultPlaylist extends ISearchResult {\n type: SearchResultType.PLAYLIST;\n length: number;\n constructor(info: Playlist) {\n super(info);\n if (info.type !== \"playlist\") throw new DisTubeError(\"INVALID_TYPE\", \"playlist\", info.type, \"type\");\n /**\n * Type of SearchResult\n * @type {SearchResultType.PLAYLIST}\n */\n this.type = SearchResultType.PLAYLIST;\n /**\n * Length of the playlist\n * @type {number}\n */\n this.length = info.length;\n this.uploader = {\n name: info.owner?.name,\n url: info.owner?.url,\n };\n }\n}\n","import { Playlist } from \"./Playlist\";\nimport { DisTubeError, formatDuration, isMemberInstance, parseNumber, toSecond } from \"..\";\nimport type ytpl from \"@distube/ytpl\";\nimport type ytdl from \"@distube/ytdl-core\";\nimport type { GuildMember } from \"discord.js\";\nimport type { Chapter, OtherSongInfo, RelatedSong, SearchResult } from \"..\";\n\n/**\n * Class representing a song.\n *\n * <info>If {@link Song} is added from a YouTube {@link SearchResult} or {@link Playlist},\n * some info will be missing to save your resources. It will be filled when emitting {@link DisTube#playSong} event.\n *\n * Missing info: {@link Song#likes}, {@link Song#dislikes}, {@link Song#streamURL},\n * {@link Song#related}, {@link Song#chapters}, {@link Song#age_restricted}</info>\n * @template T - The type for the metadata (if any) of the song\n */\nexport class Song<T = unknown> {\n source!: string;\n #metadata!: T;\n formats?: ytdl.videoFormat[];\n #member?: GuildMember;\n id?: string;\n name?: string;\n isLive!: boolean;\n duration!: number;\n formattedDuration?: string;\n url!: string;\n streamURL?: string;\n thumbnail?: string;\n related!: RelatedSong[];\n views!: number;\n likes!: number;\n dislikes!: number;\n uploader!: {\n name?: string;\n url?: string;\n };\n age_restricted!: boolean;\n chapters!: Chapter[];\n reposts!: number;\n #playlist?: Playlist;\n /**\n * Create a Song\n * @param {ytdl.videoInfo|SearchResult|OtherSongInfo} info Raw info\n * @param {Object} [options] Optional options\n * @param {Discord.GuildMember} [options.member] Requested user\n * @param {string} [options.source=\"youtube\"] Song source\n * @param {T} [options.metadata] Song metadata\n */\n constructor(\n info:\n | ytdl.videoInfo\n | SearchResult\n | OtherSongInfo\n | ytdl.relatedVideo\n | RelatedSong\n | ytpl.result[\"items\"][number],\n options: {\n member?: GuildMember;\n source?: string;\n metadata?: T;\n } = {},\n ) {\n const { member, source, metadata } = { source: \"youtube\", ...options };\n\n if (\n typeof source !== \"string\" ||\n ((info as OtherSongInfo).src && typeof (info as OtherSongInfo).src !== \"string\")\n ) {\n throw new DisTubeError(\"INVALID_TYPE\", \"string\", source, \"source\");\n }\n /**\n * The source of the song\n * @type {string}\n */\n this.source = ((info as OtherSongInfo)?.src || source).toLowerCase();\n /**\n * Optional metadata that can be used to identify the song. This is attached by the {@link DisTube#play} method.\n * @type {T}\n */\n this.metadata = metadata as T;\n this.member = member;\n if (this.source === \"youtube\") {\n this._patchYouTube(info as ytdl.videoInfo);\n } else {\n this._patchOther(info as OtherSongInfo);\n }\n }\n\n _patchYouTube(i: ytdl.videoInfo | SearchResult) {\n // FIXME\n const info = i as any;\n if (info.full === true) {\n /**\n * Stream formats (Available if the song is from YouTube and playing)\n * @type {ytdl.videoFormat[]?}\n * @private\n */\n this.formats = info.formats;\n // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports\n const err = require(\"@distube/ytdl-core/lib/utils\").playError(info.player_response, [\n \"UNPLAYABLE\",\n \"LIVE_STREAM_OFFLINE\",\n \"LOGIN_REQUIRED\",\n ]);\n if (err) throw err;\n\n if (!info.formats?.length) throw new DisTubeError(\"UNAVAILABLE_VIDEO\");\n }\n const details = info.videoDetails || info;\n /**\n * YouTube video id\n * @type {string?}\n */\n this.id = details.videoId || details.id;\n /**\n * Song name.\n * @type {string?}\n */\n this.name = details.title || details.name;\n /**\n * Indicates if the video is an active live.\n * @type {boolean}\n */\n this.isLive = Boolean(details.isLive);\n /**\n * Song duration.\n * @type {number}\n */\n this.duration = this.isLive ? 0 : toSecond(details.lengthSeconds || details.length_seconds || details.duration);\n /**\n * Formatted duration string (`hh:mm:ss`, `mm:ss` or `Live`).\n * @type {string?}\n */\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n /**\n * Song URL.\n * @type {string}\n */\n this.url = `https://www.youtube.com/watch?v=${this.id}`;\n /**\n * Stream / Download URL (Available if the song is playing)\n * @type {string?}\n */\n this.streamURL = undefined;\n /**\n * Song thumbnail.\n * @type {string?}\n */\n this.thumbnail =\n details.thumbnails?.sort((a: any, b: any) => b.width - a.width)?.[0]?.url ||\n details.thumbnail?.url ||\n details.thumbnail;\n /**\n * Related songs (without {@link Song#related} properties)\n * @type {Song[]}\n */\n this.related = info?.related_videos || details.related || [];\n if (!Array.isArray(this.related)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", this.related, \"Song#related\");\n this.related = this.related.map((v: any) => new Song(v, { source: this.source, metadata: this.metadata }));\n /**\n * Song views count\n * @type {number}\n */\n this.views = parseNumber(details.viewCount || details.view_count || details.views);\n /**\n * Song like count\n * @type {number}\n */\n this.likes = parseNumber(details.likes);\n /**\n * Song dislike count\n * @type {number}\n */\n this.dislikes = parseNumber(details.dislikes);\n /**\n * Song uploader\n * @type {Object}\n * @prop {string?} name Uploader name\n * @prop {string?} url Uploader url\n */\n this.uploader = {\n name: info.uploader?.name || details.author?.name,\n url: info.uploader?.url || details.author?.channel_url || details.author?.url,\n };\n /**\n * Whether or not an age-restricted content\n * @type {boolean}\n */\n this.age_restricted = Boolean(details.age_restricted);\n /**\n * @typedef {Object} Chapter\n * @prop {string} title Chapter title\n * @prop {number} start_time Chapter start time in seconds\n */\n /**\n * Chapters information (YouTube only)\n * @type {Chapter[]}\n */\n this.chapters = details.chapters || [];\n /**\n * Song repost count\n * @type {number}\n */\n this.reposts = 0;\n }\n\n /**\n * Patch data from other source\n * @param {OtherSongInfo} info Video info\n * @private\n */\n _patchOther(info: OtherSongInfo) {\n this.id = info.id;\n this.name = info.title || info.name;\n this.isLive = Boolean(info.is_live || info.isLive);\n this.duration = this.isLive ? 0 : toSecond(info._duration_raw || info.duration);\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n this.url = info.webpage_url || info.url;\n this.thumbnail = info.thumbnail;\n this.related = info.related || [];\n if (!Array.isArray(this.related)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", this.related, \"Song#related\");\n this.related = this.related.map(i => new Song(i, { source: this.source, metadata: this.metadata }));\n this.views = parseNumber(info.view_count || info.views);\n this.likes = parseNumber(info.like_count || info.likes);\n this.dislikes = parseNumber(info.dislike_count || info.dislikes);\n this.reposts = parseNumber(info.repost_count || info.reposts);\n if (typeof info.uploader === \"string\") {\n this.uploader = {\n name: info.uploader,\n url: info.uploader_url,\n };\n } else {\n this.uploader = {\n name: info.uploader?.name,\n url: info.uploader?.url,\n };\n }\n this.age_restricted = info.age_restricted || (Boolean(info.age_limit) && parseNumber(info.age_limit) >= 18);\n this.chapters = info.chapters || [];\n }\n\n /**\n * The playlist added this song\n * @type {Playlist?}\n */\n get playlist() {\n return this.#playlist;\n }\n\n set playlist(playlist: Playlist | undefined) {\n if (!(playlist instanceof Playlist)) throw new DisTubeError(\"INVALID_TYPE\", \"Playlist\", playlist, \"Song#playlist\");\n this.#playlist = playlist;\n this.member = playlist.member;\n }\n\n /**\n * User requested.\n * @type {Discord.GuildMember?}\n */\n get member() {\n return this.#member;\n }\n\n set member(member: GuildMember | undefined) {\n if (isMemberInstance(member)) this.#member = member;\n }\n\n /**\n * User requested.\n * @type {Discord.User?}\n */\n get user() {\n return this.member?.user;\n }\n\n get metadata() {\n return this.#metadata;\n }\n\n set metadata(metadata: T) {\n this.#metadata = metadata;\n }\n}\n","import type { Client, GuildTextBasedChannel } from \"discord.js\";\nimport type { DisTube, DisTubeEvents, DisTubeHandler, DisTubeVoiceManager, Options, QueueManager } from \"..\";\n\n/**\n * @private\n * @abstract\n */\nexport abstract class DisTubeBase {\n distube: DisTube;\n constructor(distube: DisTube) {\n /**\n * DisTube\n * @type {DisTube}\n */\n this.distube = distube;\n }\n /**\n * Emit the {@link DisTube} of this base\n * @param {string} eventName Event name\n * @param {...any} args arguments\n * @returns {boolean}\n */\n emit(eventName: keyof DisTubeEvents, ...args: any): boolean {\n return this.distube.emit(eventName, ...args);\n }\n /**\n * Emit error event\n * @param {Error} error error\n * @param {Discord.BaseGuildTextChannel} [channel] Text channel where the error is encountered.\n */\n emitError(error: Error, channel?: GuildTextBasedChannel) {\n this.distube.emitError(error, channel);\n }\n /**\n * The queue manager\n * @type {QueueManager}\n * @readonly\n */\n get queues(): QueueManager {\n return this.distube.queues;\n }\n /**\n * The voice manager\n * @type {DisTubeVoiceManager}\n * @readonly\n */\n get voices(): DisTubeVoiceManager {\n return this.distube.voices;\n }\n /**\n * Discord.js client\n * @type {Discord.Client}\n * @readonly\n */\n get client(): Client {\n return this.distube.client;\n }\n /**\n * DisTube options\n * @type {DisTubeOptions}\n * @readonly\n */\n get options(): Options {\n return this.distube.options;\n }\n /**\n * DisTube handler\n * @type {DisTubeHandler}\n * @readonly\n */\n get handler(): DisTubeHandler {\n return this.distube.handler;\n }\n}\n","import { Constants } from \"discord.js\";\nimport { TypedEmitter } from \"tiny-typed-emitter\";\nimport { DisTubeError, isSupportedVoiceChannel } from \"..\";\nimport {\n AudioPlayerStatus,\n VoiceConnectionDisconnectReason,\n VoiceConnectionStatus,\n createAudioPlayer,\n createAudioResource,\n entersState,\n joinVoiceChannel,\n} from \"@discordjs/voice\";\nimport type { Snowflake, VoiceBasedChannel, VoiceState } from \"discord.js\";\nimport type { DisTubeStream, DisTubeVoiceEvents, DisTubeVoiceManager } from \"..\";\nimport type { AudioPlayer, AudioResource, VoiceConnection } from \"@discordjs/voice\";\n\n/**\n * Create a voice connection to the voice channel\n */\nexport class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {\n readonly id: Snowflake;\n readonly voices: DisTubeVoiceManager;\n readonly audioPlayer: AudioPlayer;\n connection!: VoiceConnection;\n audioResource?: AudioResource;\n emittedError!: boolean;\n isDisconnected = false;\n #channel!: VoiceBasedChannel;\n #volume = 100;\n constructor(voiceManager: DisTubeVoiceManager, channel: VoiceBasedChannel) {\n super();\n /**\n * The voice manager that instantiated this connection\n * @type {DisTubeVoiceManager}\n */\n this.voices = voiceManager;\n this.id = channel.guildId;\n this.channel = channel;\n this.voices.add(this.id, this);\n this.audioPlayer = createAudioPlayer()\n .on(AudioPlayerStatus.Idle, oldState => {\n if (oldState.status !== AudioPlayerStatus.Idle) {\n delete this.audioResource;\n this.emit(\"finish\");\n }\n })\n .on(AudioPlayerStatus.Playing, () => this.#br())\n .on(\"error\", error => {\n if (this.emittedError) return;\n this.emittedError = true;\n this.emit(\"error\", error);\n });\n this.connection\n .on(VoiceConnectionStatus.Disconnected, (_, newState) => {\n if (newState.reason === VoiceConnectionDisconnectReason.Manual) {\n // User disconnect\n this.leave();\n } else if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {\n // Move to other channel\n entersState(this.connection, VoiceConnectionStatus.Connecting, 5e3).catch(() => {\n if (\n ![VoiceConnectionStatus.Ready, VoiceConnectionStatus.Connecting].includes(this.connection.state.status)\n ) {\n this.leave();\n }\n });\n } else if (this.connection.rejoinAttempts < 5) {\n // Try to rejoin\n setTimeout(\n () => {\n this.connection.rejoin();\n },\n (this.connection.rejoinAttempts + 1) * 5e3,\n ).unref();\n } else if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) {\n // Leave after 5 attempts\n this.leave(new DisTubeError(\"VOICE_RECONNECT_FAILED\"));\n }\n })\n .on(VoiceConnectionStatus.Destroyed, () => {\n this.leave();\n })\n .on(\"error\", () => undefined);\n this.connection.subscribe(this.audioPlayer);\n /**\n * Get or set the volume percentage\n * @name DisTubeVoice#volume\n * @type {number}\n */\n }\n #br() {\n if (this.audioResource?.encoder?.encoder) this.audioResource.encoder.setBitrate(this.channel.bitrate);\n }\n /**\n * The voice channel id the bot is in\n * @type {Snowflake?}\n */\n get channelId() {\n return this.connection?.joinConfig?.channelId ?? undefined;\n }\n get channel() {\n if (!this.channelId) return this.#channel;\n if (this.#channel?.id === this.channelId) return this.#channel;\n const channel = this.voices.client.channels.cache.get(this.channelId);\n if (!channel) return this.#channel;\n for (const type of Constants.VoiceBasedChannelTypes) {\n if (channel.type === type) {\n this.#channel = channel;\n return channel;\n }\n }\n return this.#channel;\n }\n set channel(channel: VoiceBasedChannel) {\n if (!isSupportedVoiceChannel(channel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"BaseGuildVoiceChannel\", channel, \"DisTubeVoice#channel\");\n }\n if (channel.guildId !== this.id) throw new DisTubeError(\"VOICE_DIFFERENT_GUILD\");\n if (channel.client.user?.id !== this.voices.client.user?.id) throw new DisTubeError(\"VOICE_DIFFERENT_CLIENT\");\n if (channel.id === this.channelId) return;\n if (!channel.joinable) {\n if (channel.full) throw new DisTubeError(\"VOICE_FULL\");\n else throw new DisTubeError(\"VOICE_MISSING_PERMS\");\n }\n this.connection = this.#join(channel);\n this.#channel = channel;\n this.#br();\n }\n #join(channel: VoiceBasedChannel) {\n return joinVoiceChannel({\n channelId: channel.id,\n guildId: this.id,\n adapterCreator: channel.guild.voiceAdapterCreator,\n group: channel.client.user?.id,\n });\n }\n /**\n * Join a voice channel with this connection\n * @param {Discord.BaseGuildVoiceChannel} [channel] A voice channel\n * @returns {Promise<DisTubeVoice>}\n */\n async join(channel?: VoiceBasedChannel): Promise<DisTubeVoice> {\n const TIMEOUT = 30e3;\n if (channel) this.channel = channel;\n try {\n await entersState(this.connection, VoiceConnectionStatus.Ready, TIMEOUT);\n } catch {\n if (this.connection.state.status === VoiceConnectionStatus.Ready) return this;\n if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) this.connection.destroy();\n this.voices.remove(this.id);\n throw new DisTubeError(\"VOICE_CONNECT_FAILED\", TIMEOUT / 1e3);\n }\n return this;\n }\n /**\n * Leave the voice channel of this connection\n * @param {Error} [error] Optional, an error to emit with 'error' event.\n */\n leave(error?: Error) {\n this.stop(true);\n if (!this.isDisconnected) {\n this.emit(\"disconnect\", error);\n this.isDisconnected = true;\n }\n if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) this.connection.destroy();\n this.voices.remove(this.id);\n }\n /**\n * Stop the playing stream\n * @param {boolean} [force=false] If true, will force the {@link DisTubeVoice#audioPlayer} to enter the Idle state\n * even if the {@link DisTubeVoice#audioResource} has silence padding frames.\n * @private\n */\n stop(force = false) {\n this.audioPlayer.stop(force);\n }\n /**\n * Play a readable stream\n * @private\n * @param {DisTubeStream} stream Readable stream\n */\n play(stream: DisTubeStream) {\n this.emittedError = false;\n stream.stream.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (this.emittedError || error.code === \"ERR_STREAM_PREMATURE_CLOSE\") return;\n this.emittedError = true;\n this.emit(\"error\", error);\n });\n this.audioResource = createAudioResource(stream.stream, {\n inputType: stream.type,\n inlineVolume: true,\n });\n this.volume = this.#volume;\n if (this.audioPlayer.state.status !== AudioPlayerStatus.Paused) this.audioPlayer.play(this.audioResource);\n }\n set volume(volume: number) {\n if (typeof volume !== \"number\" || isNaN(volume)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"number\", volume, \"volume\");\n }\n if (volume < 0) {\n throw new DisTubeError(\"NUMBER_COMPARE\", \"Volume\", \"bigger or equal to\", 0);\n }\n this.#volume = volume;\n this.audioResource?.volume?.setVolume(Math.pow(this.#volume / 100, 0.5 / Math.log10(2)));\n }\n get volume() {\n return this.#volume;\n }\n /**\n * Playback duration of the audio resource in seconds\n * @type {number}\n */\n get playbackDuration() {\n return (this.audioResource?.playbackDuration ?? 0) / 1000;\n }\n pause() {\n this.audioPlayer.pause();\n }\n unpause() {\n const state = this.audioPlayer.state;\n if (state.status !== AudioPlayerStatus.Paused) return;\n if (this.audioResource && state.resource !== this.audioResource) this.audioPlayer.play(this.audioResource);\n else this.audioPlayer.unpause();\n }\n /**\n * Whether the bot is self-deafened\n * @type {boolean}\n */\n get selfDeaf(): boolean {\n return this.connection.joinConfig.selfDeaf;\n }\n /**\n * Whether the bot is self-muted\n * @type {boolean}\n */\n get selfMute(): boolean {\n return this.connection.joinConfig.selfMute;\n }\n /**\n * Self-deafens/undeafens the bot.\n * @param {boolean} selfDeaf Whether or not the bot should be self-deafened\n * @returns {boolean} true if the voice state was successfully updated, otherwise false\n */\n setSelfDeaf(selfDeaf: boolean): boolean {\n if (typeof selfDeaf !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", selfDeaf, \"selfDeaf\");\n }\n return this.connection.rejoin({\n ...this.connection.joinConfig,\n selfDeaf,\n });\n }\n /**\n * Self-mutes/unmutes the bot.\n * @param {boolean} selfMute Whether or not the bot should be self-muted\n * @returns {boolean} true if the voice state was successfully updated, otherwise false\n */\n setSelfMute(selfMute: boolean): boolean {\n if (typeof selfMute !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", selfMute, \"selfMute\");\n }\n return this.connection.rejoin({\n ...this.connection.joinConfig,\n selfMute,\n });\n }\n /**\n * The voice state of this connection\n * @type {Discord.VoiceState?}\n */\n get voiceState(): VoiceState | undefined {\n return this.channel?.guild?.members?.me?.voice;\n }\n}\n","import { FFmpeg } from \"prism-media\";\nimport { DisTubeError, isURL } from \"..\";\nimport { StreamType as DiscordVoiceStreamType } from \"@discordjs/voice\";\nimport type { Song, StreamType } from \"..\";\n\ninterface StreamOptions {\n seek?: number;\n ffmpegArgs?: string[];\n type?: StreamType;\n}\n\nexport const chooseBestVideoFormat = ({ duration, formats, isLive }: Song) =>\n formats &&\n formats\n .filter(f => f.hasAudio && (duration < 10 * 60 || f.hasVideo) && (!isLive || f.isHLS))\n .sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate))[0];\n\n/**\n * Create a stream to play with {@link DisTubeVoice}\n * @private\n */\nexport class DisTubeStream {\n /**\n * Create a stream from ytdl video formats\n * @param {Song} song A YouTube Song\n * @param {StreamOptions} options options\n * @returns {DisTubeStream}\n * @private\n */\n static YouTube(song: Song, options: StreamOptions = {}): DisTubeStream {\n if (song.source !== \"youtube\") throw new DisTubeError(\"INVALID_TYPE\", \"youtube\", song.source, \"Song#source\");\n if (!song.formats?.length) throw new DisTubeError(\"UNAVAILABLE_VIDEO\");\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n }\n const bestFormat = chooseBestVideoFormat(song);\n if (!bestFormat) throw new DisTubeError(\"UNPLAYABLE_FORMATS\");\n return new DisTubeStream(bestFormat.url, options);\n }\n /**\n * Create a stream from a stream url\n * @param {string} url stream url\n * @param {StreamOptions} options options\n * @returns {DisTubeStream}\n * @private\n */\n static DirectLink(url: string, options: StreamOptions = {}): DisTubeStream {\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n }\n if (typeof url !== \"string\" || !isURL(url)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"an URL\", url);\n }\n return new DisTubeStream(url, options);\n }\n type: DiscordVoiceStreamType;\n stream: FFmpeg;\n url: string;\n /**\n * Create a DisTubeStream to play with {@link DisTubeVoice}\n * @param {string} url Stream URL\n * @param {StreamOptions} options Stream options\n * @private\n */\n constructor(url: string, options: StreamOptions) {\n /**\n * Stream URL\n * @type {string}\n */\n this.url = url;\n /**\n * Stream type\n * @type {DiscordVoice.StreamType}\n */\n this.type = !options.type ? DiscordVoiceStreamType.OggOpus : DiscordVoiceStreamType.Raw;\n const args = [\n \"-reconnect\",\n \"1\",\n \"-reconnect_streamed\",\n \"1\",\n \"-reconnect_delay_max\",\n \"5\",\n \"-i\",\n url,\n \"-analyzeduration\",\n \"0\",\n \"-loglevel\",\n \"0\",\n \"-ar\",\n \"48000\",\n \"-ac\",\n \"2\",\n \"-f\",\n ];\n\n if (!options.type) args.push(\"opus\", \"-acodec\", \"libopus\");\n else args.push(\"s16le\");\n if (typeof options.seek === \"number\" && options.seek > 0) args.unshift(\"-ss\", options.seek.toString());\n if (Array.isArray(options.ffmpegArgs) && options.ffmpegArgs.length) args.push(...options.ffmpegArgs);\n\n /**\n * FFmpeg stream\n * @type {FFmpeg}\n */\n this.stream = new FFmpeg({ args, shell: false });\n (<any>this.stream)._readableState && ((<any>this.stream)._readableState.highWaterMark = 1 << 25);\n }\n}\n","import ytpl from \"@distube/ytpl\";\nimport ytdl from \"@distube/ytdl-core\";\nimport { DisTubeBase } from \".\";\nimport { Cookie } from \"tough-cookie\";\nimport {\n DisTubeError,\n Playlist,\n Queue,\n SearchResultPlaylist,\n SearchResultVideo,\n Song,\n chooseBestVideoFormat,\n isMessageInstance,\n isNsfwChannel,\n isObject,\n isTruthy,\n isURL,\n isVoiceChannelEmpty,\n} from \"..\";\nimport type { Message, VoiceBasedChannel } from \"discord.js\";\nimport type {\n DisTube,\n OtherSongInfo,\n PlayHandlerOptions,\n ResolveOptions,\n ResolvePlaylistOptions,\n SearchResult,\n} from \"..\";\n\n/**\n * DisTube's Handler\n * @extends DisTubeBase\n * @private\n */\nexport class DisTubeHandler extends DisTubeBase {\n #cookie: ytdl.Cookie[] | string = \"\";\n constructor(distube: DisTube) {\n super(distube);\n\n const client = this.client;\n if (this.options.leaveOnEmpty) {\n client.on(\"voiceStateUpdate\", oldState => {\n if (!oldState?.channel) return;\n const queue = this.queues.get(oldState);\n if (!queue) {\n if (isVoiceChannelEmpty(oldState)) {\n setTimeout(() => {\n if (!this.queues.get(oldState) && isVoiceChannelEmpty(oldState)) this.voices.leave(oldState);\n }, this.options.emptyCooldown * 1e3).unref();\n }\n return;\n }\n if (queue._emptyTimeout) {\n clearTimeout(queue._emptyTimeout);\n delete queue._emptyTimeout;\n }\n if (isVoiceChannelEmpty(oldState)) {\n queue._emptyTimeout = setTimeout(() => {\n delete queue._emptyTimeout;\n if (isVoiceChannelEmpty(oldState)) {\n queue.voice.leave();\n this.emit(\"empty\", queue);\n if (queue.stopped) queue.remove();\n }\n }, this.options.emptyCooldown * 1e3).unref();\n }\n });\n }\n }\n\n get ytdlOptions(): ytdl.getInfoOptions {\n const options = this.options.ytdlOptions;\n if (this.options.youtubeCookie && this.options.youtubeCookie !== this.#cookie) {\n const cookies = (this.#cookie = this.options.youtubeCookie);\n if (typeof cookies === \"string\") {\n // eslint-disable-next-line no-console\n console.warn(\n \"\\x1b[33mWARNING:\\x1B[0m You are using the old YouTube cookie format, \" +\n \"please use the new one instead. (https://distube.js.org/#/docs/DisTube/main/general/cookie)\",\n );\n options.agent = ytdl.createAgent(\n cookies\n .split(\";\")\n .map(c => Cookie.parse(c))\n .filter(isTruthy),\n );\n } else {\n options.agent = ytdl.createAgent(cookies);\n }\n }\n return options;\n }\n\n get ytCookie(): string {\n const agent = this.ytdlOptions.agent;\n if (!agent) return \"\";\n const { jar } = agent;\n return jar.getCookieStringSync(\"https://www.youtube.com\");\n }\n\n /**\n * @param {string} url url\n * @param {boolean} [basic=false] getBasicInfo?\n * @returns {Promise<ytdl.videoInfo>}\n */\n getYouTubeInfo(url: string, basic = false): Promise<ytdl.videoInfo> {\n if (basic) return ytdl.getBasicInfo(url, this.ytdlOptions);\n return ytdl.getInfo(url, this.ytdlOptions);\n }\n\n resolve<T = unknown>(song: Song<T>, options?: Omit<ResolveOptions, \"metadata\">): Promise<Song<T>>;\n resolve<T = unknown>(song: Playlist<T>, options?: Omit<ResolveOptions, \"metadata\">): Promise<Playlist<T>>;\n resolve<T = unknown>(song: string | SearchResult, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;\n resolve<T = unknown>(\n song: ytdl.videoInfo | OtherSongInfo | ytdl.relatedVideo,\n options?: ResolveOptions<T>,\n ): Promise<Song<T>>;\n resolve<T = unknown>(song: Playlist, options: ResolveOptions<T>): Promise<Playlist<T>>;\n resolve(\n song: string | ytdl.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl.relatedVideo,\n options?: ResolveOptions,\n ): Promise<Song | Playlist>;\n /**\n * Resolve a url or a supported object to a {@link Song} or {@link Playlist}\n * @param {string|Song|SearchResult|Playlist} song URL | {@link Song}| {@link SearchResult} | {@link Playlist}\n * @param {ResolveOptions} [options] Optional options\n * @returns {Promise<Song|Playlist|null>} Resolved\n * @throws {DisTubeError}\n */\n async resolve(\n song: string | ytdl.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl.relatedVideo,\n options: ResolveOptions = {},\n ): Promise<Song | Playlist> {\n if (song instanceof Song || song instanceof Playlist) {\n if (\"metadata\" in options) song.metadata = options.metadata;\n if (\"member\" in options) song.member = options.member;\n return song;\n }\n if (song instanceof SearchResultVideo) return new Song(song, options);\n if (song instanceof SearchResultPlaylist) return this.resolvePlaylist(song.url, options);\n if (isObject(song)) {\n if (!(\"url\" in song) && !(\"id\" in song)) throw new DisTubeError(\"CANNOT_RESOLVE_SONG\", song);\n return new Song(song, options);\n }\n if (ytpl.validateID(song)) return this.resolvePlaylist(song, options);\n if (ytdl.validateURL(song)) return new Song(await this.getYouTubeInfo(song, true), options);\n if (isURL(song)) {\n for (const plugin of this.distube.extractorPlugins) {\n if (await plugin.validate(song)) return plugin.resolve(song, options);\n }\n throw new DisTubeError(\"NOT_SUPPORTED_URL\");\n }\n throw new DisTubeError(\"CANNOT_RESOLVE_SONG\", song);\n }\n\n resolvePlaylist<T = unknown>(\n playlist: Playlist<T> | Song<T>[] | string,\n options?: Omit<ResolvePlaylistOptions, \"metadata\">,\n ): Promise<Playlist<T>>;\n resolvePlaylist<T = undefined>(\n playlist: Playlist | Song[] | string,\n options: ResolvePlaylistOptions<T>,\n ): Promise<Playlist<T>>;\n resolvePlaylist(playlist: Playlist | Song[] | string, options?: ResolvePlaylistOptions): Promise<Playlist>;\n /**\n * Resolve Song[] or YouTube playlist url to a Playlist\n * @param {Playlist|Song[]|string} playlist Resolvable playlist\n * @param {ResolvePlaylistOptions} options Optional options\n * @returns {Promise<Playlist>}\n */\n async resolvePlaylist(playlist: Playlist | Song[] | string, options: ResolvePlaylistOptions = {}): Promise<Playlist> {\n const { member, source, metadata } = { source: \"youtube\", ...options };\n if (playlist instanceof Playlist) {\n if (\"metadata\" in options) playlist.metadata = metadata;\n if (\"member\" in options) playlist.member = member;\n return playlist;\n }\n if (typeof playlist === \"string\") {\n const info = await ytpl(playlist, { limit: Infinity, requestOptions: { headers: { cookie: this.ytCookie } } });\n const songs = info.items\n .filter(v => !v.thumbnail.includes(\"no_thumbnail\"))\n .map(v => new Song(v, { member, metadata }));\n return new Playlist(\n {\n source,\n songs,\n member,\n name: info.title,\n url: info.url,\n thumbnail: songs[0].thumbnail,\n },\n { metadata },\n );\n }\n return new Playlist(playlist, { member, properties: { source }, metadata });\n }\n\n /**\n * Search for a song, fire {@link DisTube#event:error} if not found.\n * @param {Discord.Message} message The original message from an user\n * @param {string} query The query string\n * @returns {Promise<SearchResult?>} Song info\n * @throws {DisTubeError}\n */\n async searchSong(message: Message<true>, query: string): Promise<SearchResult | null> {\n if (!isMessageInstance(message)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Message\", message, \"message\");\n if (typeof query !== \"string\") throw new DisTubeError(\"INVALID_TYPE\", \"string\", query, \"query\");\n if (query.length === 0) throw new DisTubeError(\"EMPTY_STRING\", \"query\");\n const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;\n const results = await this.distube\n .search(query, {\n limit,\n safeSearch: this.options.nsfw ? false : !isNsfwChannel(message.channel),\n })\n .catch(() => {\n if (!this.emit(\"searchNoResult\", message, query)) {\n // eslint-disable-next-line no-console\n console.warn(\"searchNoResult event does not have any listeners! Emits `error` event instead.\");\n throw new DisTubeError(\"NO_RESULT\");\n }\n });\n if (!results) return null;\n return this.createSearchMessageCollector(message, results, query);\n }\n\n /**\n * Create a message collector for selecting search results.\n *\n * Needed events: {@link DisTube#event:searchResult}, {@link DisTube#event:searchCancel},\n * {@link DisTube#event:searchInvalidAnswer}, {@link DisTube#event:searchDone}.\n * @param {Discord.Message} message The original message from an user\n * @param {Array<SearchResult|Song|Playlist>} results The search results\n * @param {string?} [query] The query string\n * @returns {Promise<SearchResult|Song|Playlist|null>} Selected result\n * @throws {DisTubeError}\n */\n async createSearchMessageCollector<R extends SearchResult | Song | Playlist>(\n message: Message<true>,\n results: Array<R>,\n query?: string,\n ): Promise<R | null> {\n if (!isMessageInstance(message)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Message\", message, \"message\");\n if (!Array.isArray(results) || results.length === 0) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Array<SearchResult|Song|Playlist>\", results, \"results\");\n }\n if (this.options.searchSongs > 1) {\n const searchEvents = [\n \"searchNoResult\",\n \"searchResult\",\n \"searchCancel\",\n \"searchInvalidAnswer\",\n \"searchDone\",\n ] as const;\n for (const evn of searchEvents) {\n if (this.distube.listenerCount(evn) === 0) {\n /* eslint-disable no-console */\n console.warn(`\"searchSongs\" option is disabled due to missing \"${evn}\" listener.`);\n console.warn(\n `If you don't want to use \"${evn}\" event, simply add an empty listener (not recommended):\\n` +\n `<DisTube>.on(\"${evn}\", () => {})`,\n );\n /* eslint-enable no-console */\n this.options.searchSongs = 0;\n }\n }\n }\n const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;\n let result = results[0];\n if (limit > 1) {\n results.splice(limit);\n this.emit(\"searchResult\", message, results, query);\n const answers = await message.channel\n .awaitMessages({\n filter: (m: Message) => m.author.id === message.author.id,\n max: 1,\n time: this.options.searchCooldown * 1e3,\n errors: [\"time\"],\n })\n .catch(() => undefined);\n const ans = answers?.first();\n if (!ans) {\n this.emit(\"searchCancel\", message, query);\n return null;\n }\n const index = parseInt(ans.content, 10);\n if (isNaN(index) || index > results.length || index < 1) {\n this.emit(\"searchInvalidAnswer\", message, ans, query);\n return null;\n }\n this.emit(\"searchDone\", message, ans, query);\n result = results[index - 1];\n }\n return result;\n }\n\n /**\n * Play or add a {@link Playlist} to the queue.\n * @param {Discord.BaseGuildVoiceChannel} voiceChannel A voice channel\n * @param {Playlist|string} playlist A YouTube playlist url | a Playlist\n * @param {PlayHandlerOptions} [options] Optional options\n * @returns {Promise<void>}\n * @throws {DisTubeError}\n */\n async playPlaylist(\n voiceChannel: VoiceBasedChannel,\n playlist: Playlist,\n options: PlayHandlerOptions = {},\n ): Promise<void> {\n const { textChannel, skip } = { skip: false, ...options };\n const position = Number(options.position) || (skip ? 1 : 0);\n if (!(playlist instanceof Playlist)) throw new DisTubeError(\"INVALID_TYPE\", \"Playlist\", playlist, \"playlist\");\n\n const queue = this.queues.get(voiceChannel);\n\n const isNsfw = isNsfwChannel(queue?.textChannel || textChannel);\n if (!this.options.nsfw && !isNsfw) playlist.songs = playlist.songs.filter(s => !s.age_restricted);\n\n if (!playlist.songs.length) {\n if (!this.options.nsfw && !isNsfw) throw new DisTubeError(\"EMPTY_FILTERED_PLAYLIST\");\n throw new DisTubeError(\"EMPTY_PLAYLIST\");\n }\n if (queue) {\n if (this.options.joinNewVoiceChannel) queue.voice.channel = voiceChannel;\n queue.addToQueue(playlist.songs, position);\n if (skip) queue.skip();\n else this.emit(\"addList\", queue, playlist);\n } else {\n const newQueue = await this.queues.create(voiceChannel, playlist.songs, textChannel);\n if (newQueue instanceof Queue) {\n if (this.options.emitAddListWhenCreatingQueue) this.emit(\"addList\", newQueue, playlist);\n this.emit(\"playSong\", newQueue, newQueue.songs[0]);\n }\n }\n }\n\n /**\n * Play or add a {@link Song} to the queue.\n * @param {Discord.BaseGuildVoiceChannel} voiceChannel A voice channel\n * @param {Song} song A YouTube playlist url | a Playlist\n * @param {PlayHandlerOptions} [options] Optional options\n * @returns {Promise<void>}\n * @throws {DisTubeError}\n */\n async playSong(voiceChannel: VoiceBasedChannel, song: Song, options: PlayHandlerOptions = {}): Promise<void> {\n if (!(song instanceof Song)) throw new DisTubeError(\"INVALID_TYPE\", \"Song\", song, \"song\");\n const { textChannel, skip } = { skip: false, ...options };\n const position = Number(options.position) || (skip ? 1 : 0);\n\n const queue = this.queues.get(voiceChannel);\n if (!this.options.nsfw && song.age_restricted && !isNsfwChannel(queue?.textChannel || textChannel)) {\n throw new DisTubeError(\"NON_NSFW\");\n }\n if (queue) {\n if (this.options.joinNewVoiceChannel) queue.voice.channel = voiceChannel;\n queue.addToQueue(song, position);\n if (skip) queue.skip();\n else this.emit(\"addSong\", queue, song);\n } else {\n const newQueue = await this.queues.create(voiceChannel, song, textChannel);\n if (newQueue instanceof Queue) {\n if (this.options.emitAddSongWhenCreatingQueue) this.emit(\"addSong\", newQueue, song);\n this.emit(\"playSong\", newQueue, song);\n }\n }\n }\n\n /**\n * Get {@link Song}'s stream info and attach it to the song.\n * @param {Song} song A Song\n */\n async attachStreamInfo(song: Song) {\n const { url, source, formats, streamURL } = song;\n if (source === \"youtube\") {\n if (!formats || !chooseBestVideoFormat(song)) {\n song._patchYouTube(await this.handler.getYouTubeInfo(url));\n }\n } else if (!streamURL) {\n for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {\n if (await plugin.validate(url)) {\n const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)] as const;\n const result = await Promise.all(info);\n song.streamURL = result[0];\n song.related = result[1];\n break;\n }\n }\n }\n }\n}\n","import { DisTubeError, StreamType, checkInvalidKey, defaultOptions } from \"..\";\nimport type ytdl from \"@distube/ytdl-core\";\nimport type { CustomPlugin, DisTubeOptions, ExtractorPlugin, Filters } from \"..\";\nimport type { Cookie } from \"@distube/ytdl-core\";\n\nexport class Options {\n plugins: (CustomPlugin | ExtractorPlugin)[];\n emitNewSongOnly: boolean;\n leaveOnFinish: boolean;\n leaveOnStop: boolean;\n leaveOnEmpty: boolean;\n emptyCooldown: number;\n savePreviousSongs: boolean;\n searchSongs: number;\n searchCooldown: number;\n youtubeCookie?: Cookie[] | string;\n customFilters?: Filters;\n ytdlOptions: ytdl.getInfoOptions;\n nsfw: boolean;\n emitAddSongWhenCreatingQueue: boolean;\n emitAddListWhenCreatingQueue: boolean;\n joinNewVoiceChannel: boolean;\n streamType: StreamType;\n directLink: boolean;\n constructor(options: DisTubeOptions) {\n if (typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"DisTubeOptions\");\n }\n const opts = { ...defaultOptions, ...options };\n this.plugins = opts.plugins;\n this.emitNewSongOnly = opts.emitNewSongOnly;\n this.leaveOnEmpty = opts.leaveOnEmpty;\n this.leaveOnFinish = opts.leaveOnFinish;\n this.leaveOnStop = opts.leaveOnStop;\n this.savePreviousSongs = opts.savePreviousSongs;\n this.searchSongs = opts.searchSongs;\n this.youtubeCookie = opts.youtubeCookie;\n this.customFilters = opts.customFilters;\n this.ytdlOptions = opts.ytdlOptions;\n this.searchCooldown = opts.searchCooldown;\n this.emptyCooldown = opts.emptyCooldown;\n this.nsfw = opts.nsfw;\n this.emitAddSongWhenCreatingQueue = opts.emitAddSongWhenCreatingQueue;\n this.emitAddListWhenCreatingQueue = opts.emitAddListWhenCreatingQueue;\n this.joinNewVoiceChannel = opts.joinNewVoiceChannel;\n this.streamType = opts.streamType;\n this.directLink = opts.directLink;\n checkInvalidKey(opts, this, \"DisTubeOptions\");\n this.#validateOptions();\n }\n\n #validateOptions(options = this) {\n const booleanOptions = new Set([\n \"emitNewSongOnly\",\n \"leaveOnEmpty\",\n \"leaveOnFinish\",\n \"leaveOnStop\",\n \"savePreviousSongs\",\n \"joinNewVoiceChannel\",\n \"nsfw\",\n \"emitAddSongWhenCreatingQueue\",\n \"emitAddListWhenCreatingQueue\",\n \"directLink\",\n ]);\n const numberOptions = new Set([\"searchCooldown\", \"emptyCooldown\", \"searchSongs\"]);\n const stringOptions = new Set();\n const objectOptions = new Set([\"customFilters\", \"ytdlOptions\"]);\n const optionalOptions = new Set([\"youtubeCookie\", \"customFilters\"]);\n\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined && optionalOptions.has(key)) continue;\n if (key === \"youtubeCookie\" && !Array.isArray(value) && typeof value !== \"string\") {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Array<Cookie>\", \"string\"], value, `DisTubeOptions.${key}`);\n } else if (key === \"streamType\" && (typeof value !== \"number\" || isNaN(value) || !StreamType[value])) {\n throw new DisTubeError(\"INVALID_TYPE\", \"StreamType\", value, `DisTubeOptions.${key}`);\n } else if (key === \"plugins\" && !Array.isArray(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Array<Plugin>\", value, `DisTubeOptions.${key}`);\n } else if (booleanOptions.has(key)) {\n if (typeof value !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", value, `DisTubeOptions.${key}`);\n }\n } else if (numberOptions.has(key)) {\n if (typeof value !== \"number\" || isNaN(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"number\", value, `DisTubeOptions.${key}`);\n }\n } else if (stringOptions.has(key)) {\n if (typeof value !== \"string\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"string\", value, `DisTubeOptions.${key}`);\n }\n } else if (objectOptions.has(key)) {\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", value, `DisTubeOptions.${key}`);\n }\n }\n }\n }\n}\n","import { DisTubeBase } from \"..\";\nimport { Collection } from \"discord.js\";\n\n/**\n * Manages the collection of a data model.\n * @abstract\n * @private\n * @extends DisTubeBase\n */\nexport abstract class BaseManager<V> extends DisTubeBase {\n /**\n * The collection of items for this manager.\n * @type {Collection}\n * @name BaseManager#collection\n */\n collection = new Collection<string, V>();\n /**\n * The size of the collection.\n * @type {number}\n */\n get size() {\n return this.collection.size;\n }\n}\n","import { BaseManager } from \".\";\nimport { resolveGuildId } from \"../..\";\nimport type { GuildIdResolvable } from \"../..\";\n\n/**\n * Manages the collection of a data model paired with a guild id.\n * @abstract\n * @private\n * @extends BaseManager\n */\nexport abstract class GuildIdManager<V> extends BaseManager<V> {\n add(idOrInstance: GuildIdResolvable, data: V) {\n const id = resolveGuildId(idOrInstance);\n const existing = this.get(id);\n if (existing) return this;\n return this.collection.set(id, data);\n }\n get(idOrInstance: GuildIdResolvable): V | undefined {\n return this.collection.get(resolveGuildId(idOrInstance));\n }\n remove(idOrInstance: GuildIdResolvable): boolean {\n return this.collection.delete(resolveGuildId(idOrInstance));\n }\n has(idOrInstance: GuildIdResolvable): boolean {\n return this.collection.has(resolveGuildId(idOrInstance));\n }\n}\n","import { DisTubeVoice } from \"../DisTubeVoice\";\nimport { resolveGuildId } from \"../..\";\nimport { GuildIdManager } from \".\";\nimport { VoiceConnectionStatus, getVoiceConnection } from \"@discordjs/voice\";\nimport type { GuildIdResolvable } from \"../..\";\nimport type { VoiceBasedChannel } from \"discord.js\";\n\n/**\n * Manages voice connections for {@link DisTube}\n * @extends BaseManager\n */\nexport class DisTubeVoiceManager extends GuildIdManager<DisTubeVoice> {\n /**\n * Get a {@link DisTubeVoice}.\n * @method get\n * @memberof DisTubeVoiceManager#\n * @param {GuildIdResolvable} guild The queue resolvable to resolve\n * @returns {DisTubeVoice?}\n */\n /**\n * Collection of {@link DisTubeVoice}.\n * @name DisTubeVoiceManager#collection\n * @type {Discord.Collection<string, DisTubeVoice>}\n */\n /**\n * Create a {@link DisTubeVoice}\n * @param {Discord.BaseGuildVoiceChannel} channel A voice channel to join\n * @returns {DisTubeVoice}\n * @private\n */\n create(channel: VoiceBasedChannel): DisTubeVoice {\n const existing = this.get(channel.guildId);\n if (existing) {\n existing.channel = channel;\n return existing;\n }\n return new DisTubeVoice(this, channel);\n }\n /**\n * Join a voice channel\n * @param {Discord.BaseGuildVoiceChannel} channel A voice channel to join\n * @returns {Promise<DisTubeVoice>}\n */\n join(channel: VoiceBasedChannel): Promise<DisTubeVoice> {\n const existing = this.get(channel.guildId);\n if (existing) return existing.join(channel);\n return this.create(channel).join();\n }\n /**\n * Leave the connected voice channel in a guild\n * @param {GuildIdResolvable} guild Queue Resolvable\n */\n leave(guild: GuildIdResolvable) {\n const voice = this.get(guild);\n if (voice) {\n voice.leave();\n } else {\n const connection =\n getVoiceConnection(resolveGuildId(guild), this.client.user?.id) ?? getVoiceConnection(resolveGuildId(guild));\n if (connection && connection.state.status !== VoiceConnectionStatus.Destroyed) {\n connection.destroy();\n }\n }\n }\n}\n","import { BaseManager } from \".\";\nimport { DisTubeError } from \"../..\";\nimport type { Filter, FilterResolvable, Queue } from \"../..\";\n\n/**\n * Manage filters of a playing {@link Queue}\n * @extends {BaseManager}\n */\nexport class FilterManager extends BaseManager<Filter> {\n /**\n * Collection of {@link Filter}.\n * @name FilterManager#collection\n * @type {Discord.Collection<string, DisTubeVoice>}\n */\n queue: Queue;\n constructor(queue: Queue) {\n super(queue.distube);\n this.queue = queue;\n }\n\n #resolve(filter: FilterResolvable): Filter {\n if (typeof filter === \"object\" && typeof filter.name === \"string\" && typeof filter.value === \"string\") {\n return filter;\n }\n if (typeof filter === \"string\" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter)) {\n return {\n name: filter,\n value: this.distube.filters[filter],\n };\n }\n throw new DisTubeError(\"INVALID_TYPE\", \"FilterResolvable\", filter, \"filter\");\n }\n\n #apply() {\n this.queue.beginTime = this.queue.currentTime;\n this.queues.playSong(this.queue);\n }\n\n /**\n * Enable a filter or multiple filters to the manager\n * @param {FilterResolvable|FilterResolvable[]} filterOrFilters The filter or filters to enable\n * @param {boolean} [override=false] Wether or not override the applied filter with new filter value\n * @returns {FilterManager}\n */\n add(filterOrFilters: FilterResolvable | FilterResolvable[], override = false) {\n if (Array.isArray(filterOrFilters)) {\n for (const filter of filterOrFilters) {\n const ft = this.#resolve(filter);\n if (override || !this.has(ft)) this.collection.set(ft.name, ft);\n }\n } else {\n const ft = this.#resolve(filterOrFilters);\n if (override || !this.has(ft)) this.collection.set(ft.name, ft);\n }\n this.#apply();\n return this;\n }\n\n /**\n * Clear enabled filters of the manager\n * @returns {FilterManager}\n */\n clear() {\n return this.set([]);\n }\n\n /**\n * Set the filters applied to the manager\n * @param {FilterResolvable[]} filters The filters to apply\n * @returns {FilterManager}\n */\n set(filters: FilterResolvable[]) {\n if (!Array.isArray(filters)) throw new DisTubeError(\"INVALID_TYPE\", \"Array<FilterResolvable>\", filters, \"filters\");\n this.collection.clear();\n for (const f of filters) {\n const filter = this.#resolve(f);\n this.collection.set(filter.name, filter);\n }\n this.#apply();\n return this;\n }\n\n #removeFn(f: FilterResolvable) {\n return this.collection.delete(this.#resolve(f).name);\n }\n\n /**\n * Disable a filter or multiple filters\n * @param {FilterResolvable|FilterResolvable[]} filterOrFilters The filter or filters to disable\n * @returns {FilterManager}\n */\n remove(filterOrFilters: FilterResolvable | FilterResolvable[]) {\n if (Array.isArray(filterOrFilters)) filterOrFilters.forEach(f => this.#removeFn(f));\n else this.#removeFn(filterOrFilters);\n this.#apply();\n return this;\n }\n\n /**\n * Check whether a filter enabled or not\n * @param {FilterResolvable} filter The filter to check\n * @returns {boolean}\n */\n has(filter: FilterResolvable) {\n return this.collection.has(typeof filter === \"string\" ? filter : this.#resolve(filter).name);\n }\n\n /**\n * Array of enabled filter names\n * @type {Array<string>}\n * @readonly\n */\n get names(): string[] {\n return [...this.collection.keys()];\n }\n\n /**\n * Array of enabled filters\n * @type {Array<Filter>}\n * @readonly\n */\n get values(): Filter[] {\n return [...this.collection.values()];\n }\n\n get ffmpegArgs(): string[] {\n return this.size ? [\"-af\", this.values.map(f => f.value).join(\",\")] : [];\n }\n\n override toString() {\n return this.names.toString();\n }\n}\n","import { GuildIdManager } from \".\";\nimport { DisTubeError, DisTubeStream, Queue, RepeatMode, objectKeys } from \"../..\";\nimport type { Song } from \"../..\";\nimport type { GuildTextBasedChannel, VoiceBasedChannel } from \"discord.js\";\n\n/**\n * Queue manager\n * @extends GuildIdManager\n */\nexport class QueueManager extends GuildIdManager<Queue> {\n /**\n * Collection of {@link Queue}.\n * @name QueueManager#collection\n * @type {Discord.Collection<string, Queue>}\n */\n\n /**\n * Create a {@link Queue}\n * @private\n * @param {Discord.BaseGuildVoiceChannel} channel A voice channel\n * @param {Song|Song[]} song First song\n * @param {Discord.BaseGuildTextChannel} textChannel Default text channel\n * @returns {Promise<Queue|true>} Returns `true` if encounter an error\n */\n async create(\n channel: VoiceBasedChannel,\n song: Song[] | Song,\n textChannel?: GuildTextBasedChannel,\n ): Promise<Queue | true> {\n if (this.has(channel.guildId)) throw new DisTubeError(\"QUEUE_EXIST\");\n const voice = this.voices.create(channel);\n const queue = new Queue(this.distube, voice, song, textChannel);\n await queue._taskQueue.queuing();\n try {\n await voice.join();\n this.#voiceEventHandler(queue);\n this.add(queue.id, queue);\n this.emit(\"initQueue\", queue);\n const err = await this.playSong(queue);\n return err || queue;\n } finally {\n queue._taskQueue.resolve();\n }\n }\n\n /**\n * Get a Queue from this QueueManager.\n * @method get\n * @memberof QueueManager#\n * @param {GuildIdResolvable} guild Resolvable thing from a guild\n * @returns {Queue?}\n */\n\n /**\n * Listen to DisTubeVoice events and handle the Queue\n * @private\n * @param {Queue} queue Queue\n */\n #voiceEventHandler(queue: Queue) {\n queue._listeners = {\n disconnect: error => {\n queue.remove();\n this.emit(\"disconnect\", queue);\n if (error) this.emitError(error, queue.textChannel);\n },\n error: error => this.#handlePlayingError(queue, error),\n finish: () => this.#handleSongFinish(queue),\n };\n for (const event of objectKeys(queue._listeners)) {\n queue.voice.on(event, queue._listeners[event]);\n }\n }\n\n /**\n * Whether or not emit playSong event\n * @param {Queue} queue Queue\n * @private\n * @returns {boolean}\n */\n #emitPlaySong(queue: Queue): boolean {\n return (\n !this.options.emitNewSongOnly ||\n (queue.repeatMode === RepeatMode.SONG && queue._next) ||\n (queue.repeatMode !== RepeatMode.SONG && queue.songs[0]?.id !== queue.songs[1]?.id)\n );\n }\n\n /**\n * Handle the queue when a Song finish\n * @private\n * @param {Queue} queue queue\n * @returns {Promise<void>}\n */\n async #handleSongFinish(queue: Queue): Promise<void> {\n this.emit(\"finishSong\", queue, queue.songs[0]);\n await queue._taskQueue.queuing();\n try {\n if (queue.stopped) return;\n if (queue.repeatMode === RepeatMode.QUEUE && !queue._prev) queue.songs.push(queue.songs[0]);\n if (queue._prev) {\n if (queue.repeatMode === RepeatMode.QUEUE) queue.songs.unshift(queue.songs.pop() as Song);\n else queue.songs.unshift(queue.previousSongs.pop() as Song);\n }\n if (queue.songs.length <= 1 && (queue._next || queue.repeatMode === RepeatMode.DISABLED)) {\n if (queue.autoplay) {\n try {\n await queue.addRelatedSong();\n } catch {\n this.emit(\"noRelated\", queue);\n }\n }\n if (queue.songs.length <= 1) {\n if (this.options.leaveOnFinish) queue.voice.leave();\n if (!queue.autoplay) this.emit(\"finish\", queue);\n queue.remove();\n return;\n }\n }\n const emitPlaySong = this.#emitPlaySong(queue);\n if (!queue._prev && (queue.repeatMode !== RepeatMode.SONG || queue._next)) {\n const prev = queue.songs.shift() as Song;\n delete prev.formats;\n delete prev.streamURL;\n if (this.options.savePreviousSongs) queue.previousSongs.push(prev);\n else queue.previousSongs.push({ id: prev.id } as Song);\n }\n queue._next = queue._prev = false;\n queue.beginTime = 0;\n const err = await this.playSong(queue);\n if (!err && emitPlaySong) this.emit(\"playSong\", queue, queue.songs[0]);\n } finally {\n queue._taskQueue.resolve();\n }\n }\n\n /**\n * Handle error while playing\n * @private\n * @param {Queue} queue queue\n * @param {Error} error error\n */\n #handlePlayingError(queue: Queue, error: Error) {\n const song = queue.songs.shift() as Song;\n try {\n error.name = \"PlayingError\";\n error.message = `${error.message}\\nId: ${song.id}\\nName: ${song.name}`;\n } catch {\n // Emit original error\n }\n this.emitError(error, queue.textChannel);\n if (queue.songs.length > 0) {\n queue._next = queue._prev = false;\n queue.beginTime = 0;\n this.playSong(queue).then(e => {\n if (!e) this.emit(\"playSong\", queue, queue.songs[0]);\n });\n } else {\n queue.stop();\n }\n }\n\n /**\n * Create a ytdl stream\n * @param {Queue} queue Queue\n * @returns {DisTubeStream}\n */\n createStream(queue: Queue): DisTubeStream {\n const song = queue.songs[0];\n const { duration, source, streamURL } = song;\n const streamOptions = {\n ffmpegArgs: queue.filters.ffmpegArgs,\n seek: duration ? queue.beginTime : undefined,\n type: this.options.streamType,\n };\n if (source === \"youtube\") return DisTubeStream.YouTube(song, streamOptions);\n return DisTubeStream.DirectLink(streamURL as string, streamOptions);\n }\n\n /**\n * Play a song on voice connection\n * @private\n * @param {Queue} queue The guild queue\n * @returns {Promise<boolean>} error?\n */\n async playSong(queue: Queue): Promise<boolean> {\n if (!queue) return true;\n if (queue.stopped || !queue.songs.length) {\n queue.stop();\n return true;\n }\n try {\n const song = queue.songs[0];\n await this.handler.attachStreamInfo(song);\n if (queue.stopped || !queue.songs.length) {\n queue.stop();\n return true;\n }\n const stream = this.createStream(queue);\n queue.voice.play(stream);\n song.streamURL = stream.url;\n return false;\n } catch (e: any) {\n this.#handlePlayingError(queue, e);\n return true;\n }\n }\n}\n","import { DisTubeBase, FilterManager } from \"../core\";\nimport { DisTubeError, RepeatMode, Song, TaskQueue, formatDuration, objectKeys } from \"..\";\nimport type { GuildTextBasedChannel, Snowflake } from \"discord.js\";\nimport type { DisTube, DisTubeVoice, DisTubeVoiceEvents } from \"..\";\n\n/**\n * Represents a queue.\n * @extends DisTubeBase\n */\nexport class Queue extends DisTubeBase {\n readonly id: Snowflake;\n voice: DisTubeVoice;\n songs: Song[];\n previousSongs: Song[];\n stopped: boolean;\n _next: boolean;\n _prev: boolean;\n playing: boolean;\n paused: boolean;\n repeatMode: RepeatMode;\n autoplay: boolean;\n #filters: FilterManager;\n beginTime: number;\n textChannel?: GuildTextBasedChannel;\n _emptyTimeout?: NodeJS.Timeout;\n _taskQueue: TaskQueue;\n _listeners?: DisTubeVoiceEvents;\n /**\n * Create a queue for the guild\n * @param {DisTube} distube DisTube\n * @param {DisTubeVoice} voice Voice connection\n * @param {Song|Song[]} song First song(s)\n * @param {Discord.BaseGuildTextChannel?} textChannel Default text channel\n */\n constructor(distube: DisTube, voice: DisTubeVoice, song: Song | Song[], textChannel?: GuildTextBasedChannel) {\n super(distube);\n /**\n * Voice connection of this queue.\n * @type {DisTubeVoice}\n */\n this.voice = voice;\n /**\n * Queue id (Guild id)\n * @type {Discord.Snowflake}\n */\n this.id = voice.id;\n /**\n * Get or set the stream volume. Default value: `50`.\n * @type {number}\n */\n this.volume = 50;\n /**\n * List of songs in the queue (The first one is the playing song)\n * @type {Array<Song>}\n */\n this.songs = Array.isArray(song) ? [...song] : [song];\n /**\n * List of the previous songs.\n * @type {Array<Song>}\n */\n this.previousSongs = [];\n /**\n * Whether stream is currently stopped.\n * @type {boolean}\n * @private\n */\n this.stopped = false;\n /**\n * Whether or not the last song was skipped to next song.\n * @type {boolean}\n * @private\n */\n this._next = false;\n /**\n * Whether or not the last song was skipped to previous song.\n * @type {boolean}\n * @private\n */\n this._prev = false;\n /**\n * Whether or not the stream is currently playing.\n * @type {boolean}\n */\n this.playing = true;\n /**\n * Whether or not the stream is currently paused.\n * @type {boolean}\n */\n this.paused = false;\n /**\n * Type of repeat mode (`0` is disabled, `1` is repeating a song, `2` is repeating all the queue).\n * Default value: `0` (disabled)\n * @type {RepeatMode}\n */\n this.repeatMode = RepeatMode.DISABLED;\n /**\n * Whether or not the autoplay mode is enabled.\n * Default value: `false`\n * @type {boolean}\n */\n this.autoplay = false;\n this.#filters = new FilterManager(this);\n /**\n * What time in the song to begin (in seconds).\n * @type {number}\n */\n this.beginTime = 0;\n /**\n * The text channel of the Queue. (Default: where the first command is called).\n * @type {Discord.TextChannel?}\n */\n this.textChannel = textChannel;\n /**\n * Timeout for checking empty channel\n * @type {*}\n * @private\n */\n this._emptyTimeout = undefined;\n /**\n * Task queuing system\n * @type {TaskQueue}\n * @private\n */\n this._taskQueue = new TaskQueue();\n /**\n * DisTubeVoice listener\n * @type {Object}\n * @private\n */\n this._listeners = undefined;\n }\n /**\n * The client user as a `GuildMember` of this queue's guild\n * @type {Discord.GuildMember?}\n */\n get clientMember() {\n return this.voice.channel.guild.members.me ?? undefined;\n }\n /**\n * The filter manager of the queue\n * @type {FilterManager}\n * @readonly\n */\n get filters() {\n return this.#filters;\n }\n /**\n * Formatted duration string.\n * @type {string}\n * @readonly\n */\n get formattedDuration() {\n return formatDuration(this.duration);\n }\n /**\n * Queue's duration.\n * @type {number}\n * @readonly\n */\n get duration() {\n return this.songs.length ? this.songs.reduce((prev, next) => prev + next.duration, 0) : 0;\n }\n /**\n * What time in the song is playing (in seconds).\n * @type {number}\n * @readonly\n */\n get currentTime() {\n return this.voice.playbackDuration + this.beginTime;\n }\n /**\n * Formatted {@link Queue#currentTime} string.\n * @type {string}\n * @readonly\n */\n get formattedCurrentTime() {\n return formatDuration(this.currentTime);\n }\n /**\n * The voice channel playing in.\n * @type {Discord.VoiceChannel|Discord.StageChannel|null}\n * @readonly\n */\n get voiceChannel() {\n return this.clientMember?.voice?.channel ?? null;\n }\n get volume() {\n return this.voice.volume;\n }\n set volume(value: number) {\n this.voice.volume = value;\n }\n /**\n * @private\n * Add a Song or an array of Song to the queue\n * @param {Song|Song[]} song Song to add\n * @param {number} [position=0] Position to add, <= 0 to add to the end of the queue\n * @throws {Error}\n * @returns {Queue} The guild queue\n */\n addToQueue(song: Song | Song[], position = 0): Queue {\n if (!song || (Array.isArray(song) && !song.length)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Song\", \"Array<Song>\"], song, \"song\");\n }\n if (typeof position !== \"number\" || !Number.isInteger(position)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"integer\", position, \"position\");\n }\n if (position <= 0) {\n if (Array.isArray(song)) this.songs.push(...song);\n else this.songs.push(song);\n } else if (Array.isArray(song)) {\n this.songs.splice(position, 0, ...song);\n } else {\n this.songs.splice(position, 0, song);\n }\n if (Array.isArray(song)) song.forEach(s => delete s.formats);\n else delete song.formats;\n return this;\n }\n /**\n * Pause the guild stream\n * @returns {Queue} The guild queue\n */\n pause(): Queue {\n if (this.paused) throw new DisTubeError(\"PAUSED\");\n this.playing = false;\n this.paused = true;\n this.voice.pause();\n return this;\n }\n /**\n * Resume the guild stream\n * @returns {Queue} The guild queue\n */\n resume(): Queue {\n if (this.playing) throw new DisTubeError(\"RESUMED\");\n this.playing = true;\n this.paused = false;\n this.voice.unpause();\n return this;\n }\n /**\n * Set the guild stream's volume\n * @param {number} percent The percentage of volume you want to set\n * @returns {Queue} The guild queue\n */\n setVolume(percent: number): Queue {\n this.volume = percent;\n return this;\n }\n\n /**\n * Skip the playing song if there is a next song in the queue.\n * <info>If {@link Queue#autoplay} is `true` and there is no up next song,\n * DisTube will add and play a related song.</info>\n * @returns {Promise<Song>} The song will skip to\n * @throws {Error}\n */\n async skip(): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (this.songs.length <= 1) {\n if (this.autoplay) await this.addRelatedSong();\n else throw new DisTubeError(\"NO_UP_NEXT\");\n }\n const song = this.songs[1];\n this._next = true;\n this.voice.stop();\n return song;\n } finally {\n this._taskQueue.resolve();\n }\n }\n\n /**\n * Play the previous song if exists\n * @returns {Promise<Song>} The guild queue\n * @throws {Error}\n */\n async previous(): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (!this.options.savePreviousSongs) throw new DisTubeError(\"DISABLED_OPTION\", \"savePreviousSongs\");\n if (this.previousSongs?.length === 0 && this.repeatMode !== RepeatMode.QUEUE) {\n throw new DisTubeError(\"NO_PREVIOUS\");\n }\n const song =\n this.repeatMode === 2 ? this.songs[this.songs.length - 1] : this.previousSongs[this.previousSongs.length - 1];\n this._prev = true;\n this.voice.stop();\n return song;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Shuffle the queue's songs\n * @returns {Promise<Queue>} The guild queue\n */\n async shuffle(): Promise<Queue> {\n await this._taskQueue.queuing();\n try {\n const playing = this.songs.shift();\n if (playing === undefined) return this;\n for (let i = this.songs.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [this.songs[i], this.songs[j]] = [this.songs[j], this.songs[i]];\n }\n this.songs.unshift(playing);\n return this;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Jump to the song position in the queue.\n * The next one is 1, 2,...\n * The previous one is -1, -2,...\n * @param {number} position The song position to play\n * @returns {Promise<Song>} The new Song will be played\n * @throws {Error} if `num` is invalid number\n */\n async jump(position: number): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (typeof position !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", position, \"position\");\n if (!position || position > this.songs.length || -position > this.previousSongs.length) {\n throw new DisTubeError(\"NO_SONG_POSITION\");\n }\n let nextSong: Song;\n if (position > 0) {\n const nextSongs = this.songs.splice(position - 1);\n if (this.options.savePreviousSongs) {\n this.previousSongs.push(...this.songs);\n } else {\n this.previousSongs.push(...this.songs.map(s => ({ id: s.id }) as Song));\n }\n this.songs = nextSongs;\n this._next = true;\n nextSong = nextSongs[1];\n } else if (!this.options.savePreviousSongs) {\n throw new DisTubeError(\"DISABLED_OPTION\", \"savePreviousSongs\");\n } else {\n this._prev = true;\n if (position !== -1) this.songs.unshift(...this.previousSongs.splice(position + 1));\n nextSong = this.previousSongs[this.previousSongs.length - 1];\n }\n this.voice.stop();\n return nextSong;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Set the repeat mode of the guild queue.\\\n * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`\n * @param {RepeatMode?} [mode] The repeat modes (toggle if `undefined`)\n * @returns {RepeatMode} The new repeat mode\n */\n setRepeatMode(mode?: RepeatMode): RepeatMode {\n if (mode !== undefined && !Object.values(RepeatMode).includes(mode)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"RepeatMode\", \"undefined\"], mode, \"mode\");\n }\n if (mode === undefined) this.repeatMode = (this.repeatMode + 1) % 3;\n else if (this.repeatMode === mode) this.repeatMode = RepeatMode.DISABLED;\n else this.repeatMode = mode;\n return this.repeatMode;\n }\n /**\n * Set the playing time to another position\n * @param {number} time Time in seconds\n * @returns {Queue} The guild queue\n */\n seek(time: number): Queue {\n if (typeof time !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", time, \"time\");\n if (isNaN(time) || time < 0) throw new DisTubeError(\"NUMBER_COMPARE\", \"time\", \"bigger or equal to\", 0);\n this.beginTime = time;\n this.queues.playSong(this);\n return this;\n }\n /**\n * Add a related song of the playing song to the queue\n * @returns {Promise<Song>} The added song\n * @throws {Error}\n */\n async addRelatedSong(): Promise<Song> {\n if (!this.songs?.[0]) throw new DisTubeError(\"NO_PLAYING\");\n const related = this.songs[0].related.find(v => !this.previousSongs.map(s => s.id).includes(v.id));\n if (!related || !(related instanceof Song)) throw new DisTubeError(\"NO_RELATED\");\n const song = await this.handler.resolve(related, { member: this.clientMember, metadata: related.metadata });\n if (!(song instanceof Song)) throw new DisTubeError(\"CANNOT_PLAY_RELATED\");\n this.addToQueue(song);\n return song;\n }\n /**\n * Stop the guild stream and delete the queue\n */\n async stop() {\n await this._taskQueue.queuing();\n try {\n this.playing = false;\n this.paused = false;\n this.stopped = true;\n if (this.options.leaveOnStop) this.voice.leave();\n else this.voice.stop();\n this.remove();\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Remove the queue from the manager\n * (This does not leave the voice channel even if {@link DisTubeOptions|DisTubeOptions.leaveOnStop} is enabled)\n * @private\n */\n remove() {\n this.stopped = true;\n this.songs = [];\n this.previousSongs = [];\n if (this._listeners) {\n for (const event of objectKeys(this._listeners)) {\n this.voice.removeListener(event, this._listeners[event]);\n }\n }\n this.queues.remove(this.id);\n this.emit(\"deleteQueue\", this);\n }\n /**\n * Toggle autoplay mode\n * @returns {boolean} Autoplay mode state\n */\n toggleAutoplay(): boolean {\n this.autoplay = !this.autoplay;\n return this.autoplay;\n }\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { Client, GuildTextBasedChannel } from \"discord.js\";\nimport type {\n Awaitable,\n DisTube,\n DisTubeEvents,\n DisTubeHandler,\n DisTubeVoiceManager,\n Options,\n PluginType,\n QueueManager,\n RelatedSong,\n} from \"..\";\n\n/**\n * DisTube Plugin\n * @abstract\n * @private\n */\nexport abstract class Plugin {\n abstract type: PluginType;\n distube!: DisTube;\n init(distube: DisTube) {\n /**\n * DisTube\n * @type {DisTube}\n */\n this.distube = distube;\n }\n /**\n * Type of the plugin\n * @name Plugin#type\n * @type {PluginType}\n */\n /**\n * Emit an event to the {@link DisTube} class\n * @param {string} eventName Event name\n * @param {...any} args arguments\n * @returns {boolean}\n */\n emit(eventName: keyof DisTubeEvents, ...args: any): boolean {\n return this.distube.emit(eventName, ...args);\n }\n /**\n * Emit error event to the {@link DisTube} class\n * @param {Error} error error\n * @param {Discord.BaseGuildTextChannel} [channel] Text channel where the error is encountered.\n */\n emitError(error: Error, channel?: GuildTextBasedChannel) {\n this.distube.emitError(error, channel);\n }\n /**\n * The queue manager\n * @type {QueueManager}\n * @readonly\n */\n get queues(): QueueManager {\n return this.distube.queues;\n }\n /**\n * The voice manager\n * @type {DisTubeVoiceManager}\n * @readonly\n */\n get voices(): DisTubeVoiceManager {\n return this.distube.voices;\n }\n /**\n * Discord.js client\n * @type {Discord.Client}\n * @readonly\n */\n get client(): Client {\n return this.distube.client;\n }\n /**\n * DisTube options\n * @type {DisTubeOptions}\n * @readonly\n */\n get options(): Options {\n return this.distube.options;\n }\n /**\n * DisTube handler\n * @type {DisTubeHandler}\n * @readonly\n */\n get handler(): DisTubeHandler {\n return this.distube.handler;\n }\n /**\n * Check if the string is working with this plugin\n * @param {string} _string Input string\n * @returns {boolean|Promise<boolean>}\n */\n validate(_string: string): Awaitable<boolean> {\n return false;\n }\n /**\n * Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.\n * Not needed if the plugin plays song from YouTube.\n * @param {string} url Input url\n * @returns {string|Promise<string>}\n */\n getStreamURL(url: string): Awaitable<string> {\n return url;\n }\n /**\n * Get related songs from a supported url. {@link Song#member} should be `undefined`.\n * Not needed to add {@link Song#related} because it will be added with this function later.\n * @param {string} _url Input url\n * @returns {Song[]|Promise<Song[]>}\n */\n getRelatedSongs(_url: string): Awaitable<RelatedSong[]> {\n return [];\n }\n}\n","import { Plugin } from \".\";\nimport { PluginType } from \"..\";\nimport type { VoiceBasedChannel } from \"discord.js\";\nimport type { Awaitable, PlayOptions } from \"..\";\n\n/**\n * Custom Plugin\n * @extends Plugin\n * @abstract\n */\nexport abstract class CustomPlugin extends Plugin {\n readonly type = PluginType.CUSTOM;\n abstract play(voiceChannel: VoiceBasedChannel, song: string, options: PlayOptions): Awaitable<void>;\n}\n\n/**\n * This method will be executed if the url is validated.\n * @param {Discord.BaseGuildVoiceChannel} voiceChannel The voice channel will be joined\n * @param {string} song Validated `song`\n * @param {PlayOptions} [options] Optional options\n * @returns {Promise<void>}\n * @abstract\n * @method play\n * @memberof CustomPlugin#\n */\n\n/**\n * Check if the string is working with this plugin\n * @param {string} string String need to validate\n * @returns {boolean|Promise<boolean>}\n * @method validate\n * @memberof CustomPlugin#\n */\n","import { Plugin } from \".\";\nimport { PluginType } from \"..\";\nimport type { GuildMember } from \"discord.js\";\nimport type { Awaitable, Playlist, Song } from \"..\";\n\n/**\n * Extractor Plugin\n * @extends Plugin\n * @abstract\n */\nexport abstract class ExtractorPlugin extends Plugin {\n readonly type = PluginType.EXTRACTOR;\n abstract resolve<T = unknown>(\n url: string,\n options: { member?: GuildMember; metadata?: T },\n ): Awaitable<Song<T> | Playlist<T>>;\n}\n\n/**\n * Resolve the validated url to a {@link Song} or a {@link Playlist}.\n *\n * @param {string} url URL\n * @param {Object} [options] Optional options\n * @param {Discord.GuildMember} [options.member] Requested user\n * @param {*} [options.metadata] Metadata\n * @returns {Song|Playlist|Promise<Song|Playlist>}\n * @method resolve\n * @memberof ExtractorPlugin#\n * @abstract\n */\n\n/**\n * Check if the url is working with this plugin\n * @param {string} url Input url\n * @returns {boolean|Promise<boolean>}\n * @method validate\n * @memberof ExtractorPlugin#\n */\n","import { URL } from \"url\";\nimport { DisTubeError, DisTubeVoice, Queue } from \".\";\nimport { Constants, GatewayIntentBits, IntentsBitField, SnowflakeUtil } from \"discord.js\";\nimport type { GuildIdResolvable } from \".\";\nimport type {\n Client,\n ClientOptions,\n Guild,\n GuildMember,\n GuildTextBasedChannel,\n Message,\n Snowflake,\n VoiceBasedChannel,\n VoiceState,\n} from \"discord.js\";\n\nconst formatInt = (int: number) => (int < 10 ? `0${int}` : int);\n\n/**\n * Format duration to string\n * @param {number} sec Duration in seconds\n * @returns {string}\n */\nexport function formatDuration(sec: number): string {\n if (!sec || !Number(sec)) return \"00:00\";\n const seconds = Math.floor(sec % 60);\n const minutes = Math.floor((sec % 3600) / 60);\n const hours = Math.floor(sec / 3600);\n if (hours > 0) return `${formatInt(hours)}:${formatInt(minutes)}:${formatInt(seconds)}`;\n if (minutes > 0) return `${formatInt(minutes)}:${formatInt(seconds)}`;\n return `00:${formatInt(seconds)}`;\n}\n/**\n * Convert formatted duration to seconds\n * @param {*} input Formatted duration string\n * @returns {number}\n */\nexport function toSecond(input: any): number {\n if (!input) return 0;\n if (typeof input !== \"string\") return Number(input) || 0;\n if (input.includes(\":\")) {\n const time = input.split(\":\").reverse();\n let seconds = 0;\n for (let i = 0; i < 3; i++) if (time[i]) seconds += Number(time[i].replace(/[^\\d.]+/g, \"\")) * Math.pow(60, i);\n if (time.length > 3) seconds += Number(time[3].replace(/[^\\d.]+/g, \"\")) * 24 * 60 * 60;\n return seconds;\n } else {\n return Number(input.replace(/[^\\d.]+/g, \"\")) || 0;\n }\n}\n/**\n * Parse number from input\n * @param {*} input Any\n * @returns {number}\n */\nexport function parseNumber(input: any): number {\n if (typeof input === \"string\") return Number(input.replace(/[^\\d.]+/g, \"\")) || 0;\n return Number(input) || 0;\n}\nconst SUPPORTED_PROTOCOL = [\"https:\", \"http:\", \"file:\"] as const;\n/**\n * Check if the string is an URL\n * @param {string} input input\n * @returns {boolean}\n */\nexport function isURL(input: any): input is `${(typeof SUPPORTED_PROTOCOL)[number]}//${string}` {\n if (typeof input !== \"string\" || input.includes(\" \")) return false;\n try {\n const url = new URL(input);\n if (!SUPPORTED_PROTOCOL.some(p => p === url.protocol)) return false;\n } catch {\n return false;\n }\n return true;\n}\n/**\n * Check if the Client has enough intents to using DisTube\n * @param {ClientOptions} options options\n */\nexport function checkIntents(options: ClientOptions): void {\n const intents = new IntentsBitField(options.intents);\n if (!intents.has(GatewayIntentBits.GuildVoiceStates)) throw new DisTubeError(\"MISSING_INTENTS\", \"GuildVoiceStates\");\n}\n\n/**\n * Check if the voice channel is empty\n * @param {Discord.VoiceState} voiceState voiceState\n * @returns {boolean}\n */\nexport function isVoiceChannelEmpty(voiceState: VoiceState): boolean {\n const guild = voiceState.guild;\n const clientId = voiceState.client.user?.id;\n if (!guild || !clientId) return false;\n const voiceChannel = guild.members.me?.voice?.channel;\n if (!voiceChannel) return false;\n const members = voiceChannel.members.filter(m => !m.user.bot);\n return !members.size;\n}\n\nexport function isSnowflake(id: any): id is Snowflake {\n try {\n return SnowflakeUtil.deconstruct(id).timestamp > SnowflakeUtil.epoch;\n } catch {\n return false;\n }\n}\n\nexport function isMemberInstance(member: any): member is GuildMember {\n return (\n Boolean(member) &&\n isSnowflake(member.id) &&\n isSnowflake(member.guild?.id) &&\n isSnowflake(member.user?.id) &&\n member.id === member.user.id\n );\n}\n\nexport function isTextChannelInstance(channel: any): channel is GuildTextBasedChannel {\n return (\n Boolean(channel) &&\n isSnowflake(channel.id) &&\n isSnowflake(channel.guildId || channel.guild?.id) &&\n Constants.TextBasedChannelTypes.includes(channel.type) &&\n typeof channel.send === \"function\" &&\n (typeof channel.nsfw === \"boolean\" || typeof channel.parent?.nsfw === \"boolean\")\n );\n}\n\nexport function isMessageInstance(message: any): message is Message<true> {\n // Simple check for using distube normally\n return (\n Boolean(message) &&\n isSnowflake(message.id) &&\n isSnowflake(message.guildId || message.guild?.id) &&\n isMemberInstance(message.member) &&\n isTextChannelInstance(message.channel) &&\n Constants.NonSystemMessageTypes.includes(message.type) &&\n message.member.id === message.author?.id\n );\n}\n\nexport function isSupportedVoiceChannel(channel: any): channel is VoiceBasedChannel {\n return (\n Boolean(channel) &&\n isSnowflake(channel.id) &&\n isSnowflake(channel.guildId || channel.guild?.id) &&\n Constants.VoiceBasedChannelTypes.includes(channel.type)\n );\n}\n\nexport function isGuildInstance(guild: any): guild is Guild {\n return Boolean(guild) && isSnowflake(guild.id) && isSnowflake(guild.ownerId) && typeof guild.name === \"string\";\n}\n\nexport function resolveGuildId(resolvable: GuildIdResolvable): Snowflake {\n let guildId: string | undefined;\n if (typeof resolvable === \"string\") {\n guildId = resolvable;\n } else if (isObject(resolvable)) {\n if (\"guildId\" in resolvable && resolvable.guildId) {\n guildId = resolvable.guildId;\n } else if (resolvable instanceof Queue || resolvable instanceof DisTubeVoice || isGuildInstance(resolvable)) {\n guildId = resolvable.id;\n } else if (\"guild\" in resolvable && isGuildInstance(resolvable.guild)) {\n guildId = resolvable.guild.id;\n }\n }\n if (!isSnowflake(guildId)) throw new DisTubeError(\"INVALID_TYPE\", \"GuildIdResolvable\", resolvable);\n return guildId;\n}\n\nexport function isClientInstance(client: any): client is Client {\n return Boolean(client) && typeof client.login === \"function\";\n}\n\nexport function checkInvalidKey(\n target: Record<string, any>,\n source: Record<string, any> | string[],\n sourceName: string,\n) {\n if (!isObject(target)) throw new DisTubeError(\"INVALID_TYPE\", \"object\", target, sourceName);\n const sourceKeys = Array.isArray(source) ? source : objectKeys(source);\n const invalidKey = objectKeys(target).find(key => !sourceKeys.includes(key));\n if (invalidKey) throw new DisTubeError(\"INVALID_KEY\", sourceName, invalidKey);\n}\n\nexport function isObject(obj: any): obj is object {\n return typeof obj === \"object\" && obj !== null && !Array.isArray(obj);\n}\n\nexport function isRecord<T = unknown>(obj: any): obj is Record<string, T> {\n return isObject(obj);\n}\n\ntype KeyOf<T> = T extends object ? (keyof T)[] : [];\nexport function objectKeys<T>(obj: T): KeyOf<T> {\n if (!isObject(obj)) return [] as KeyOf<T>;\n return Object.keys(obj) as KeyOf<T>;\n}\n\nexport function isNsfwChannel(channel?: GuildTextBasedChannel): boolean {\n if (!isTextChannelInstance(channel)) return false;\n if (channel.isThread()) return channel.parent?.nsfw ?? false;\n return channel.nsfw;\n}\n\ntype Falsy = undefined | null | false | 0 | \"\";\nexport const isTruthy = <T>(x: T | Falsy): x is T => Boolean(x);\n","import { request } from \"undici\";\nimport { ExtractorPlugin, Song } from \"..\";\nimport type { GuildMember } from \"discord.js\";\n\nexport class DirectLinkPlugin extends ExtractorPlugin {\n override async validate(url: string) {\n try {\n const headers = await request(url, { method: \"HEAD\" }).then(res => res.headers);\n const types = headers[\"content-type\"];\n const type = Array.isArray(types) ? types[0] : types;\n if ([\"audio/\", \"video/\", \"application/ogg\"].some(s => type?.startsWith(s))) return true;\n } catch {\n // invalid URL\n }\n return false;\n }\n\n resolve(url: string, options: { member?: GuildMember; metadata?: any } = {}) {\n url = url.replace(/\\/+$/, \"\");\n return new Song(\n {\n name: url.substring(url.lastIndexOf(\"/\") + 1).replace(/((\\?|#).*)?$/, \"\") || url,\n url,\n src: \"direct_link\",\n },\n options,\n );\n }\n}\n","import ytsr from \"@distube/ytsr\";\nimport { TypedEmitter } from \"tiny-typed-emitter\";\nimport {\n DirectLinkPlugin,\n DisTubeError,\n DisTubeHandler,\n DisTubeVoiceManager,\n Options,\n Playlist,\n QueueManager,\n SearchResultPlaylist,\n SearchResultType,\n SearchResultVideo,\n Song,\n checkIntents,\n defaultFilters,\n isClientInstance,\n isMemberInstance,\n isMessageInstance,\n isObject,\n isSupportedVoiceChannel,\n isTextChannelInstance,\n isURL,\n} from \".\";\nimport type { Client, GuildTextBasedChannel, VoiceBasedChannel } from \"discord.js\";\nimport type {\n CustomPlaylistOptions,\n CustomPlugin,\n DisTubeOptions,\n ExtractorPlugin,\n Filters,\n GuildIdResolvable,\n PlayOptions,\n Queue,\n SearchResult,\n TypedDisTubeEvents,\n} from \".\";\n\n// Cannot be `import` as it's not under TS root dir\n// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports\nexport const { version }: { version: string } = require(\"../package.json\");\n\n/**\n * DisTube class\n * @extends EventEmitter\n */\nexport class DisTube extends TypedEmitter<TypedDisTubeEvents> {\n readonly handler: DisTubeHandler;\n readonly options: Options;\n readonly client: Client;\n readonly queues: QueueManager;\n readonly voices: DisTubeVoiceManager;\n readonly extractorPlugins: ExtractorPlugin[];\n readonly customPlugins: CustomPlugin[];\n readonly filters: Filters;\n\n /**\n * @deprecated Use `youtubeCookie: Cookie[]` instead. Guide: {@link https://distube.js.org/#/docs/DisTube/main/general/cookie YouTube Cookies}\n */\n constructor(\n client: Client,\n otp: DisTubeOptions & {\n youtubeCookie: string;\n },\n );\n /**\n * Create a new DisTube class.\n * @param {Discord.Client} client Discord.JS client\n * @param {DisTubeOptions} [otp] Custom DisTube options\n * @throws {DisTubeError}\n * @example\n * const Discord = require('discord.js'),\n * DisTube = require('distube'),\n * client = new Discord.Client();\n * // Create a new DisTube\n * const distube = new DisTube.default(client, { searchSongs: 10 });\n * // client.DisTube = distube // make it access easily\n * client.login(\"Your Discord Bot Token\")\n */\n constructor(client: Client, otp?: DisTubeOptions);\n constructor(client: Client, otp: DisTubeOptions = {}) {\n super();\n this.setMaxListeners(1);\n if (!isClientInstance(client)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Client\", client, \"client\");\n /**\n * Discord.JS client\n * @type {Discord.Client}\n */\n this.client = client;\n checkIntents(client.options);\n /**\n * DisTube options\n * @type {DisTubeOptions}\n */\n this.options = new Options(otp);\n /**\n * Voice connections manager\n * @type {DisTubeVoiceManager}\n */\n this.voices = new DisTubeVoiceManager(this);\n /**\n * DisTube's Handler\n * @type {DisTubeHandler}\n * @private\n */\n this.handler = new DisTubeHandler(this);\n /**\n * Queues manager\n * @type {QueueManager}\n */\n this.queues = new QueueManager(this);\n /**\n * DisTube filters\n * @type {Filters}\n */\n this.filters = { ...defaultFilters, ...this.options.customFilters };\n // Default plugin\n if (this.options.directLink) this.options.plugins.push(new DirectLinkPlugin());\n this.options.plugins.forEach(p => p.init(this));\n /**\n * Extractor Plugins\n * @type {ExtractorPlugin[]}\n * @private\n */\n this.extractorPlugins = this.options.plugins.filter((p): p is ExtractorPlugin => p.type === \"extractor\");\n /**\n * Custom Plugins\n * @type {CustomPlugin[]}\n * @private\n */\n this.customPlugins = this.options.plugins.filter((p): p is CustomPlugin => p.type === \"custom\");\n }\n\n static get version() {\n return version;\n }\n\n /**\n * DisTube version\n * @type {string}\n */\n get version() {\n return version;\n }\n\n /**\n * Play / add a song or playlist from url. Search and play a song if it is not a valid url.\n *\n * @param {Discord.BaseGuildVoiceChannel} voiceChannel The channel will be joined if the bot isn't in any channels,\n * the bot will be moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`\n * @param {string|Song|SearchResult|Playlist} song URL | Search string |\n * {@link Song} | {@link SearchResult} | {@link Playlist}\n * @param {PlayOptions} [options] Optional options\n * @throws {DisTubeError}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"play\")\n * distube.play(message.member.voice.channel, args.join(\" \"), {\n * member: message.member,\n * textChannel: message.channel,\n * message\n * });\n * });\n * @returns {Promise<void>}\n */\n async play(\n voiceChannel: VoiceBasedChannel,\n song: string | Song | SearchResult | Playlist,\n options: PlayOptions = {},\n ): Promise<void> {\n if (!isSupportedVoiceChannel(voiceChannel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"BaseGuildVoiceChannel\", voiceChannel, \"voiceChannel\");\n }\n if (!isObject(options)) throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n\n const { textChannel, member, skip, message, metadata } = {\n member: voiceChannel.guild.members.me ?? undefined,\n textChannel: options?.message?.channel,\n skip: false,\n ...options,\n };\n const position = Number(options.position) || (skip ? 1 : 0);\n\n if (message && !isMessageInstance(message)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Discord.Message\", \"a falsy value\"], message, \"options.message\");\n }\n if (textChannel && !isTextChannelInstance(textChannel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.GuildTextBasedChannel\", textChannel, \"options.textChannel\");\n }\n if (member && !isMemberInstance(member)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.GuildMember\", member, \"options.member\");\n }\n const queue = this.getQueue(voiceChannel);\n const queuing = queue && !queue._taskQueue.hasResolveTask;\n if (queuing) await queue?._taskQueue.queuing(true);\n try {\n if (typeof song === \"string\") {\n for (const plugin of this.customPlugins) {\n if (await plugin.validate(song)) {\n await plugin.play(voiceChannel, song, options);\n return;\n }\n }\n }\n if (typeof song === \"string\" && !isURL(song)) {\n if (!message) {\n song = (await this.search(song, { limit: 1 }))[0];\n } else {\n const result = await this.handler.searchSong(message, song);\n if (!result) return;\n song = result;\n }\n }\n song = await this.handler.resolve(song, { member, metadata });\n if (song instanceof Playlist) {\n await this.handler.playPlaylist(voiceChannel, song, { textChannel, skip, position });\n } else {\n await this.handler.playSong(voiceChannel, song, { textChannel, skip, position });\n }\n } catch (e: any) {\n if (!(e instanceof DisTubeError)) {\n try {\n e.name = \"PlayError\";\n e.message = `${typeof song === \"string\" ? song : song.url}\\n${e.message}`;\n } catch {\n // Throw original error\n }\n }\n throw e;\n } finally {\n if (queuing) queue?._taskQueue.resolve();\n }\n }\n\n /**\n * Create a custom playlist\n * @returns {Promise<Playlist>}\n * @param {Array<string|Song|SearchResult>} songs Array of url, Song or SearchResult\n * @param {CustomPlaylistOptions} [options] Optional options\n * @example\n * const songs = [\"https://www.youtube.com/watch?v=xxx\", \"https://www.youtube.com/watch?v=yyy\"];\n * const playlist = await distube.createCustomPlaylist(songs, {\n * member: message.member,\n * properties: { name: \"My playlist name\", source: \"custom\" },\n * parallel: true\n * });\n * distube.play(voiceChannel, playlist, { ... });\n */\n async createCustomPlaylist(\n songs: (string | Song | SearchResult)[],\n options: CustomPlaylistOptions = {},\n ): Promise<Playlist> {\n const { member, properties, parallel, metadata } = { parallel: true, ...options };\n if (!Array.isArray(songs)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", songs, \"songs\");\n if (!songs.length) throw new DisTubeError(\"EMPTY_ARRAY\", \"songs\");\n const filteredSongs = songs.filter(\n song => song instanceof Song || isURL(song) || (typeof song !== \"string\" && song.type === SearchResultType.VIDEO),\n );\n if (!filteredSongs.length) throw new DisTubeError(\"NO_VALID_SONG\");\n if (member && !isMemberInstance(member)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Member\", member, \"options.member\");\n }\n let resolvedSongs: Song[];\n if (parallel) {\n const promises = filteredSongs.map((song: string | Song | SearchResult) =>\n this.handler.resolve(song, { member, metadata }).catch(() => undefined),\n );\n resolvedSongs = (await Promise.all(promises)).filter((s: any): s is Song => Boolean(s));\n } else {\n const resolved = [];\n for (const song of filteredSongs) {\n resolved.push(await this.handler.resolve(song, { member, metadata }).catch(() => undefined));\n }\n resolvedSongs = resolved.filter((s: any): s is Song => Boolean(s));\n }\n return new Playlist(resolvedSongs, { member, properties, metadata });\n }\n\n search(\n string: string,\n options?: { type?: SearchResultType.VIDEO; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResultVideo>>;\n search(\n string: string,\n options: { type: SearchResultType.PLAYLIST; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResultPlaylist>>;\n search(\n string: string,\n options?: { type?: SearchResultType; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResult>>;\n /**\n * Search for a song. You can customize how user answers instead of send a number.\n * Then use {@link DisTube#play} to play it.\n *\n * @param {string} string The string search for\n * @param {Object} options Search options\n * @param {number} [options.limit=10] Limit the results\n * @param {SearchResultType} [options.type=SearchResultType.VIDEO] Type of results (`video` or `playlist`).\n * @param {boolean} [options.safeSearch=false] Whether or not use safe search (YouTube restricted mode)\n * @throws {Error}\n * @returns {Promise<Array<SearchResult>>} Array of results\n */\n async search(\n string: string,\n options: {\n type?: SearchResultType;\n limit?: number;\n safeSearch?: boolean;\n retried?: boolean;\n } = {},\n ): Promise<Array<SearchResult>> {\n const opts = { type: SearchResultType.VIDEO, limit: 10, safeSearch: false, ...options };\n if (typeof opts.type !== \"string\" || ![\"video\", \"playlist\"].includes(opts.type)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"video\", \"playlist\"], opts.type, \"options.type\");\n }\n if (typeof opts.limit !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", opts.limit, \"options.limit\");\n if (opts.limit < 1) throw new DisTubeError(\"NUMBER_COMPARE\", \"option.limit\", \"bigger or equal to\", 1);\n if (typeof opts.safeSearch !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", opts.safeSearch, \"options.safeSearch\");\n }\n\n try {\n const search = await ytsr(string, { ...opts, requestOptions: { headers: { cookie: this.handler.ytCookie } } });\n const results = search.items.map(i => {\n if (i.type === \"video\") return new SearchResultVideo(i);\n return new SearchResultPlaylist(i as any);\n });\n if (results.length === 0) throw new DisTubeError(\"NO_RESULT\");\n return results;\n } catch (e) {\n if (options.retried) throw e;\n options.retried = true;\n return this.search(string, options);\n }\n }\n\n /**\n * Get the guild queue\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Queue?}\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"queue\") {\n * const queue = distube.getQueue(message);\n * message.channel.send('Current queue:\\n' + queue.songs.map((song, id) =>\n * `**${id+1}**. [${song.name}](${song.url}) - \\`${song.formattedDuration}\\``\n * ).join(\"\\n\"));\n * }\n * });\n */\n getQueue(guild: GuildIdResolvable): Queue | undefined {\n return this.queues.get(guild);\n }\n\n #getQueue(guild: GuildIdResolvable): Queue {\n const queue = this.getQueue(guild);\n if (!queue) throw new DisTubeError(\"NO_QUEUE\");\n return queue;\n }\n\n /**\n * Pause the guild stream\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Queue} The guild queue\n * @throws {Error}\n */\n pause(guild: GuildIdResolvable): Queue {\n return this.#getQueue(guild).pause();\n }\n\n /**\n * Resume the guild stream\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Queue} The guild queue\n * @throws {Error}\n */\n resume(guild: GuildIdResolvable): Queue {\n return this.#getQueue(guild).resume();\n }\n\n /**\n * Stop the guild stream\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Promise<void>}\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"stop\") {\n * distube.stop(message);\n * message.channel.send(\"Stopped the queue!\");\n * }\n * });\n */\n stop(guild: GuildIdResolvable): Promise<void> {\n return this.#getQueue(guild).stop();\n }\n\n /**\n * Set the guild stream's volume\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @param {number} percent The percentage of volume you want to set\n * @returns {Queue} The guild queue\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"volume\")\n * distube.setVolume(message, Number(args[0]));\n * });\n */\n setVolume(guild: GuildIdResolvable, percent: number): Queue {\n return this.#getQueue(guild).setVolume(percent);\n }\n\n /**\n * Skip the playing song if there is a next song in the queue.\n * <info>If {@link Queue#autoplay} is `true` and there is no up next song,\n * DisTube will add and play a related song.</info>\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Promise<Song>} The new Song will be played\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"skip\")\n * distube.skip(message);\n * });\n */\n skip(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).skip();\n }\n\n /**\n * Play the previous song\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Promise<Song>} The new Song will be played\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"previous\")\n * distube.previous(message);\n * });\n */\n previous(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).previous();\n }\n\n /**\n * Shuffle the guild queue songs\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Promise<Queue>} The guild queue\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"shuffle\")\n * distube.shuffle(message);\n * });\n */\n shuffle(guild: GuildIdResolvable): Promise<Queue> {\n return this.#getQueue(guild).shuffle();\n }\n\n /**\n * Jump to the song number in the queue.\n * The next one is 1, 2,...\n * The previous one is -1, -2,...\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @param {number} num The song number to play\n * @returns {Promise<Song>} The new Song will be played\n * @throws {Error} if `num` is invalid number (0 < num < {@link Queue#songs}.length)\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"jump\")\n * distube.jump(message, parseInt(args[0]))\n * .catch(err => message.channel.send(\"Invalid song number.\"));\n * });\n */\n jump(guild: GuildIdResolvable, num: number): Promise<Song> {\n return this.#getQueue(guild).jump(num);\n }\n\n /**\n * Set the repeat mode of the guild queue.\\\n * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @param {RepeatMode?} [mode] The repeat modes (toggle if `undefined`)\n * @returns {RepeatMode} The new repeat mode\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"repeat\") {\n * let mode = distube.setRepeatMode(message, parseInt(args[0]));\n * mode = mode ? mode == 2 ? \"Repeat queue\" : \"Repeat song\" : \"Off\";\n * message.channel.send(\"Set repeat mode to `\" + mode + \"`\");\n * }\n * });\n * @example\n * const { RepeatMode } = require(\"distube\");\n * let mode;\n * switch(distube.setRepeatMode(message, parseInt(args[0]))) {\n * case RepeatMode.DISABLED:\n * mode = \"Off\";\n * break;\n * case RepeatMode.SONG:\n * mode = \"Repeat a song\";\n * break;\n * case RepeatMode.QUEUE:\n * mode = \"Repeat all queue\";\n * break;\n * }\n * message.channel.send(\"Set repeat mode to `\" + mode + \"`\");\n */\n setRepeatMode(guild: GuildIdResolvable, mode?: number): number {\n return this.#getQueue(guild).setRepeatMode(mode);\n }\n\n /**\n * Toggle autoplay mode\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {boolean} Autoplay mode state\n * @throws {Error}\n * @example\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"autoplay\") {\n * const mode = distube.toggleAutoplay(message);\n * message.channel.send(\"Set autoplay mode to `\" + (mode ? \"On\" : \"Off\") + \"`\");\n * }\n * });\n */\n toggleAutoplay(guild: GuildIdResolvable): boolean {\n const queue = this.#getQueue(guild);\n queue.autoplay = !queue.autoplay;\n return queue.autoplay;\n }\n\n /**\n * Add related song to the queue\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @returns {Promise<Song>} The guild queue\n */\n addRelatedSong(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).addRelatedSong();\n }\n\n /**\n * Set the playing time to another position\n * @param {GuildIdResolvable} guild The type can be resolved to give a {@link Queue}\n * @param {number} time Time in seconds\n * @returns {Queue} Seeked queue\n * @example\n * client.on('message', message => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command = 'seek')\n * distube.seek(message, Number(args[0]));\n * });\n */\n seek(guild: GuildIdResolvable, time: number): Queue {\n return this.#getQueue(guild).seek(time);\n }\n\n /**\n * Emit error event\n * @param {Error} error error\n * @param {Discord.BaseGuildTextChannel} [channel] Text channel where the error is encountered.\n * @private\n */\n emitError(error: Error, channel?: GuildTextBasedChannel): void {\n if (this.listeners(\"error\").length) {\n this.emit(\"error\", channel, error);\n } else {\n /* eslint-disable no-console */\n console.error(error);\n console.warn(\"Unhandled 'error' event.\");\n console.warn(\n \"See: https://distube.js.org/#/docs/DisTube/stable/class/DisTube?scrollTo=e-error and https://nodejs.org/api/events.html#events_error_events\",\n );\n /* eslint-enable no-console */\n }\n }\n}\n\nexport default DisTube;\n\n/**\n * Emitted after DisTube add a new playlist to the playing {@link Queue}.\n *\n * @event DisTube#addList\n * @param {Queue} queue The guild queue\n * @param {Playlist} playlist Playlist info\n * @example\n * distube.on(\"addList\", (queue, playlist) => queue.textChannel.send(\n * `Added \\`${playlist.name}\\` playlist (${playlist.songs.length} songs) to the queue!`\n * ));\n */\n\n/**\n * Emitted after DisTube add a new song to the playing {@link Queue}.\n *\n * @event DisTube#addSong\n * @param {Queue} queue The guild queue\n * @param {Song} song Added song\n * @example\n * distube.on(\"addSong\", (queue, song) => queue.textChannel.send(\n * `Added ${song.name} - \\`${song.formattedDuration}\\` to the queue by ${song.user}.`\n * ));\n */\n\n/**\n * Emitted when there is no user in the voice channel,\n * {@link DisTubeOptions}.leaveOnEmpty is `true` and there is a playing queue.\n *\n * If there is no playing queue (stopped and {@link DisTubeOptions}.leaveOnStop is `false`),\n * it will leave the channel without emitting this event.\n * @event DisTube#empty\n * @param {Queue} queue The guild queue\n * @example\n * distube.on(\"empty\", queue => queue.textChannel.send(\"Channel is empty. Leaving the channel\"))\n */\n\n/**\n * Emitted when DisTube encounters an error while playing songs.\n *\n * @event DisTube#error\n * @param {Discord.BaseGuildTextChannel?} channel Text channel where the error is encountered.\n * @param {Error} error The error encountered\n * @example\n * distube.on('error', (channel, e) => {\n * if (channel) channel.send(`An error encountered: ${e}`)\n * else console.error(e)\n * })\n */\n\n/**\n * Emitted when there is no more song in the queue and {@link Queue#autoplay} is `false`.\n * DisTube will leave voice channel if {@link DisTubeOptions}.leaveOnFinish is `true`.\n *\n * @event DisTube#finish\n * @param {Queue} queue The guild queue\n * @example\n * distube.on(\"finish\", queue => queue.textChannel.send(\"No more song in queue\"));\n */\n\n/**\n * Emitted when DisTube initialize a queue to change queue default properties.\n *\n * @event DisTube#initQueue\n * @param {Queue} queue The guild queue\n * @example\n * distube.on(\"initQueue\", queue => {\n * queue.autoplay = false;\n * queue.volume = 100;\n * });\n */\n\n/**\n * Emitted when {@link Queue#autoplay} is `true`, {@link Queue#songs} is empty,\n * and DisTube cannot find related songs to play.\n *\n * @event DisTube#noRelated\n * @param {Queue} queue The guild queue\n * @example\n * distube.on(\"noRelated\", queue => queue.textChannel.send(\"Can't find related video to play.\"));\n */\n\n/**\n * Emitted when DisTube play a song.\n *\n * If {@link DisTubeOptions}.emitNewSongOnly is `true`,\n * this event is not emitted when looping a song or next song is the previous one.\n *\n * @event DisTube#playSong\n * @param {Queue} queue The guild queue\n * @param {Song} song Playing song\n * @example\n * distube.on(\"playSong\", (queue, song) => queue.textChannel.send(\n * `Playing \\`${song.name}\\` - \\`${song.formattedDuration}\\`\\nRequested by: ${song.user}`\n * ));\n */\n\n/**\n * Emitted when DisTube cannot find any results for the query.\n *\n * @event DisTube#searchNoResult\n * @param {Discord.Message} message The user message called play method\n * @param {string} query The search query\n * @example\n * distube.on(\"searchNoResult\", (message, query) => message.channel.send(`No result found for ${query}!`));\n */\n\n/**\n * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,\n * and song param of {@link DisTube#play} is invalid url.\n * DisTube will wait for user's next message to choose a song manually.\n * <info>{@link https://support.google.com/youtube/answer/7354993|Safe search} is enabled\n * if {@link DisTubeOptions}.nsfw is disabled and the message's channel is not a nsfw channel.</info>\n *\n * @event DisTube#searchResult\n * @param {Discord.Message} message The user message called play method\n * @param {Array<SearchResult>} results Searched results\n * @param {string} query The search query\n * @example\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchResult\", (message, results) => {\n * message.channel.send(`**Choose an option from below**\\n${\n * results.map((song, i) => `**${i + 1}**. ${song.name} - \\`${song.formattedDuration}\\``).join(\"\\n\")\n * }\\n*Enter anything else or wait 60 seconds to cancel*`);\n * });\n */\n\n/**\n * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,\n * and the search canceled due to {@link DisTubeOptions|DisTubeOptions.searchTimeout}.\n *\n * @event DisTube#searchCancel\n * @param {Discord.Message} message The user message called play method\n * @param {string} query The search query\n * @example\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchCancel\", (message) => message.channel.send(`Searching canceled`));\n */\n\n/**\n * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,\n * and the search canceled due to user's next message is not a number or out of results range.\n *\n * @event DisTube#searchInvalidAnswer\n * @param {Discord.Message} message The user message called play method\n * @param {Discord.Message} answer The answered message of user\n * @param {string} query The search query\n * @example\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchInvalidAnswer\", (message) => message.channel.send(`You answered an invalid number!`));\n */\n\n/**\n * Emitted when {@link DisTubeOptions|DisTubeOptions.searchSongs} bigger than 0,\n * and after the user chose a search result to play.\n *\n * @event DisTube#searchDone\n * @param {Discord.Message} message The user message called play method\n * @param {Discord.Message} answer The answered message of user\n * @param {string} query The search query\n */\n\n/**\n * Emitted when the bot is disconnected to a voice channel.\n *\n * @event DisTube#disconnect\n * @param {Queue} queue The guild queue\n */\n\n/**\n * Emitted when a {@link Queue} is deleted with any reasons.\n *\n * @event DisTube#deleteQueue\n * @param {Queue} queue The guild queue\n */\n\n/**\n * Emitted when DisTube finished a song.\n *\n * @event DisTube#finishSong\n * @param {Queue} queue The guild queue\n * @param {Song} song Finished song\n */\n"],"mappings":"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","names":["module","RepeatMode","PluginType","SearchResultType","StreamType","Events","_metadata","_member","import_voice","DiscordVoiceStreamType","ytdl","ytpl","import_discord","import_voice","import_discord","import_tiny_typed_emitter","ytsr"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/index.ts","../src/type.ts","../src/constant.ts","../src/struct/DisTubeError.ts","../src/struct/TaskQueue.ts","../src/struct/Playlist.ts","../src/struct/SearchResult.ts","../src/struct/Song.ts","../src/core/DisTubeBase.ts","../src/core/DisTubeVoice.ts","../src/core/DisTubeStream.ts","../src/core/DisTubeHandler.ts","../src/core/DisTubeOptions.ts","../src/core/manager/BaseManager.ts","../src/core/manager/GuildIdManager.ts","../src/core/manager/DisTubeVoiceManager.ts","../src/core/manager/FilterManager.ts","../src/core/manager/QueueManager.ts","../src/struct/Queue.ts","../src/struct/Plugin.ts","../src/struct/CustomPlugin.ts","../src/struct/ExtractorPlugin.ts","../src/util.ts","../src/plugin/DirectLink.ts","../src/DisTube.ts"],"sourcesContent":["{\n \"name\": \"distube\",\n \"version\": \"4.2.1\",\n \"description\": \"A Discord.js module to simplify your music commands and play songs with audio filters on Discord without any API key.\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": \"./dist/index.js\",\n \"directories\": {\n \"lib\": \"src\",\n \"test\": \"tests\"\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"test\": \"jest\",\n \"docs\": \"typedoc\",\n \"lint\": \"prettier --check . && eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prettier\": \"prettier --write \\\"**/*.{ts,json,yml,yaml,md}\\\"\",\n \"build\": \"tsup\",\n \"build:check\": \"tsc --noEmit\",\n \"update\": \"pnpm up -L\",\n \"postinstall\": \"husky\",\n \"prepublishOnly\": \"pnpm run lint && pnpm run test\",\n \"prepack\": \"pnpm run build && pinst --disable\",\n \"postpack\": \"pinst --enable\",\n \"dev:add-docs-to-worktree\": \"git worktree add --track -b docs docs origin/docs\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/skick1234/DisTube.git\"\n },\n \"keywords\": [\n \"youtube\",\n \"music\",\n \"discord\",\n \"discordjs\",\n \"bot\",\n \"distube\",\n \"queue\",\n \"musicbot\",\n \"discord-music-bot\",\n \"music-bot\",\n \"discord-js\"\n ],\n \"author\": \"Skick (https://github.com/skick1234)\",\n \"license\": \"MIT\",\n \"bugs\": {\n \"url\": \"https://github.com/skick1234/DisTube/issues\"\n },\n \"funding\": \"https://github.com/skick1234/DisTube?sponsor=1\",\n \"homepage\": \"https://distube.js.org/\",\n \"dependencies\": {\n \"@distube/ytdl-core\": \"^4.13.3\",\n \"@distube/ytpl\": \"^1.2.1\",\n \"@distube/ytsr\": \"^2.0.0\",\n \"tiny-typed-emitter\": \"^2.1.0\",\n \"tough-cookie\": \"^4.1.3\",\n \"tslib\": \"^2.6.2\",\n \"undici\": \"^6.13.0\"\n },\n \"devDependencies\": {\n \"@babel/core\": \"^7.24.4\",\n \"@babel/plugin-transform-class-properties\": \"^7.24.1\",\n \"@babel/plugin-transform-object-rest-spread\": \"^7.24.1\",\n \"@babel/plugin-transform-private-methods\": \"^7.24.1\",\n \"@babel/preset-env\": \"^7.24.4\",\n \"@babel/preset-typescript\": \"^7.24.1\",\n \"@commitlint/cli\": \"^19.2.2\",\n \"@commitlint/config-conventional\": \"^19.2.2\",\n \"@discordjs/voice\": \"^0.16.1\",\n \"@types/jest\": \"^29.5.12\",\n \"@types/node\": \"^20.12.7\",\n \"@types/tough-cookie\": \"^4.0.5\",\n \"@typescript-eslint/eslint-plugin\": \"^7.7.0\",\n \"@typescript-eslint/parser\": \"^7.7.0\",\n \"babel-jest\": \"^29.7.0\",\n \"discord.js\": \"^14.14.1\",\n \"eslint\": \"^8.57.0\",\n \"eslint-config-distube\": \"^1.7.0\",\n \"husky\": \"^9.0.11\",\n \"jest\": \"^29.7.0\",\n \"nano-staged\": \"^0.8.0\",\n \"pinst\": \"^3.0.0\",\n \"prettier\": \"^3.2.5\",\n \"tsup\": \"^8.0.2\",\n \"typedoc\": \"^0.25.13\",\n \"typedoc-material-theme\": \"^1.0.2\",\n \"typescript\": \"^5.4.5\"\n },\n \"peerDependencies\": {\n \"@discordjs/voice\": \"*\",\n \"discord.js\": \"14\"\n },\n \"nano-staged\": {\n \"*.ts\": [\n \"prettier --write\",\n \"eslint\"\n ],\n \"*.{json,yml,yaml,md}\": [\n \"prettier --write\"\n ]\n },\n \"engines\": {\n \"node\": \">=18.17\"\n }\n}\n","export * from \"./type\";\nexport * from \"./constant\";\nexport * from \"./struct\";\nexport * from \"./util\";\nexport * from \"./core\";\nexport * from \"./plugin\";\nexport { DisTube, DisTube as default, version } from \"./DisTube\";\n","import type ytdl from \"@distube/ytdl-core\";\nimport type {\n Guild,\n GuildMember,\n GuildTextBasedChannel,\n Interaction,\n Message,\n Snowflake,\n VoiceBasedChannel,\n VoiceState,\n} from \"discord.js\";\nimport type { CustomPlugin, DisTubeVoice, ExtractorPlugin, Playlist, Queue, SearchResult, Song } from \".\";\nimport type { Cookie } from \"@distube/ytdl-core\";\n\nexport type Awaitable<T = any> = T | PromiseLike<T>;\n\n// export type DisTubeEvents = {\n// [Events.ADD_LIST]: [queue: Queue, playlist: Playlist];\n// [Events.ADD_SONG]: [queue: Queue, song: Song];\n// [Events.DELETE_QUEUE]: [queue: Queue];\n// [Events.DISCONNECT]: [queue: Queue];\n// [Events.EMPTY]: [queue: Queue];\n// [Events.ERROR]: [channel: GuildTextBasedChannel | undefined, error: Error];\n// [Events.FFMPEG_DEBUG]: [debug: string];\n// [Events.FINISH]: [queue: Queue];\n// [Events.FINISH_SONG]: [queue: Queue, song: Song];\n// [Events.INIT_QUEUE]: [queue: Queue];\n// [Events.NO_RELATED]: [queue: Queue];\n// [Events.PLAY_SONG]: [queue: Queue, song: Song];\n// [Events.SEARCH_CANCEL]: [message: Message<true>, query: string];\n// [Events.SEARCH_DONE]: [message: Message<true>, answer: Message<true>, query: string];\n// [Events.SEARCH_INVALID_ANSWER]: [message: Message<true>, answer: Message<true>, query: string];\n// [Events.SEARCH_NO_RESULT]: [message: Message<true>, query: string];\n// [Events.SEARCH_RESULT]: [message: Message<true>, results: SearchResult[], query: string];\n// };\n\nexport type DisTubeEvents = {\n addList: [queue: Queue, playlist: Playlist];\n addSong: [queue: Queue, song: Song];\n deleteQueue: [queue: Queue];\n disconnect: [queue: Queue];\n empty: [queue: Queue];\n error: [channel: GuildTextBasedChannel | undefined, error: Error];\n ffmpegDebug: [debug: string];\n finish: [queue: Queue];\n finishSong: [queue: Queue, song: Song];\n initQueue: [queue: Queue];\n noRelated: [queue: Queue];\n playSong: [queue: Queue, song: Song];\n searchCancel: [message: Message<true>, query: string];\n searchDone: [message: Message<true>, answer: Message<true>, query: string];\n searchInvalidAnswer: [message: Message<true>, answer: Message<true>, query: string];\n searchNoResult: [message: Message<true>, query: string];\n searchResult: [message: Message<true>, results: SearchResult[], query: string];\n};\n\nexport type TypedDisTubeEvents = {\n [K in keyof DisTubeEvents]: (...args: DisTubeEvents[K]) => Awaitable;\n};\n\nexport type DisTubeVoiceEvents = {\n disconnect: (error?: Error) => Awaitable;\n error: (error: Error) => Awaitable;\n finish: () => Awaitable;\n};\n\n/**\n * An FFmpeg audio filter object\n *\n * ```ts\n * {\n * name: \"bassboost\",\n * value: \"bass=g=10\"\n * }\n * ```ts\n */\nexport interface Filter {\n /**\n * Name of the filter\n */\n name: string;\n /**\n * FFmpeg audio filter argument\n */\n value: string;\n}\n\n/**\n * Data that resolves to give an FFmpeg audio filter. This can be:\n *\n * - A name of a default filters or custom filters (`string`)\n * - A {@link Filter} object\n *\n * @see {@link defaultFilters}\n * @see {@link DisTubeOptions|DisTubeOptions.customFilters}\n */\nexport type FilterResolvable = string | Filter;\n\n/**\n * FFmpeg Filters\n *\n * ```ts\n * {\n * \"Filter Name\": \"Filter Value\",\n * \"bassboost\": \"bass=g=10\"\n * }\n * ```ts\n *\n * @see {@link defaultFilters}\n */\nexport type Filters = Record<string, string>;\n\n/**\n * DisTube options\n */\nexport type DisTubeOptions = {\n /**\n * DisTube plugins\n */\n plugins?: (CustomPlugin | ExtractorPlugin)[];\n /**\n * Whether or not emitting {@link DisTube#playSong} event when looping a song\n * or next song is the same as the previous one\n */\n emitNewSongOnly?: boolean;\n /**\n * Whether or not leaving voice channel if the voice channel is empty after {@link\n * DisTubeOptions}.emptyCooldown seconds\n */\n leaveOnEmpty?: boolean;\n /**\n * Whether or not leaving voice channel when the queue ends\n */\n leaveOnFinish?: boolean;\n /**\n * Whether or not leaving voice channel after using {@link DisTube#stop} function\n */\n leaveOnStop?: boolean;\n /**\n * Built-in leave on empty cooldown in seconds (When leaveOnEmpty is true)\n */\n emptyCooldown?: number;\n /**\n * Whether or not saving the previous songs of the queue and enable {@link\n * DisTube#previous} method\n */\n savePreviousSongs?: boolean;\n /**\n * Limit of search results emits in {@link DisTube#searchResult} event when\n * {@link DisTube#play} method executed. If `searchSongs <= 1`, play the first\n * result\n */\n searchSongs?: number;\n /**\n * Built-in search cooldown in seconds (When searchSongs is bigger than 0)\n */\n searchCooldown?: number;\n /**\n * YouTube cookies. Guide: {@link\n * https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}\n */\n youtubeCookie?: Cookie[] | string;\n /**\n * Override {@link defaultFilters} or add more ffmpeg filters\n */\n customFilters?: Filters;\n /**\n * `ytdl-core` get info options\n */\n ytdlOptions?: ytdl.downloadOptions;\n /**\n * Whether or not playing age-restricted content and disabling safe search in\n * non-NSFW channel\n */\n nsfw?: boolean;\n /**\n * Whether or not emitting `addSong` event when creating a new Queue\n */\n emitAddSongWhenCreatingQueue?: boolean;\n /**\n * Whether or not emitting `addList` event when creating a new Queue\n */\n emitAddListWhenCreatingQueue?: boolean;\n /**\n * Whether or not joining the new voice channel when using {@link DisTube#play}\n * method\n */\n joinNewVoiceChannel?: boolean;\n /**\n * Decide the {@link DisTubeStream#type} will be used (Not the same as {@link\n * DisTubeStream#type})\n */\n streamType?: StreamType;\n /**\n * Whether or not playing a song with direct link\n */\n directLink?: boolean;\n /**\n * FFmpeg path\n * @deprecated\n */\n ffmpegPath?: string;\n /**\n * FFmpeg default arguments\n * @deprecated\n */\n ffmpegDefaultArgs?: FFmpegArgs;\n /**\n * FFmpeg options\n */\n ffmpeg?: {\n /**\n * FFmpeg path\n */\n path?: string;\n /**\n * FFmpeg default arguments\n */\n args?: {\n global?: FFmpegArgs;\n input?: FFmpegArgs;\n output?: FFmpegArgs;\n };\n };\n};\n\n/**\n * Data that can be resolved to give a guild id string. This can be:\n *\n * - A guild id string | a guild {@link https://discord.js.org/#/docs/main/stable/class/Snowflake|Snowflake}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Guild | Guild}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Message | Message}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/BaseGuildVoiceChannel\n * | BaseGuildVoiceChannel}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/BaseGuildTextChannel\n * | BaseGuildTextChannel}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/VoiceState |\n * VoiceState}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/GuildMember |\n * GuildMember}\n * - A {@link https://discord.js.org/#/docs/main/stable/class/Interaction |\n * Interaction}\n * - A {@link DisTubeVoice}\n * - A {@link Queue}\n */\nexport type GuildIdResolvable =\n | Queue\n | DisTubeVoice\n | Snowflake\n | Message\n | GuildTextBasedChannel\n | VoiceBasedChannel\n | VoiceState\n | Guild\n | GuildMember\n | Interaction\n | string;\n\nexport interface OtherSongInfo {\n src: string;\n id?: string;\n title?: string;\n name?: string;\n is_live?: boolean;\n isLive?: boolean;\n _duration_raw?: string | number;\n duration?: string | number;\n webpage_url?: string;\n url: string;\n thumbnail?: string;\n related?: RelatedSong[];\n view_count?: string | number;\n views?: string | number;\n like_count?: string | number;\n likes?: string | number;\n dislike_count?: string | number;\n dislikes?: string | number;\n repost_count?: string | number;\n reposts?: string | number;\n uploader?: string | { name: string; url: string };\n uploader_url?: string;\n age_limit?: string | number;\n chapters?: Chapter[];\n age_restricted?: boolean;\n}\n\nexport interface Chapter {\n title: string;\n start_time: number;\n}\n\nexport interface PlaylistInfo {\n source: string;\n member?: GuildMember;\n songs: Song[];\n name?: string;\n url?: string;\n thumbnail?: string;\n /**\n * @deprecated Use {@link PlaylistInfo#name}\n */\n title?: string;\n /**\n * @deprecated Use {@link PlaylistInfo#url}\n */\n webpage_url?: string;\n}\n\nexport type RelatedSong = Omit<Song, \"related\">;\n\nexport type PlayHandlerOptions = {\n /**\n * [Default: false] Skip the playing song (if exists) and play the added playlist\n * instantly\n */\n skip?: boolean;\n /**\n * [Default: 0] Position of the song/playlist to add to the queue, \\<= 0 to add to\n * the end of the queue\n */\n position?: number;\n /**\n * The default text channel of the queue\n */\n textChannel?: GuildTextBasedChannel;\n};\n\nexport interface PlayOptions extends PlayHandlerOptions, ResolveOptions<any> {\n /**\n * Called message (For built-in search events. If this is a {@link\n * https://developer.mozilla.org/en-US/docs/Glossary/Falsy | falsy value}, it will\n * play the first result instead)\n */\n message?: Message;\n}\n\nexport interface ResolveOptions<T = unknown> {\n /**\n * Requested user\n */\n member?: GuildMember;\n /**\n * Metadata\n */\n metadata?: T;\n}\n\nexport interface ResolvePlaylistOptions<T = unknown> extends ResolveOptions<T> {\n /**\n * Source of the playlist\n */\n source?: string;\n}\n\nexport interface CustomPlaylistOptions {\n /**\n * A guild member creating the playlist\n */\n member?: GuildMember;\n /**\n * Additional properties such as `name`\n */\n properties?: Record<string, any>;\n /**\n * Whether or not fetch the songs in parallel\n */\n parallel?: boolean;\n /**\n * Metadata\n */\n metadata?: any;\n}\n\n/**\n * The repeat mode of a {@link Queue}\n *\n * - `DISABLED` = 0\n * - `SONG` = 1\n * - `QUEUE` = 2\n */\nexport enum RepeatMode {\n DISABLED,\n SONG,\n QUEUE,\n}\n\n/**\n * All available plugin types:\n *\n * - `CUSTOM` = `\"custom\"`: {@link CustomPlugin}\n * - `EXTRACTOR` = `\"extractor\"`: {@link ExtractorPlugin}\n */\nexport enum PluginType {\n CUSTOM = \"custom\",\n EXTRACTOR = \"extractor\",\n}\n\n/**\n * Search result types:\n *\n * - `VIDEO` = `\"video\"`\n * - `PLAYLIST` = `\"playlist\"`\n */\nexport enum SearchResultType {\n VIDEO = \"video\",\n PLAYLIST = \"playlist\",\n}\n\n/**\n * Stream types:\n *\n * - `OPUS` = `0` (Better quality, use more resources - **Recommended**)\n * - `RAW` = `1` (Better performance, use less resources)\n */\nexport enum StreamType {\n OPUS,\n RAW,\n}\n\nexport enum Events {\n ERROR = \"error\",\n ADD_LIST = \"addList\",\n ADD_SONG = \"addSong\",\n PLAY_SONG = \"playSong\",\n FINISH_SONG = \"finishSong\",\n EMPTY = \"empty\",\n FINISH = \"finish\",\n INIT_QUEUE = \"initQueue\",\n NO_RELATED = \"noRelated\",\n DISCONNECT = \"disconnect\",\n DELETE_QUEUE = \"deleteQueue\",\n SEARCH_CANCEL = \"searchCancel\",\n SEARCH_NO_RESULT = \"searchNoResult\",\n SEARCH_DONE = \"searchDone\",\n SEARCH_INVALID_ANSWER = \"searchInvalidAnswer\",\n SEARCH_RESULT = \"searchResult\",\n FFMPEG_DEBUG = \"ffmpegDebug\",\n}\n\nexport type FFmpegArgs = Record<\n string,\n string | number | boolean | Array<string | null | undefined> | null | undefined\n>;\n\nexport type FFmpegOptions = {\n path: string;\n args: {\n global: FFmpegArgs;\n input: FFmpegArgs;\n output: FFmpegArgs;\n };\n};\n","import { StreamType } from \".\";\nimport type { DisTubeOptions, Filters } from \".\";\n\n/**\n * Default DisTube audio filters.\n */\nexport const defaultFilters: Filters = {\n \"3d\": \"apulsator=hz=0.125\",\n bassboost: \"bass=g=10\",\n echo: \"aecho=0.8:0.9:1000:0.3\",\n flanger: \"flanger\",\n gate: \"agate\",\n haas: \"haas\",\n karaoke: \"stereotools=mlev=0.1\",\n nightcore: \"asetrate=48000*1.25,aresample=48000,bass=g=5\",\n reverse: \"areverse\",\n vaporwave: \"asetrate=48000*0.8,aresample=48000,atempo=1.1\",\n mcompand: \"mcompand\",\n phaser: \"aphaser\",\n tremolo: \"tremolo\",\n surround: \"surround\",\n earwax: \"earwax\",\n};\n\nexport const defaultOptions = {\n plugins: [],\n emitNewSongOnly: false,\n leaveOnEmpty: true,\n leaveOnFinish: false,\n leaveOnStop: true,\n savePreviousSongs: true,\n searchSongs: 0,\n ytdlOptions: {},\n searchCooldown: 60,\n emptyCooldown: 60,\n nsfw: false,\n emitAddSongWhenCreatingQueue: true,\n emitAddListWhenCreatingQueue: true,\n joinNewVoiceChannel: true,\n streamType: StreamType.OPUS,\n directLink: true,\n} satisfies DisTubeOptions;\n","import { inspect } from \"node:util\";\n\nconst ERROR_MESSAGES = {\n INVALID_TYPE: (expected: (number | string) | readonly (number | string)[], got: any, name?: string) =>\n `Expected ${\n Array.isArray(expected) ? expected.map(e => (typeof e === \"number\" ? e : `'${e}'`)).join(\" or \") : `'${expected}'`\n }${name ? ` for '${name}'` : \"\"}, but got ${inspect(got)} (${typeof got})`,\n NUMBER_COMPARE: (name: string, expected: string, value: number) => `'${name}' must be ${expected} ${value}`,\n EMPTY_ARRAY: (name: string) => `'${name}' is an empty array`,\n EMPTY_FILTERED_ARRAY: (name: string, type: string) => `There is no valid '${type}' in the '${name}' array`,\n EMPTY_STRING: (name: string) => `'${name}' string must not be empty`,\n INVALID_KEY: (obj: string, key: string) => `'${key}' does not need to be provided in ${obj}`,\n MISSING_KEY: (obj: string, key: string) => `'${key}' needs to be provided in ${obj}`,\n MISSING_KEYS: (obj: string, key: string[], all: boolean) =>\n `${key.map(k => `'${k}'`).join(all ? \" and \" : \" or \")} need to be provided in ${obj}`,\n\n MISSING_INTENTS: (i: string) => `${i} intent must be provided for the Client`,\n DISABLED_OPTION: (o: string) => `DisTubeOptions.${o} is disabled`,\n ENABLED_OPTION: (o: string) => `DisTubeOptions.${o} is enabled`,\n\n NOT_IN_VOICE: \"User is not in any voice channel\",\n VOICE_FULL: \"The voice channel is full\",\n VOICE_CONNECT_FAILED: (s: number) => `Cannot connect to the voice channel after ${s} seconds`,\n VOICE_MISSING_PERMS: \"I do not have permission to join this voice channel\",\n VOICE_RECONNECT_FAILED: \"Cannot reconnect to the voice channel\",\n VOICE_DIFFERENT_GUILD: \"Cannot join a voice channel in a different guild\",\n VOICE_DIFFERENT_CLIENT: \"Cannot join a voice channel created by a different client\",\n\n FFMPEG_EXITED: (code: number) => `ffmpeg exited with code ${code}`,\n FFMPEG_NOT_INSTALLED: (path: string) => `ffmpeg is not installed at '${path}' path`,\n\n NO_QUEUE: \"There is no playing queue in this guild\",\n QUEUE_EXIST: \"This guild has a Queue already\",\n PAUSED: \"The queue has been paused already\",\n RESUMED: \"The queue has been playing already\",\n NO_PREVIOUS: \"There is no previous song in this queue\",\n NO_UP_NEXT: \"There is no up next song\",\n NO_SONG_POSITION: \"Does not have any song at this position\",\n NO_PLAYING: \"There is no playing song in the queue\",\n\n NO_RESULT: \"No result found\",\n NO_RELATED: \"Cannot find any related songs\",\n CANNOT_PLAY_RELATED: \"Cannot play the related song\",\n UNAVAILABLE_VIDEO: \"This video is unavailable\",\n UNPLAYABLE_FORMATS: \"No playable format found\",\n NON_NSFW: \"Cannot play age-restricted content in non-NSFW channel\",\n NOT_SUPPORTED_URL: \"This url is not supported\",\n CANNOT_RESOLVE_SONG: (t: any) => `Cannot resolve ${inspect(t)} to a Song`,\n NO_VALID_SONG: \"'songs' array does not have any valid Song, SearchResult or url\",\n EMPTY_FILTERED_PLAYLIST:\n \"There is no valid video in the playlist\\n\" +\n \"Maybe age-restricted contents is filtered because you are in non-NSFW channel\",\n EMPTY_PLAYLIST: \"There is no valid video in the playlist\",\n};\n\ntype ErrorMessage = typeof ERROR_MESSAGES;\ntype ErrorCode = keyof ErrorMessage;\ntype StaticErrorCode = { [K in ErrorCode]-?: ErrorMessage[K] extends string ? K : never }[ErrorCode];\ntype TemplateErrorCode = Exclude<keyof typeof ERROR_MESSAGES, StaticErrorCode>;\n\nconst haveCode = (code: string): code is ErrorCode => Object.keys(ERROR_MESSAGES).includes(code);\nconst parseMessage = (m: string | ((...x: any) => string), ...args: any) => (typeof m === \"string\" ? m : m(...args));\nconst getErrorMessage = (code: string, ...args: any): string =>\n haveCode(code) ? parseMessage(ERROR_MESSAGES[code], ...args) : args[0];\nexport class DisTubeError<T extends string> extends Error {\n errorCode: string;\n constructor(code: StaticErrorCode);\n constructor(code: T extends TemplateErrorCode ? T : never, ...args: Parameters<ErrorMessage[typeof code]>);\n constructor(code: TemplateErrorCode, _: never);\n constructor(code: T extends ErrorCode ? \"This is built-in error code\" : T, message: string);\n constructor(code: string, ...args: any) {\n super(getErrorMessage(code, ...args));\n\n this.errorCode = code;\n if (Error.captureStackTrace) Error.captureStackTrace(this, DisTubeError);\n }\n\n override get name() {\n return `DisTubeError [${this.errorCode}]`;\n }\n\n get code() {\n return this.errorCode;\n }\n}\n","class Task {\n resolve!: () => void;\n promise: Promise<void>;\n resolveInfo: boolean;\n constructor(resolveInfo: boolean) {\n this.resolveInfo = resolveInfo;\n this.promise = new Promise<void>(res => {\n this.resolve = res;\n });\n }\n}\n\n/**\n * Task queuing system\n */\nexport class TaskQueue {\n /**\n * The task array\n */\n #tasks: Task[] = [];\n\n /**\n * Waits for last task finished and queues a new task\n *\n * @param resolveInfo - Whether the task is a resolving info task\n */\n public queuing(resolveInfo = false): Promise<void> {\n const next = this.remaining ? this.#tasks[this.#tasks.length - 1].promise : Promise.resolve();\n this.#tasks.push(new Task(resolveInfo));\n return next;\n }\n\n /**\n * Removes the finished task and processes the next task\n */\n public resolve(): void {\n this.#tasks.shift()?.resolve();\n }\n\n /**\n * The remaining number of tasks\n */\n public get remaining(): number {\n return this.#tasks.length;\n }\n\n /**\n * Whether or not having a resolving info task\n */\n public get hasResolveTask(): boolean {\n return this.#tasks.some(t => t.resolveInfo);\n }\n}\n","import { DisTubeError, formatDuration, isMemberInstance, isRecord } from \"..\";\nimport type { PlaylistInfo, Song } from \"..\";\nimport type { GuildMember } from \"discord.js\";\n\n/**\n * Class representing a playlist.\n */\nexport class Playlist<T = unknown> implements PlaylistInfo {\n source!: string;\n songs!: Song[];\n name!: string;\n #metadata!: T;\n #member?: GuildMember;\n url?: string;\n thumbnail?: string;\n [x: string]: any;\n /**\n * Create a playlist\n *\n * @param playlist - Playlist\n * @param options - Optional options\n */\n constructor(\n playlist: Song[] | PlaylistInfo,\n options: {\n member?: GuildMember;\n properties?: Record<string, any>;\n metadata?: T;\n } = {},\n ) {\n const { member, properties, metadata } = options;\n\n if (\n typeof playlist !== \"object\" ||\n (!Array.isArray(playlist) && [\"source\", \"songs\"].some(key => !(key in playlist)))\n ) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Array<Song>\", \"PlaylistInfo\"], playlist, \"playlist\");\n }\n if (typeof properties !== \"undefined\" && !isRecord<any>(properties)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", properties, \"properties\");\n }\n\n if (Array.isArray(playlist)) {\n /**\n * The source of the playlist\n */\n this.source = \"youtube\";\n if (!playlist.length) throw new DisTubeError(\"EMPTY_PLAYLIST\");\n /**\n * Playlist songs.\n */\n this.songs = playlist;\n /**\n * Playlist name.\n */\n this.name = this.songs[0].name\n ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.`\n : `${this.songs.length} songs playlist`;\n this.thumbnail = this.songs[0].thumbnail;\n this.member = member;\n } else {\n this.source = playlist.source.toLowerCase();\n if (!Array.isArray(playlist.songs) || !playlist.songs.length) throw new DisTubeError(\"EMPTY_PLAYLIST\");\n this.songs = playlist.songs;\n this.name =\n playlist.name ||\n // eslint-disable-next-line deprecation/deprecation\n playlist.title ||\n (this.songs[0].name\n ? `${this.songs[0].name} and ${this.songs.length - 1} more songs.`\n : `${this.songs.length} songs playlist`);\n /**\n * Playlist URL.\n */\n // eslint-disable-next-line deprecation/deprecation\n this.url = playlist.url || playlist.webpage_url;\n /**\n * Playlist thumbnail.\n */\n this.thumbnail = playlist.thumbnail || this.songs[0].thumbnail;\n this.member = member || playlist.member;\n }\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.playlist = this));\n if (properties) for (const [key, value] of Object.entries(properties)) this[key] = value;\n /**\n * Optional metadata that can be used to identify the playlist.\n */\n this.metadata = metadata as T;\n }\n\n /**\n * Playlist duration in second.\n */\n get duration() {\n return this.songs.reduce((prev, next) => prev + next.duration, 0);\n }\n\n /**\n * Formatted duration string `hh:mm:ss`.\n */\n get formattedDuration() {\n return formatDuration(this.duration);\n }\n\n /**\n * User requested.\n */\n get member() {\n return this.#member;\n }\n\n set member(member: GuildMember | undefined) {\n if (!isMemberInstance(member)) return;\n this.#member = member;\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.member = this.member));\n }\n\n /**\n * User requested.\n */\n get user() {\n return this.member?.user;\n }\n\n get metadata() {\n return this.#metadata;\n }\n\n set metadata(metadata: T) {\n this.#metadata = metadata;\n this.songs.forEach(s => s.constructor.name === \"Song\" && (s.metadata = metadata));\n }\n}\n","import { DisTubeError, SearchResultType, formatDuration, toSecond } from \"..\";\nimport type { Playlist, Video } from \"@distube/ytsr\";\n\n/**\n * A abstract class representing a search result.\n *\n * @virtual\n */\nabstract class ISearchResult {\n source: \"youtube\";\n abstract type: SearchResultType;\n id: string;\n name: string;\n url: string;\n uploader: {\n name?: string;\n url?: string;\n };\n\n /**\n * Create a search result\n *\n * @param info - ytsr result\n */\n constructor(info: Video | Playlist) {\n /**\n * The source of the search result\n */\n this.source = \"youtube\";\n /**\n * YouTube video or playlist id\n */\n this.id = info.id;\n /**\n * Video or playlist title.\n */\n this.name = info.name;\n /**\n * Video or playlist URL.\n */\n this.url = info.url;\n /**\n * Video or playlist uploader\n */\n this.uploader = {\n name: undefined,\n url: undefined,\n };\n }\n}\n\n/**\n * A class representing a video search result.\n */\nexport class SearchResultVideo extends ISearchResult {\n type: SearchResultType.VIDEO;\n views: number;\n isLive: boolean;\n duration: number;\n formattedDuration: string;\n thumbnail: string;\n constructor(info: Video) {\n super(info);\n if (info.type !== \"video\") throw new DisTubeError(\"INVALID_TYPE\", \"video\", info.type, \"type\");\n /**\n * Type of SearchResult\n */\n this.type = SearchResultType.VIDEO;\n /**\n * Video views count\n */\n this.views = info.views;\n /**\n * Indicates if the video is an active live.\n */\n this.isLive = info.isLive;\n /**\n * Video duration.\n */\n this.duration = this.isLive ? 0 : toSecond(info.duration);\n /**\n * Formatted duration string `hh:mm:ss` or `mm:ss`.\n */\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n /**\n * Video thumbnail.\n */\n this.thumbnail = info.thumbnail;\n this.uploader = {\n name: info.author?.name,\n url: info.author?.url,\n };\n }\n}\n\n/**\n * A video or playlist search result\n */\nexport type SearchResult = SearchResultVideo | SearchResultPlaylist;\n\n/**\n * A class representing a playlist search result.\n */\nexport class SearchResultPlaylist extends ISearchResult {\n type: SearchResultType.PLAYLIST;\n length: number;\n constructor(info: Playlist) {\n super(info);\n if (info.type !== \"playlist\") throw new DisTubeError(\"INVALID_TYPE\", \"playlist\", info.type, \"type\");\n /**\n * Type of SearchResult\n */\n this.type = SearchResultType.PLAYLIST;\n /**\n * Length of the playlist\n */\n this.length = info.length;\n this.uploader = {\n name: info.owner?.name,\n url: info.owner?.url,\n };\n }\n}\n","import { Playlist } from \"./Playlist\";\nimport { DisTubeError, formatDuration, isMemberInstance, parseNumber, toSecond } from \"..\";\nimport type ytpl from \"@distube/ytpl\";\nimport type ytdl from \"@distube/ytdl-core\";\nimport type { GuildMember } from \"discord.js\";\nimport type { Chapter, OtherSongInfo, RelatedSong, SearchResult } from \"..\";\n\n/**\n * Class representing a song.\n *\n * <info>If {@link Song} is added from a YouTube {@link SearchResult} or {@link\n * Playlist}, some info will be missing to save your resources. It will be filled\n * when emitting {@link DisTube#playSong} event.\n *\n * Missing info: {@link Song#likes}, {@link Song#dislikes}, {@link Song#streamURL},\n * {@link Song#related}, {@link Song#chapters}, {@link Song#age_restricted}</info>\n */\nexport class Song<T = unknown> {\n source!: string;\n #metadata!: T;\n formats?: ytdl.videoFormat[];\n #member?: GuildMember;\n id?: string;\n name?: string;\n isLive!: boolean;\n duration!: number;\n formattedDuration?: string;\n url!: string;\n streamURL?: string;\n thumbnail?: string;\n related!: RelatedSong[];\n views!: number;\n likes!: number;\n dislikes!: number;\n uploader!: {\n name?: string;\n url?: string;\n };\n age_restricted!: boolean;\n chapters!: Chapter[];\n reposts!: number;\n #playlist?: Playlist;\n /**\n * Create a Song\n *\n * @param info - Raw info\n * @param options - Optional options\n */\n constructor(\n info:\n | ytdl.videoInfo\n | SearchResult\n | OtherSongInfo\n | ytdl.relatedVideo\n | RelatedSong\n | ytpl.result[\"items\"][number],\n options: {\n member?: GuildMember;\n source?: string;\n metadata?: T;\n } = {},\n ) {\n const { member, source, metadata } = { source: \"youtube\", ...options };\n\n if (\n typeof source !== \"string\" ||\n ((info as OtherSongInfo).src && typeof (info as OtherSongInfo).src !== \"string\")\n ) {\n throw new DisTubeError(\"INVALID_TYPE\", \"string\", source, \"source\");\n }\n /**\n * The source of the song\n */\n this.source = ((info as OtherSongInfo)?.src || source).toLowerCase();\n /**\n * Optional metadata that can be used to identify the song. This is attached by the\n * {@link DisTube#play} method.\n */\n this.metadata = metadata as T;\n this.member = member;\n if (this.source === \"youtube\") {\n this._patchYouTube(info as ytdl.videoInfo);\n } else {\n this._patchOther(info as OtherSongInfo);\n }\n }\n\n _patchYouTube(i: ytdl.videoInfo | SearchResult) {\n // FIXME\n const info = i as any;\n if (info.full === true) {\n /**\n * Stream formats (Available if the song is from YouTube and playing)\n */\n this.formats = info.formats;\n // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports\n const err = require(\"@distube/ytdl-core/lib/utils\").playError(info.player_response, [\n \"UNPLAYABLE\",\n \"LIVE_STREAM_OFFLINE\",\n \"LOGIN_REQUIRED\",\n ]);\n if (err) throw err;\n\n if (!info.formats?.length) throw new DisTubeError(\"UNAVAILABLE_VIDEO\");\n }\n const details = info.videoDetails || info;\n /**\n * YouTube video id\n */\n this.id = details.videoId || details.id;\n /**\n * Song name.\n */\n this.name = details.title || details.name;\n /**\n * Indicates if the video is an active live.\n */\n this.isLive = Boolean(details.isLive);\n /**\n * Song duration.\n */\n this.duration = this.isLive ? 0 : toSecond(details.lengthSeconds || details.length_seconds || details.duration);\n /**\n * Formatted duration string (`hh:mm:ss`, `mm:ss` or `Live`).\n */\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n /**\n * Song URL.\n */\n this.url = `https://www.youtube.com/watch?v=${this.id}`;\n /**\n * Stream / Download URL (Available if the song is playing)\n */\n this.streamURL = undefined;\n /**\n * Song thumbnail.\n */\n this.thumbnail =\n details.thumbnails?.sort((a: any, b: any) => b.width - a.width)?.[0]?.url ||\n details.thumbnail?.url ||\n details.thumbnail;\n /**\n * Related songs (without {@link Song#related} properties)\n */\n this.related = info?.related_videos || details.related || [];\n if (!Array.isArray(this.related)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", this.related, \"Song#related\");\n this.related = this.related.map((v: any) => new Song(v, { source: this.source, metadata: this.metadata }));\n /**\n * Song views count\n */\n this.views = parseNumber(details.viewCount || details.view_count || details.views);\n /**\n * Song like count\n */\n this.likes = parseNumber(details.likes);\n /**\n * Song dislike count\n */\n this.dislikes = parseNumber(details.dislikes);\n /**\n * Song uploader\n */\n this.uploader = {\n name: info.uploader?.name || details.author?.name,\n url: info.uploader?.url || details.author?.channel_url || details.author?.url,\n };\n /**\n * Whether or not an age-restricted content\n */\n this.age_restricted = Boolean(details.age_restricted);\n\n /**\n * Chapters information (YouTube only)\n */\n this.chapters = details.chapters || [];\n /**\n * Song repost count\n */\n this.reposts = 0;\n }\n\n /**\n * Patch data from other source\n *\n * @param info - Video info\n */\n _patchOther(info: OtherSongInfo) {\n this.id = info.id;\n this.name = info.title || info.name;\n this.isLive = Boolean(info.is_live || info.isLive);\n this.duration = this.isLive ? 0 : toSecond(info._duration_raw || info.duration);\n this.formattedDuration = this.isLive ? \"Live\" : formatDuration(this.duration);\n this.url = info.webpage_url || info.url;\n this.thumbnail = info.thumbnail;\n this.related = info.related || [];\n if (!Array.isArray(this.related)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", this.related, \"Song#related\");\n this.related = this.related.map(i => new Song(i, { source: this.source, metadata: this.metadata }));\n this.views = parseNumber(info.view_count || info.views);\n this.likes = parseNumber(info.like_count || info.likes);\n this.dislikes = parseNumber(info.dislike_count || info.dislikes);\n this.reposts = parseNumber(info.repost_count || info.reposts);\n if (typeof info.uploader === \"string\") {\n this.uploader = {\n name: info.uploader,\n url: info.uploader_url,\n };\n } else {\n this.uploader = {\n name: info.uploader?.name,\n url: info.uploader?.url,\n };\n }\n this.age_restricted = info.age_restricted || (Boolean(info.age_limit) && parseNumber(info.age_limit) >= 18);\n this.chapters = info.chapters || [];\n }\n\n /**\n * The playlist added this song\n */\n get playlist() {\n return this.#playlist;\n }\n\n set playlist(playlist: Playlist | undefined) {\n if (!(playlist instanceof Playlist)) throw new DisTubeError(\"INVALID_TYPE\", \"Playlist\", playlist, \"Song#playlist\");\n this.#playlist = playlist;\n this.member = playlist.member;\n }\n\n /**\n * User requested.\n */\n get member() {\n return this.#member;\n }\n\n set member(member: GuildMember | undefined) {\n if (isMemberInstance(member)) this.#member = member;\n }\n\n /**\n * User requested.\n */\n get user() {\n return this.member?.user;\n }\n\n get metadata() {\n return this.#metadata;\n }\n\n set metadata(metadata: T) {\n this.#metadata = metadata;\n }\n}\n","import type { Client, GuildTextBasedChannel } from \"discord.js\";\nimport type { DisTube, DisTubeEvents, DisTubeHandler, DisTubeVoiceManager, Options, QueueManager } from \"..\";\n\n/**\n * @virtual\n */\nexport abstract class DisTubeBase {\n distube: DisTube;\n constructor(distube: DisTube) {\n /**\n * DisTube\n */\n this.distube = distube;\n }\n /**\n * Emit the {@link DisTube} of this base\n *\n * @param eventName - Event name\n * @param args - arguments\n */\n emit(eventName: keyof DisTubeEvents, ...args: any): boolean {\n return this.distube.emit(eventName, ...args);\n }\n /**\n * Emit error event\n *\n * @param error - error\n * @param channel - Text channel where the error is encountered.\n */\n emitError(error: Error, channel?: GuildTextBasedChannel) {\n this.distube.emitError(error, channel);\n }\n /**\n * The queue manager\n */\n get queues(): QueueManager {\n return this.distube.queues;\n }\n /**\n * The voice manager\n */\n get voices(): DisTubeVoiceManager {\n return this.distube.voices;\n }\n /**\n * Discord.js client\n */\n get client(): Client {\n return this.distube.client;\n }\n /**\n * DisTube options\n */\n get options(): Options {\n return this.distube.options;\n }\n /**\n * DisTube handler\n */\n get handler(): DisTubeHandler {\n return this.distube.handler;\n }\n}\n","import { Constants } from \"discord.js\";\nimport { TypedEmitter } from \"tiny-typed-emitter\";\nimport { DisTubeError, isSupportedVoiceChannel } from \"..\";\nimport {\n AudioPlayerStatus,\n VoiceConnectionDisconnectReason,\n VoiceConnectionStatus,\n createAudioPlayer,\n createAudioResource,\n entersState,\n joinVoiceChannel,\n} from \"@discordjs/voice\";\nimport type { Snowflake, VoiceBasedChannel, VoiceState } from \"discord.js\";\nimport type { DisTubeStream, DisTubeVoiceEvents, DisTubeVoiceManager } from \"..\";\nimport type { AudioPlayer, AudioResource, VoiceConnection } from \"@discordjs/voice\";\n\n/**\n * Create a voice connection to the voice channel\n */\nexport class DisTubeVoice extends TypedEmitter<DisTubeVoiceEvents> {\n readonly id: Snowflake;\n readonly voices: DisTubeVoiceManager;\n readonly audioPlayer: AudioPlayer;\n connection!: VoiceConnection;\n audioResource?: AudioResource;\n emittedError!: boolean;\n isDisconnected = false;\n stream?: DisTubeStream;\n #channel!: VoiceBasedChannel;\n #volume = 100;\n constructor(voiceManager: DisTubeVoiceManager, channel: VoiceBasedChannel) {\n super();\n /**\n * The voice manager that instantiated this connection\n */\n this.voices = voiceManager;\n this.id = channel.guildId;\n this.channel = channel;\n this.voices.add(this.id, this);\n this.audioPlayer = createAudioPlayer()\n .on(AudioPlayerStatus.Idle, oldState => {\n if (oldState.status !== AudioPlayerStatus.Idle) {\n delete this.audioResource;\n this.emit(\"finish\");\n }\n })\n .on(AudioPlayerStatus.Playing, () => this.#br())\n .on(\"error\", (error: NodeJS.ErrnoException) => {\n if (this.emittedError) return;\n this.emittedError = true;\n this.emit(\"error\", error);\n });\n this.connection\n .on(VoiceConnectionStatus.Disconnected, (_, newState) => {\n if (newState.reason === VoiceConnectionDisconnectReason.Manual) {\n // User disconnect\n this.leave();\n } else if (newState.reason === VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) {\n // Move to other channel\n entersState(this.connection, VoiceConnectionStatus.Connecting, 5e3).catch(() => {\n if (\n ![VoiceConnectionStatus.Ready, VoiceConnectionStatus.Connecting].includes(this.connection.state.status)\n ) {\n this.leave();\n }\n });\n } else if (this.connection.rejoinAttempts < 5) {\n // Try to rejoin\n setTimeout(\n () => {\n this.connection.rejoin();\n },\n (this.connection.rejoinAttempts + 1) * 5e3,\n ).unref();\n } else if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) {\n // Leave after 5 attempts\n this.leave(new DisTubeError(\"VOICE_RECONNECT_FAILED\"));\n }\n })\n .on(VoiceConnectionStatus.Destroyed, () => {\n this.leave();\n })\n .on(\"error\", () => undefined);\n this.connection.subscribe(this.audioPlayer);\n /**\n * Get or set the volume percentage\n */\n }\n #br() {\n if (this.audioResource?.encoder?.encoder) this.audioResource.encoder.setBitrate(this.channel.bitrate);\n }\n /**\n * The voice channel id the bot is in\n */\n get channelId() {\n return this.connection?.joinConfig?.channelId ?? undefined;\n }\n get channel() {\n if (!this.channelId) return this.#channel;\n if (this.#channel?.id === this.channelId) return this.#channel;\n const channel = this.voices.client.channels.cache.get(this.channelId);\n if (!channel) return this.#channel;\n for (const type of Constants.VoiceBasedChannelTypes) {\n if (channel.type === type) {\n this.#channel = channel;\n return channel;\n }\n }\n return this.#channel;\n }\n set channel(channel: VoiceBasedChannel) {\n if (!isSupportedVoiceChannel(channel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"BaseGuildVoiceChannel\", channel, \"DisTubeVoice#channel\");\n }\n if (channel.guildId !== this.id) throw new DisTubeError(\"VOICE_DIFFERENT_GUILD\");\n if (channel.client.user?.id !== this.voices.client.user?.id) throw new DisTubeError(\"VOICE_DIFFERENT_CLIENT\");\n if (channel.id === this.channelId) return;\n if (!channel.joinable) {\n if (channel.full) throw new DisTubeError(\"VOICE_FULL\");\n else throw new DisTubeError(\"VOICE_MISSING_PERMS\");\n }\n this.connection = this.#join(channel);\n this.#channel = channel;\n this.#br();\n }\n #join(channel: VoiceBasedChannel) {\n return joinVoiceChannel({\n channelId: channel.id,\n guildId: this.id,\n adapterCreator: channel.guild.voiceAdapterCreator,\n group: channel.client.user?.id,\n });\n }\n /**\n * Join a voice channel with this connection\n *\n * @param channel - A voice channel\n */\n async join(channel?: VoiceBasedChannel): Promise<DisTubeVoice> {\n const TIMEOUT = 30e3;\n if (channel) this.channel = channel;\n try {\n await entersState(this.connection, VoiceConnectionStatus.Ready, TIMEOUT);\n } catch {\n if (this.connection.state.status === VoiceConnectionStatus.Ready) return this;\n if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) this.connection.destroy();\n this.voices.remove(this.id);\n throw new DisTubeError(\"VOICE_CONNECT_FAILED\", TIMEOUT / 1e3);\n }\n return this;\n }\n /**\n * Leave the voice channel of this connection\n *\n * @param error - Optional, an error to emit with 'error' event.\n */\n leave(error?: Error) {\n this.stop(true);\n if (!this.isDisconnected) {\n this.emit(\"disconnect\", error);\n this.isDisconnected = true;\n }\n if (this.connection.state.status !== VoiceConnectionStatus.Destroyed) this.connection.destroy();\n this.voices.remove(this.id);\n }\n /**\n * Stop the playing stream\n *\n * @param force - If true, will force the {@link DisTubeVoice#audioPlayer} to enter the Idle state even\n * if the {@link DisTubeVoice#audioResource} has silence padding frames.\n */\n stop(force = false) {\n this.audioPlayer.stop(force);\n this.stream?.kill?.();\n }\n /**\n * Play a {@link DisTubeStream}\n *\n * @param dtStream - DisTubeStream\n */\n play(dtStream: DisTubeStream) {\n this.emittedError = false;\n dtStream.on(\"error\", (error: NodeJS.ErrnoException) => {\n if (this.emittedError || error.code === \"ERR_STREAM_PREMATURE_CLOSE\") return;\n this.emittedError = true;\n this.emit(\"error\", error);\n });\n this.audioResource = createAudioResource(dtStream.stream, {\n inputType: dtStream.type,\n inlineVolume: true,\n });\n this.volume = this.#volume;\n if (this.audioPlayer.state.status !== AudioPlayerStatus.Paused) this.audioPlayer.play(this.audioResource);\n this.stream?.kill?.();\n this.stream = dtStream;\n }\n set volume(volume: number) {\n if (typeof volume !== \"number\" || isNaN(volume)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"number\", volume, \"volume\");\n }\n if (volume < 0) {\n throw new DisTubeError(\"NUMBER_COMPARE\", \"Volume\", \"bigger or equal to\", 0);\n }\n this.#volume = volume;\n this.audioResource?.volume?.setVolume(Math.pow(this.#volume / 100, 0.5 / Math.log10(2)));\n }\n get volume() {\n return this.#volume;\n }\n /**\n * Playback duration of the audio resource in seconds\n */\n get playbackDuration() {\n return (this.audioResource?.playbackDuration ?? 0) / 1000;\n }\n pause() {\n this.audioPlayer.pause();\n }\n unpause() {\n const state = this.audioPlayer.state;\n if (state.status !== AudioPlayerStatus.Paused) return;\n if (this.audioResource && state.resource !== this.audioResource) this.audioPlayer.play(this.audioResource);\n else this.audioPlayer.unpause();\n }\n /**\n * Whether the bot is self-deafened\n */\n get selfDeaf(): boolean {\n return this.connection.joinConfig.selfDeaf;\n }\n /**\n * Whether the bot is self-muted\n */\n get selfMute(): boolean {\n return this.connection.joinConfig.selfMute;\n }\n /**\n * Self-deafens/undeafens the bot.\n *\n * @param selfDeaf - Whether or not the bot should be self-deafened\n *\n * @returns true if the voice state was successfully updated, otherwise false\n */\n setSelfDeaf(selfDeaf: boolean): boolean {\n if (typeof selfDeaf !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", selfDeaf, \"selfDeaf\");\n }\n return this.connection.rejoin({\n ...this.connection.joinConfig,\n selfDeaf,\n });\n }\n /**\n * Self-mutes/unmutes the bot.\n *\n * @param selfMute - Whether or not the bot should be self-muted\n *\n * @returns true if the voice state was successfully updated, otherwise false\n */\n setSelfMute(selfMute: boolean): boolean {\n if (typeof selfMute !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", selfMute, \"selfMute\");\n }\n return this.connection.rejoin({\n ...this.connection.joinConfig,\n selfMute,\n });\n }\n /**\n * The voice state of this connection\n */\n get voiceState(): VoiceState | undefined {\n return this.channel?.guild?.members?.me?.voice;\n }\n}\n","import { PassThrough } from \"node:stream\";\nimport { spawn, spawnSync } from \"child_process\";\nimport { TypedEmitter } from \"tiny-typed-emitter\";\nimport { DisTubeError, Events, StreamType, isURL } from \"..\";\nimport { StreamType as DiscordVoiceStreamType } from \"@discordjs/voice\";\nimport type { ChildProcess } from \"child_process\";\nimport type { Awaitable, DisTube, FFmpegArgs, FFmpegOptions, Song } from \"..\";\n\ninterface StreamOptions {\n ffmpeg: FFmpegOptions;\n seek?: number;\n type?: StreamType;\n}\n\nexport const chooseBestVideoFormat = ({ duration, formats, isLive }: Song) =>\n formats &&\n formats\n .filter(f => f.hasAudio && (duration < 10 * 60 || f.hasVideo) && (!isLive || f.isHLS))\n .sort((a, b) => Number(b.audioBitrate) - Number(a.audioBitrate) || Number(a.bitrate) - Number(b.bitrate))[0];\n\nlet checked = process.env.NODE_ENV === \"test\";\nexport const checkFFmpeg = (distube: DisTube) => {\n if (checked) return;\n const path = distube.options.ffmpeg.path;\n const debug = (str: string) => distube.emit(Events.FFMPEG_DEBUG, str);\n try {\n debug(`[test] spawn ffmpeg at '${path}' path`);\n const process = spawnSync(path, [\"-h\"], { windowsHide: true, shell: true, encoding: \"utf-8\" });\n if (process.error) throw process.error;\n if (process.stderr && !process.stdout) throw new Error(process.stderr);\n\n const result = process.output.join(\"\\n\");\n const version = /ffmpeg version (\\S+)/iu.exec(result)?.[1];\n if (!version) throw new Error(\"Invalid FFmpeg version\");\n debug(`[test] ffmpeg version: ${version}`);\n\n if (result.includes(\"--enable-libopus\")) {\n debug(\"[test] ffmpeg supports libopus\");\n } else {\n debug(\"[test] ffmpeg does not support libopus\");\n distube.options.streamType = StreamType.RAW;\n }\n } catch (e: any) {\n debug(`[test] failed to spawn ffmpeg at '${path}': ${e?.stack ?? e}`);\n throw new DisTubeError(\"FFMPEG_NOT_INSTALLED\", path);\n }\n checked = true;\n};\n\n/**\n * Create a stream to play with {@link DisTubeVoice}\n */\nexport class DisTubeStream extends TypedEmitter<{\n debug: (debug: string) => Awaitable;\n error: (error: Error) => Awaitable;\n}> {\n private killed = false;\n process: ChildProcess;\n stream: PassThrough;\n type: DiscordVoiceStreamType;\n url: string;\n /**\n * Create a DisTubeStream to play with {@link DisTubeVoice}\n *\n * @param url - Stream URL\n * @param options - Stream options\n */\n constructor(url: string, { ffmpeg, seek, type }: StreamOptions) {\n super();\n this.url = url;\n this.type = !type ? DiscordVoiceStreamType.OggOpus : DiscordVoiceStreamType.Raw;\n const opts: FFmpegArgs = {\n reconnect: 1,\n reconnect_streamed: 1,\n reconnect_delay_max: 5,\n analyzeduration: 0,\n hide_banner: true,\n ...ffmpeg.args.global,\n ...ffmpeg.args.input,\n i: url,\n ar: 48000,\n ac: 2,\n ...ffmpeg.args.output,\n };\n\n if (!type) {\n opts.f = \"opus\";\n opts.acodec = \"libopus\";\n } else {\n opts.f = \"s16le\";\n }\n if (typeof seek === \"number\" && seek > 0) opts.ss = seek.toString();\n\n if (typeof ffmpeg.args === \"object\") Object.assign(opts, ffmpeg.args);\n\n this.process = spawn(\n ffmpeg.path,\n [\n ...Object.entries(opts)\n .flatMap(([key, value]) =>\n Array.isArray(value)\n ? value.filter(Boolean).map(v => [`-${key}`, String(v)])\n : value == null || value === false\n ? []\n : [value === true ? `-${key}` : [`-${key}`, String(value)]],\n )\n .flat(),\n \"pipe:1\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false, windowsHide: true },\n )\n .on(\"error\", err => {\n this.debug(`[process] error: ${err.message}`);\n this.emit(\"error\", err);\n })\n .on(\"exit\", (code, signal) => {\n this.debug(`[process] exit: code=${code ?? \"unknown\"} signal=${signal ?? \"unknown\"}`);\n if (!code || [0, 255].includes(code)) return;\n this.debug(`[process] error: ffmpeg exited with code ${code}`);\n this.emit(\"error\", new DisTubeError(\"FFMPEG_EXITED\", code));\n });\n\n if (!this.process.stdout || !this.process.stderr) {\n this.kill();\n throw new Error(\"Failed to create ffmpeg process\");\n }\n\n this.stream = new PassThrough();\n this.stream\n .on(\"close\", () => this.kill())\n .on(\"error\", err => {\n this.debug(`[stream] error: ${err.message}`);\n this.emit(\"error\", err);\n })\n .on(\"finish\", () => this.debug(\"[stream] log: stream finished\"));\n this.process.stdout.pipe(this.stream);\n\n this.process.stderr.setEncoding(\"utf8\")?.on(\"data\", (data: string) => {\n const lines = data.split(/\\r\\n|\\r|\\n/u);\n for (const line of lines) {\n if (/^\\s*$/.test(line)) continue;\n this.debug(`[ffmpeg] log: ${line}`);\n }\n });\n }\n\n private debug(debug: string) {\n this.emit(\"debug\", debug);\n }\n\n kill() {\n if (this.killed) return;\n this.process.kill(\"SIGKILL\");\n this.killed = true;\n }\n /**\n * Create a stream from a YouTube {@link Song}\n *\n * @param song - A YouTube Song\n * @param options - options\n */\n static YouTube(song: Song, options: StreamOptions): DisTubeStream {\n if (song.source !== \"youtube\") throw new DisTubeError(\"INVALID_TYPE\", \"youtube\", song.source, \"Song#source\");\n if (!song.formats?.length) throw new DisTubeError(\"UNAVAILABLE_VIDEO\");\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n }\n const bestFormat = chooseBestVideoFormat(song);\n if (!bestFormat) throw new DisTubeError(\"UNPLAYABLE_FORMATS\");\n return new DisTubeStream(bestFormat.url, options);\n }\n /**\n * Create a stream from a stream url\n *\n * @param url - stream url\n * @param options - options\n */\n static DirectLink(url: string, options: StreamOptions): DisTubeStream {\n if (typeof url !== \"string\" || !isURL(url)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"an URL\", url);\n }\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n }\n return new DisTubeStream(url, options);\n }\n}\n","import ytpl from \"@distube/ytpl\";\nimport ytdl from \"@distube/ytdl-core\";\nimport { DisTubeBase } from \".\";\nimport { Cookie } from \"tough-cookie\";\nimport {\n DisTubeError,\n Events,\n Playlist,\n Queue,\n SearchResultPlaylist,\n SearchResultVideo,\n Song,\n isMessageInstance,\n isNsfwChannel,\n isObject,\n isTruthy,\n isURL,\n isVoiceChannelEmpty,\n} from \"..\";\nimport type { Message, VoiceBasedChannel } from \"discord.js\";\nimport type {\n DisTube,\n OtherSongInfo,\n PlayHandlerOptions,\n ResolveOptions,\n ResolvePlaylistOptions,\n SearchResult,\n} from \"..\";\n\n/**\n * DisTube's Handler\n */\nexport class DisTubeHandler extends DisTubeBase {\n #cookie: ytdl.Cookie[] | string = \"\";\n constructor(distube: DisTube) {\n super(distube);\n\n const client = this.client;\n if (this.options.leaveOnEmpty) {\n client.on(\"voiceStateUpdate\", oldState => {\n if (!oldState?.channel) return;\n const queue = this.queues.get(oldState);\n if (!queue) {\n if (isVoiceChannelEmpty(oldState)) {\n setTimeout(() => {\n if (!this.queues.get(oldState) && isVoiceChannelEmpty(oldState)) this.voices.leave(oldState);\n }, this.options.emptyCooldown * 1e3).unref();\n }\n return;\n }\n if (queue._emptyTimeout) {\n clearTimeout(queue._emptyTimeout);\n delete queue._emptyTimeout;\n }\n if (isVoiceChannelEmpty(oldState)) {\n queue._emptyTimeout = setTimeout(() => {\n delete queue._emptyTimeout;\n if (isVoiceChannelEmpty(oldState)) {\n queue.voice.leave();\n this.emit(Events.EMPTY, queue);\n if (queue.stopped) queue.remove();\n }\n }, this.options.emptyCooldown * 1e3).unref();\n }\n });\n }\n }\n\n get ytdlOptions(): ytdl.getInfoOptions {\n const options = this.options.ytdlOptions;\n if (this.options.youtubeCookie && this.options.youtubeCookie !== this.#cookie) {\n const cookies = (this.#cookie = this.options.youtubeCookie);\n if (typeof cookies === \"string\") {\n // eslint-disable-next-line no-console\n console.warn(\n \"\\x1b[33mWARNING:\\x1B[0m You are using the old YouTube cookie format, \" +\n \"please use the new one instead. (https://github.com/skick1234/DisTube/wiki/YouTube-Cookies)\",\n );\n options.agent = ytdl.createAgent(\n cookies\n .split(\";\")\n .map(c => Cookie.parse(c))\n .filter(isTruthy),\n );\n } else {\n options.agent = ytdl.createAgent(cookies);\n }\n }\n return options;\n }\n\n get ytCookie(): string {\n const agent = this.ytdlOptions.agent;\n if (!agent) return \"\";\n const { jar } = agent;\n return jar.getCookieStringSync(\"https://www.youtube.com\");\n }\n\n /**\n * @param url - url\n * @param basic - getBasicInfo?\n */\n getYouTubeInfo(url: string, basic = false): Promise<ytdl.videoInfo> {\n if (basic) return ytdl.getBasicInfo(url, this.ytdlOptions);\n return ytdl.getInfo(url, this.ytdlOptions);\n }\n\n resolve<T = unknown>(song: Song<T>, options?: Omit<ResolveOptions, \"metadata\">): Promise<Song<T>>;\n resolve<T = unknown>(song: Playlist<T>, options?: Omit<ResolveOptions, \"metadata\">): Promise<Playlist<T>>;\n resolve<T = unknown>(song: string | SearchResult, options?: ResolveOptions<T>): Promise<Song<T> | Playlist<T>>;\n resolve<T = unknown>(\n song: ytdl.videoInfo | OtherSongInfo | ytdl.relatedVideo,\n options?: ResolveOptions<T>,\n ): Promise<Song<T>>;\n resolve<T = unknown>(song: Playlist, options: ResolveOptions<T>): Promise<Playlist<T>>;\n resolve(\n song: string | ytdl.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl.relatedVideo,\n options?: ResolveOptions,\n ): Promise<Song | Playlist>;\n /**\n * Resolve a url or a supported object to a {@link Song} or {@link Playlist}\n *\n * @throws {@link DisTubeError}\n *\n * @param song - URL | {@link Song}| {@link SearchResult} | {@link Playlist}\n * @param options - Optional options\n *\n * @returns Resolved\n */\n async resolve(\n song: string | ytdl.videoInfo | Song | Playlist | SearchResult | OtherSongInfo | ytdl.relatedVideo,\n options: ResolveOptions = {},\n ): Promise<Song | Playlist> {\n if (song instanceof Song || song instanceof Playlist) {\n if (\"metadata\" in options) song.metadata = options.metadata;\n if (\"member\" in options) song.member = options.member;\n return song;\n }\n if (song instanceof SearchResultVideo) return new Song(song, options);\n if (song instanceof SearchResultPlaylist) return this.resolvePlaylist(song.url, options);\n if (isObject(song)) {\n if (!(\"url\" in song) && !(\"id\" in song)) throw new DisTubeError(\"CANNOT_RESOLVE_SONG\", song);\n return new Song(song, options);\n }\n if (ytpl.validateID(song)) return this.resolvePlaylist(song, options);\n if (ytdl.validateURL(song)) return new Song(await this.getYouTubeInfo(song, true), options);\n if (isURL(song)) {\n for (const plugin of this.distube.extractorPlugins) {\n if (await plugin.validate(song)) return plugin.resolve(song, options);\n }\n throw new DisTubeError(\"NOT_SUPPORTED_URL\");\n }\n throw new DisTubeError(\"CANNOT_RESOLVE_SONG\", song);\n }\n\n resolvePlaylist<T = unknown>(\n playlist: Playlist<T> | Song<T>[] | string,\n options?: Omit<ResolvePlaylistOptions, \"metadata\">,\n ): Promise<Playlist<T>>;\n resolvePlaylist<T = undefined>(\n playlist: Playlist | Song[] | string,\n options: ResolvePlaylistOptions<T>,\n ): Promise<Playlist<T>>;\n resolvePlaylist(playlist: Playlist | Song[] | string, options?: ResolvePlaylistOptions): Promise<Playlist>;\n /**\n * Resolve Song[] or YouTube playlist url to a Playlist\n *\n * @param playlist - Resolvable playlist\n * @param options - Optional options\n */\n async resolvePlaylist(playlist: Playlist | Song[] | string, options: ResolvePlaylistOptions = {}): Promise<Playlist> {\n const { member, source, metadata } = { source: \"youtube\", ...options };\n if (playlist instanceof Playlist) {\n if (\"metadata\" in options) playlist.metadata = metadata;\n if (\"member\" in options) playlist.member = member;\n return playlist;\n }\n if (typeof playlist === \"string\") {\n const info = await ytpl(playlist, { limit: Infinity, requestOptions: { headers: { cookie: this.ytCookie } } });\n const songs = info.items\n .filter(v => !v.thumbnail.includes(\"no_thumbnail\"))\n .map(v => new Song(v, { member, metadata }));\n return new Playlist(\n {\n source,\n songs,\n member,\n name: info.title,\n url: info.url,\n thumbnail: songs[0].thumbnail,\n },\n { metadata },\n );\n }\n return new Playlist(playlist, { member, properties: { source }, metadata });\n }\n\n /**\n * Search for a song, fire {@link DisTube#error} if not found.\n *\n * @throws {@link DisTubeError}\n *\n * @param message - The original message from an user\n * @param query - The query string\n *\n * @returns Song info\n */\n async searchSong(message: Message<true>, query: string): Promise<SearchResult | null> {\n if (!isMessageInstance(message)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Message\", message, \"message\");\n if (typeof query !== \"string\") throw new DisTubeError(\"INVALID_TYPE\", \"string\", query, \"query\");\n if (query.length === 0) throw new DisTubeError(\"EMPTY_STRING\", \"query\");\n const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;\n const results = await this.distube\n .search(query, {\n limit,\n safeSearch: this.options.nsfw ? false : !isNsfwChannel(message.channel),\n })\n .catch(() => {\n if (!this.emit(Events.SEARCH_NO_RESULT, message, query)) {\n // eslint-disable-next-line no-console\n console.warn(\"searchNoResult event does not have any listeners! Emits `error` event instead.\");\n throw new DisTubeError(\"NO_RESULT\");\n }\n });\n if (!results) return null;\n return this.createSearchMessageCollector(message, results, query);\n }\n\n /**\n * Create a message collector for selecting search results.\n *\n * Needed events: {@link DisTube#searchResult}, {@link DisTube#searchCancel},\n * {@link DisTube#searchInvalidAnswer}, {@link DisTube#searchDone}.\n *\n * @throws {@link DisTubeError}\n *\n * @param message - The original message from an user\n * @param results - The search results\n * @param query - The query string\n *\n * @returns Selected result\n */\n async createSearchMessageCollector<R extends SearchResult | Song | Playlist>(\n message: Message<true>,\n results: Array<R>,\n query?: string,\n ): Promise<R | null> {\n if (!isMessageInstance(message)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Message\", message, \"message\");\n if (!Array.isArray(results) || results.length === 0) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Array<SearchResult|Song|Playlist>\", results, \"results\");\n }\n if (this.options.searchSongs > 1) {\n const searchEvents = [\n Events.SEARCH_NO_RESULT,\n Events.SEARCH_RESULT,\n Events.SEARCH_CANCEL,\n Events.SEARCH_INVALID_ANSWER,\n Events.SEARCH_DONE,\n ];\n for (const evn of searchEvents) {\n if (this.distube.listenerCount(evn) === 0) {\n /* eslint-disable no-console */\n console.warn(`\"searchSongs\" option is disabled due to missing \"${evn}\" listener.`);\n console.warn(\n `If you don't want to use \"${evn}\" event, simply add an empty listener (not recommended):\\n` +\n `<DisTube>.on(\"${evn}\", () => {})`,\n );\n /* eslint-enable no-console */\n this.options.searchSongs = 0;\n }\n }\n }\n const limit = this.options.searchSongs > 1 ? this.options.searchSongs : 1;\n let result = results[0];\n if (limit > 1) {\n results.splice(limit);\n this.emit(Events.SEARCH_RESULT, message, results, query);\n const answers = await message.channel\n .awaitMessages({\n filter: (m: Message) => m.author.id === message.author.id,\n max: 1,\n time: this.options.searchCooldown * 1e3,\n errors: [\"time\"],\n })\n .catch(() => undefined);\n const ans = answers?.first();\n if (!ans) {\n this.emit(Events.SEARCH_CANCEL, message, query);\n return null;\n }\n const index = parseInt(ans.content, 10);\n if (isNaN(index) || index > results.length || index < 1) {\n this.emit(Events.SEARCH_INVALID_ANSWER, message, ans, query);\n return null;\n }\n this.emit(Events.SEARCH_DONE, message, ans, query);\n result = results[index - 1];\n }\n return result;\n }\n\n /**\n * Play or add a {@link Playlist} to the queue.\n *\n * @throws {@link DisTubeError}\n *\n * @param voiceChannel - A voice channel\n * @param playlist - A YouTube playlist url | a Playlist\n * @param options - Optional options\n */\n async playPlaylist(\n voiceChannel: VoiceBasedChannel,\n playlist: Playlist,\n options: PlayHandlerOptions = {},\n ): Promise<void> {\n const { textChannel, skip } = { skip: false, ...options };\n const position = Number(options.position) || (skip ? 1 : 0);\n if (!(playlist instanceof Playlist)) throw new DisTubeError(\"INVALID_TYPE\", \"Playlist\", playlist, \"playlist\");\n\n const queue = this.queues.get(voiceChannel);\n\n const isNsfw = isNsfwChannel(queue?.textChannel || textChannel);\n if (!this.options.nsfw && !isNsfw) playlist.songs = playlist.songs.filter(s => !s.age_restricted);\n\n if (!playlist.songs.length) {\n if (!this.options.nsfw && !isNsfw) throw new DisTubeError(\"EMPTY_FILTERED_PLAYLIST\");\n throw new DisTubeError(\"EMPTY_PLAYLIST\");\n }\n if (queue) {\n if (this.options.joinNewVoiceChannel) queue.voice.channel = voiceChannel;\n queue.addToQueue(playlist.songs, position);\n if (skip) queue.skip();\n else this.emit(Events.ADD_LIST, queue, playlist);\n } else {\n const newQueue = await this.queues.create(voiceChannel, playlist.songs, textChannel);\n if (newQueue instanceof Queue) {\n if (this.options.emitAddListWhenCreatingQueue) this.emit(Events.ADD_LIST, newQueue, playlist);\n this.emit(Events.PLAY_SONG, newQueue, newQueue.songs[0]);\n }\n }\n }\n\n /**\n * Play or add a {@link Song} to the queue.\n *\n * @throws {@link DisTubeError}\n *\n * @param voiceChannel - A voice channel\n * @param song - A YouTube playlist url | a Playlist\n * @param options - Optional options\n */\n async playSong(voiceChannel: VoiceBasedChannel, song: Song, options: PlayHandlerOptions = {}): Promise<void> {\n if (!(song instanceof Song)) throw new DisTubeError(\"INVALID_TYPE\", \"Song\", song, \"song\");\n const { textChannel, skip } = { skip: false, ...options };\n const position = Number(options.position) || (skip ? 1 : 0);\n\n const queue = this.queues.get(voiceChannel);\n if (!this.options.nsfw && song.age_restricted && !isNsfwChannel(queue?.textChannel || textChannel)) {\n throw new DisTubeError(\"NON_NSFW\");\n }\n if (queue) {\n if (this.options.joinNewVoiceChannel) queue.voice.channel = voiceChannel;\n queue.addToQueue(song, position);\n if (skip) queue.skip();\n else this.emit(Events.ADD_SONG, queue, song);\n } else {\n const newQueue = await this.queues.create(voiceChannel, song, textChannel);\n if (newQueue instanceof Queue) {\n if (this.options.emitAddSongWhenCreatingQueue) this.emit(Events.ADD_SONG, newQueue, song);\n this.emit(Events.PLAY_SONG, newQueue, song);\n }\n }\n }\n\n /**\n * Get {@link Song}'s stream info and attach it to the song.\n *\n * @param song - A Song\n */\n async attachStreamInfo(song: Song) {\n const { url, source } = song;\n if (source === \"youtube\") {\n song._patchYouTube(await this.handler.getYouTubeInfo(url));\n } else {\n for (const plugin of [...this.distube.extractorPlugins, ...this.distube.customPlugins]) {\n if (await plugin.validate(url)) {\n const info = [plugin.getStreamURL(url), plugin.getRelatedSongs(url)] as const;\n const result = await Promise.all(info);\n song.streamURL = result[0];\n song.related = result[1];\n break;\n }\n }\n }\n }\n}\n","import { DisTubeError, StreamType, checkInvalidKey, defaultOptions } from \"..\";\nimport type ytdl from \"@distube/ytdl-core\";\nimport type { Cookie } from \"@distube/ytdl-core\";\nimport type { CustomPlugin, DisTubeOptions, ExtractorPlugin, FFmpegArgs, FFmpegOptions, Filters } from \"..\";\n\nexport class Options {\n plugins: (CustomPlugin | ExtractorPlugin)[];\n emitNewSongOnly: boolean;\n leaveOnFinish: boolean;\n leaveOnStop: boolean;\n leaveOnEmpty: boolean;\n emptyCooldown: number;\n savePreviousSongs: boolean;\n searchSongs: number;\n searchCooldown: number;\n youtubeCookie?: Cookie[] | string;\n customFilters?: Filters;\n ytdlOptions: ytdl.getInfoOptions;\n nsfw: boolean;\n emitAddSongWhenCreatingQueue: boolean;\n emitAddListWhenCreatingQueue: boolean;\n joinNewVoiceChannel: boolean;\n streamType: StreamType;\n directLink: boolean;\n /** @deprecated */\n ffmpegPath: undefined = undefined;\n /** @deprecated */\n ffmpegDefaultArgs: undefined = undefined;\n ffmpeg: FFmpegOptions;\n constructor(options: DisTubeOptions) {\n if (typeof options !== \"object\" || Array.isArray(options)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"DisTubeOptions\");\n }\n const opts = { ...defaultOptions, ...options };\n this.plugins = opts.plugins;\n this.emitNewSongOnly = opts.emitNewSongOnly;\n this.leaveOnEmpty = opts.leaveOnEmpty;\n this.leaveOnFinish = opts.leaveOnFinish;\n this.leaveOnStop = opts.leaveOnStop;\n this.savePreviousSongs = opts.savePreviousSongs;\n this.searchSongs = opts.searchSongs;\n this.youtubeCookie = opts.youtubeCookie;\n this.customFilters = opts.customFilters;\n this.ytdlOptions = opts.ytdlOptions;\n this.searchCooldown = opts.searchCooldown;\n this.emptyCooldown = opts.emptyCooldown;\n this.nsfw = opts.nsfw;\n this.emitAddSongWhenCreatingQueue = opts.emitAddSongWhenCreatingQueue;\n this.emitAddListWhenCreatingQueue = opts.emitAddListWhenCreatingQueue;\n this.joinNewVoiceChannel = opts.joinNewVoiceChannel;\n this.streamType = opts.streamType;\n this.directLink = opts.directLink;\n this.ffmpeg = this.#ffmpegOption(options);\n checkInvalidKey(opts, this, \"DisTubeOptions\");\n this.#validateOptions();\n }\n\n #validateOptions(options = this) {\n const booleanOptions = new Set([\n \"emitNewSongOnly\",\n \"leaveOnEmpty\",\n \"leaveOnFinish\",\n \"leaveOnStop\",\n \"savePreviousSongs\",\n \"joinNewVoiceChannel\",\n \"nsfw\",\n \"emitAddSongWhenCreatingQueue\",\n \"emitAddListWhenCreatingQueue\",\n \"directLink\",\n ]);\n const numberOptions = new Set([\"searchCooldown\", \"emptyCooldown\", \"searchSongs\"]);\n const stringOptions = new Set();\n const objectOptions = new Set([\"customFilters\", \"ytdlOptions\", \"ffmpeg\"]);\n const optionalOptions = new Set([\"youtubeCookie\", \"customFilters\"]);\n\n for (const [key, value] of Object.entries(options)) {\n if (value === undefined && optionalOptions.has(key)) continue;\n if (key === \"youtubeCookie\" && !Array.isArray(value) && typeof value !== \"string\") {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Array<Cookie>\", \"string\"], value, `DisTubeOptions.${key}`);\n } else if (key === \"streamType\" && (typeof value !== \"number\" || isNaN(value) || !StreamType[value])) {\n throw new DisTubeError(\"INVALID_TYPE\", \"StreamType\", value, `DisTubeOptions.${key}`);\n } else if (key === \"plugins\" && !Array.isArray(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Array<Plugin>\", value, `DisTubeOptions.${key}`);\n } else if (booleanOptions.has(key)) {\n if (typeof value !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", value, `DisTubeOptions.${key}`);\n }\n } else if (numberOptions.has(key)) {\n if (typeof value !== \"number\" || isNaN(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"number\", value, `DisTubeOptions.${key}`);\n }\n } else if (stringOptions.has(key)) {\n if (typeof value !== \"string\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"string\", value, `DisTubeOptions.${key}`);\n }\n } else if (objectOptions.has(key)) {\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"object\", value, `DisTubeOptions.${key}`);\n }\n }\n }\n }\n\n #ffmpegOption(opts: DisTubeOptions) {\n let path: string;\n const args: {\n global: FFmpegArgs;\n input: FFmpegArgs;\n output: FFmpegArgs;\n } = { global: {}, input: {}, output: {} };\n /* eslint-disable deprecation/deprecation,no-console */\n if (opts.ffmpegPath) {\n console.warn(\"`DisTubeOptions.ffmpegPath` is deprecated. Use `ffmpeg.path` instead.\");\n path = opts.ffmpegPath;\n }\n if (opts.ffmpegDefaultArgs) {\n console.warn(\"`DisTubeOptions.ffmpegDefaultArgs` is deprecated. Use `ffmpeg.args` instead.\");\n args.global = opts.ffmpegDefaultArgs;\n }\n /* eslint-enable deprecation/deprecation,no-console */\n path ??= opts.ffmpeg?.path ?? `ffmpeg${process.platform === \"win32\" ? \".exe\" : \"\"}`;\n if (opts.ffmpeg?.args) {\n if (opts.ffmpeg.args.global) args.global = opts.ffmpeg.args.global;\n if (opts.ffmpeg.args.input) args.input = opts.ffmpeg.args.input;\n if (opts.ffmpeg.args.output) args.output = opts.ffmpeg.args.output;\n }\n return { path, args };\n }\n}\n","import { DisTubeBase } from \"..\";\nimport { Collection } from \"discord.js\";\n\n/**\n * Manages the collection of a data model.\n *\n * @virtual\n */\nexport abstract class BaseManager<V> extends DisTubeBase {\n /**\n * The collection of items for this manager.\n */\n collection = new Collection<string, V>();\n /**\n * The size of the collection.\n */\n get size() {\n return this.collection.size;\n }\n}\n","import { BaseManager } from \".\";\nimport { resolveGuildId } from \"../..\";\nimport type { GuildIdResolvable } from \"../..\";\n\n/**\n * Manages the collection of a data model paired with a guild id.\n *\n * @virtual\n */\nexport abstract class GuildIdManager<V> extends BaseManager<V> {\n add(idOrInstance: GuildIdResolvable, data: V) {\n const id = resolveGuildId(idOrInstance);\n const existing = this.get(id);\n if (existing) return this;\n this.collection.set(id, data);\n return this;\n }\n get(idOrInstance: GuildIdResolvable): V | undefined {\n return this.collection.get(resolveGuildId(idOrInstance));\n }\n remove(idOrInstance: GuildIdResolvable): boolean {\n return this.collection.delete(resolveGuildId(idOrInstance));\n }\n has(idOrInstance: GuildIdResolvable): boolean {\n return this.collection.has(resolveGuildId(idOrInstance));\n }\n}\n","import { DisTubeVoice } from \"../DisTubeVoice\";\nimport { resolveGuildId } from \"../..\";\nimport { GuildIdManager } from \".\";\nimport { VoiceConnectionStatus, getVoiceConnection } from \"@discordjs/voice\";\nimport type { GuildIdResolvable } from \"../..\";\nimport type { VoiceBasedChannel } from \"discord.js\";\n\n/**\n * Manages voice connections for {@link DisTube}\n */\nexport class DisTubeVoiceManager extends GuildIdManager<DisTubeVoice> {\n /**\n * Get a {@link DisTubeVoice}.\n *\n * @param guild - The queue resolvable to resolve\n */\n /**\n * Collection of {@link DisTubeVoice}.\n */\n /**\n * Create a {@link DisTubeVoice}\n *\n * @param channel - A voice channel to join\n */\n create(channel: VoiceBasedChannel): DisTubeVoice {\n const existing = this.get(channel.guildId);\n if (existing) {\n existing.channel = channel;\n return existing;\n }\n return new DisTubeVoice(this, channel);\n }\n /**\n * Join a voice channel\n *\n * @param channel - A voice channel to join\n */\n join(channel: VoiceBasedChannel): Promise<DisTubeVoice> {\n const existing = this.get(channel.guildId);\n if (existing) return existing.join(channel);\n return this.create(channel).join();\n }\n /**\n * Leave the connected voice channel in a guild\n *\n * @param guild - Queue Resolvable\n */\n leave(guild: GuildIdResolvable) {\n const voice = this.get(guild);\n if (voice) {\n voice.leave();\n } else {\n const connection =\n getVoiceConnection(resolveGuildId(guild), this.client.user?.id) ?? getVoiceConnection(resolveGuildId(guild));\n if (connection && connection.state.status !== VoiceConnectionStatus.Destroyed) {\n connection.destroy();\n }\n }\n }\n}\n","import { BaseManager } from \".\";\nimport { DisTubeError } from \"../..\";\nimport type { FFmpegArgs, Filter, FilterResolvable, Queue } from \"../..\";\n\n/**\n * Manage filters of a playing {@link Queue}\n */\nexport class FilterManager extends BaseManager<Filter> {\n /**\n * Collection of {@link Filter}.\n */\n queue: Queue;\n constructor(queue: Queue) {\n super(queue.distube);\n this.queue = queue;\n }\n\n #resolve(filter: FilterResolvable): Filter {\n if (typeof filter === \"object\" && typeof filter.name === \"string\" && typeof filter.value === \"string\") {\n return filter;\n }\n if (typeof filter === \"string\" && Object.prototype.hasOwnProperty.call(this.distube.filters, filter)) {\n return {\n name: filter,\n value: this.distube.filters[filter],\n };\n }\n throw new DisTubeError(\"INVALID_TYPE\", \"FilterResolvable\", filter, \"filter\");\n }\n\n #apply() {\n this.queue.beginTime = this.queue.currentTime;\n this.queues.playSong(this.queue);\n }\n\n /**\n * Enable a filter or multiple filters to the manager\n *\n * @param filterOrFilters - The filter or filters to enable\n * @param override - Wether or not override the applied filter with new filter value\n */\n add(filterOrFilters: FilterResolvable | FilterResolvable[], override = false) {\n if (Array.isArray(filterOrFilters)) {\n for (const filter of filterOrFilters) {\n const ft = this.#resolve(filter);\n if (override || !this.has(ft)) this.collection.set(ft.name, ft);\n }\n } else {\n const ft = this.#resolve(filterOrFilters);\n if (override || !this.has(ft)) this.collection.set(ft.name, ft);\n }\n this.#apply();\n return this;\n }\n\n /**\n * Clear enabled filters of the manager\n */\n clear() {\n return this.set([]);\n }\n\n /**\n * Set the filters applied to the manager\n *\n * @param filters - The filters to apply\n */\n set(filters: FilterResolvable[]) {\n if (!Array.isArray(filters)) throw new DisTubeError(\"INVALID_TYPE\", \"Array<FilterResolvable>\", filters, \"filters\");\n this.collection.clear();\n for (const f of filters) {\n const filter = this.#resolve(f);\n this.collection.set(filter.name, filter);\n }\n this.#apply();\n return this;\n }\n\n #removeFn(f: FilterResolvable) {\n return this.collection.delete(this.#resolve(f).name);\n }\n\n /**\n * Disable a filter or multiple filters\n *\n * @param filterOrFilters - The filter or filters to disable\n */\n remove(filterOrFilters: FilterResolvable | FilterResolvable[]) {\n if (Array.isArray(filterOrFilters)) filterOrFilters.forEach(f => this.#removeFn(f));\n else this.#removeFn(filterOrFilters);\n this.#apply();\n return this;\n }\n\n /**\n * Check whether a filter enabled or not\n *\n * @param filter - The filter to check\n */\n has(filter: FilterResolvable) {\n return this.collection.has(typeof filter === \"string\" ? filter : this.#resolve(filter).name);\n }\n\n /**\n * Array of enabled filter names\n */\n get names(): string[] {\n return [...this.collection.keys()];\n }\n\n /**\n * Array of enabled filters\n */\n get values(): Filter[] {\n return [...this.collection.values()];\n }\n\n get ffmpegArgs(): FFmpegArgs {\n return this.size ? { af: this.values.map(f => f.value).join(\",\") } : {};\n }\n\n override toString() {\n return this.names.toString();\n }\n}\n","import { GuildIdManager } from \".\";\nimport { DisTubeError, DisTubeStream, Events, Queue, RepeatMode, checkFFmpeg, objectKeys } from \"../..\";\nimport type { Song } from \"../..\";\nimport type { GuildTextBasedChannel, VoiceBasedChannel } from \"discord.js\";\n\n/**\n * Queue manager\n */\nexport class QueueManager extends GuildIdManager<Queue> {\n /**\n * Collection of {@link Queue}.\n */\n\n /**\n * Create a {@link Queue}\n *\n * @param channel - A voice channel\n * @param song - First song\n * @param textChannel - Default text channel\n *\n * @returns Returns `true` if encounter an error\n */\n async create(\n channel: VoiceBasedChannel,\n song: Song[] | Song,\n textChannel?: GuildTextBasedChannel,\n ): Promise<Queue | true> {\n if (this.has(channel.guildId)) throw new DisTubeError(\"QUEUE_EXIST\");\n const voice = this.voices.create(channel);\n const queue = new Queue(this.distube, voice, song, textChannel);\n await queue._taskQueue.queuing();\n try {\n checkFFmpeg(this.distube);\n await voice.join();\n this.#voiceEventHandler(queue);\n this.add(queue.id, queue);\n this.emit(Events.INIT_QUEUE, queue);\n const err = await this.playSong(queue);\n return err || queue;\n } finally {\n queue._taskQueue.resolve();\n }\n }\n\n /**\n * Get a Queue from this QueueManager.\n *\n * @param guild - Resolvable thing from a guild\n */\n\n /**\n * Listen to DisTubeVoice events and handle the Queue\n *\n * @param queue - Queue\n */\n #voiceEventHandler(queue: Queue) {\n queue._listeners = {\n disconnect: error => {\n queue.remove();\n this.emit(Events.DISCONNECT, queue);\n if (error) this.emitError(error, queue.textChannel);\n },\n error: error => this.#handlePlayingError(queue, error),\n finish: () => this.#handleSongFinish(queue),\n };\n for (const event of objectKeys(queue._listeners)) {\n queue.voice.on(event, queue._listeners[event]);\n }\n }\n\n /**\n * Whether or not emit playSong event\n *\n * @param queue - Queue\n */\n #emitPlaySong(queue: Queue): boolean {\n return (\n !this.options.emitNewSongOnly ||\n (queue.repeatMode === RepeatMode.SONG && queue._next) ||\n (queue.repeatMode !== RepeatMode.SONG && queue.songs[0]?.id !== queue.songs[1]?.id)\n );\n }\n\n /**\n * Handle the queue when a Song finish\n *\n * @param queue - queue\n */\n async #handleSongFinish(queue: Queue): Promise<void> {\n this.emit(Events.FINISH_SONG, queue, queue.songs[0]);\n await queue._taskQueue.queuing();\n try {\n if (queue.stopped) return;\n if (queue.repeatMode === RepeatMode.QUEUE && !queue._prev) queue.songs.push(queue.songs[0]);\n if (queue._prev) {\n if (queue.repeatMode === RepeatMode.QUEUE) queue.songs.unshift(queue.songs.pop() as Song);\n else queue.songs.unshift(queue.previousSongs.pop() as Song);\n }\n if (queue.songs.length <= 1 && (queue._next || queue.repeatMode === RepeatMode.DISABLED)) {\n if (queue.autoplay) {\n try {\n await queue.addRelatedSong();\n } catch {\n this.emit(Events.NO_RELATED, queue);\n }\n }\n if (queue.songs.length <= 1) {\n if (this.options.leaveOnFinish) queue.voice.leave();\n if (!queue.autoplay) this.emit(Events.FINISH, queue);\n queue.remove();\n return;\n }\n }\n const emitPlaySong = this.#emitPlaySong(queue);\n if (!queue._prev && (queue.repeatMode !== RepeatMode.SONG || queue._next)) {\n const prev = queue.songs.shift() as Song;\n delete prev.formats;\n delete prev.streamURL;\n if (this.options.savePreviousSongs) queue.previousSongs.push(prev);\n else queue.previousSongs.push({ id: prev.id } as Song);\n }\n queue._next = queue._prev = false;\n queue.beginTime = 0;\n const err = await this.playSong(queue);\n if (!err && emitPlaySong) this.emit(Events.PLAY_SONG, queue, queue.songs[0]);\n } finally {\n queue._taskQueue.resolve();\n }\n }\n\n /**\n * Handle error while playing\n *\n * @param queue - queue\n * @param error - error\n */\n #handlePlayingError(queue: Queue, error: Error) {\n const song = queue.songs.shift() as Song;\n try {\n error.name = \"PlayingError\";\n error.message = `${error.message}\\nId: ${song.id}\\nName: ${song.name}`;\n } catch {\n // Emit original error\n }\n this.emitError(error, queue.textChannel);\n if (queue.songs.length > 0) {\n queue._next = queue._prev = false;\n queue.beginTime = 0;\n this.playSong(queue).then(e => {\n if (!e) this.emit(Events.PLAY_SONG, queue, queue.songs[0]);\n });\n } else {\n queue.stop();\n }\n }\n\n /**\n * Create a ytdl stream\n *\n * @param queue - Queue\n */\n createStream(queue: Queue): DisTubeStream {\n const song = queue.songs[0];\n const { duration, source, streamURL } = song;\n const streamOptions = {\n ffmpeg: {\n path: this.options.ffmpeg.path,\n args: {\n global: { ...this.options.ffmpeg.args.global },\n input: { ...this.options.ffmpeg.args.input },\n output: { ...this.options.ffmpeg.args.output, ...queue.filters.ffmpegArgs },\n },\n },\n seek: duration ? queue.beginTime : undefined,\n type: this.options.streamType,\n };\n\n if (source === \"youtube\") return DisTubeStream.YouTube(song, streamOptions);\n if (!streamURL) throw new Error(\"No streamURL, something went wrong\");\n return DisTubeStream.DirectLink(streamURL, streamOptions);\n }\n\n /**\n * Play a song on voice connection\n *\n * @param queue - The guild queue\n *\n * @returns error?\n */\n async playSong(queue: Queue): Promise<boolean> {\n if (!queue) return true;\n if (queue.stopped || !queue.songs.length) {\n queue.stop();\n return true;\n }\n try {\n const song = queue.songs[0];\n await this.handler.attachStreamInfo(song);\n if (queue.stopped || !queue.songs.length) {\n queue.stop();\n return true;\n }\n const stream = this.createStream(queue);\n stream.on(\"debug\", data => this.emit(Events.FFMPEG_DEBUG, `[${queue.id}]: ${data}`));\n queue.voice.play(stream);\n song.streamURL = stream.url;\n return false;\n } catch (e: any) {\n this.#handlePlayingError(queue, e);\n return true;\n }\n }\n}\n","import { DisTubeBase, FilterManager } from \"../core\";\nimport { DisTubeError, Events, RepeatMode, Song, TaskQueue, formatDuration, objectKeys } from \"..\";\nimport type { GuildTextBasedChannel, Snowflake } from \"discord.js\";\nimport type { DisTube, DisTubeVoice, DisTubeVoiceEvents } from \"..\";\n\n/**\n * Represents a queue.\n */\nexport class Queue extends DisTubeBase {\n readonly id: Snowflake;\n voice: DisTubeVoice;\n songs: Song[];\n previousSongs: Song[];\n stopped: boolean;\n _next: boolean;\n _prev: boolean;\n playing: boolean;\n paused: boolean;\n repeatMode: RepeatMode;\n autoplay: boolean;\n #filters: FilterManager;\n beginTime: number;\n textChannel?: GuildTextBasedChannel;\n _emptyTimeout?: NodeJS.Timeout;\n _taskQueue: TaskQueue;\n _listeners?: DisTubeVoiceEvents;\n /**\n * Create a queue for the guild\n *\n * @param distube - DisTube\n * @param voice - Voice connection\n * @param song - First song(s)\n * @param textChannel - Default text channel\n */\n constructor(distube: DisTube, voice: DisTubeVoice, song: Song | Song[], textChannel?: GuildTextBasedChannel) {\n super(distube);\n /**\n * Voice connection of this queue.\n */\n this.voice = voice;\n /**\n * Queue id (Guild id)\n */\n this.id = voice.id;\n /**\n * Get or set the stream volume. Default value: `50`.\n */\n this.volume = 50;\n /**\n * List of songs in the queue (The first one is the playing song)\n */\n this.songs = Array.isArray(song) ? [...song] : [song];\n /**\n * List of the previous songs.\n */\n this.previousSongs = [];\n /**\n * Whether stream is currently stopped.\n */\n this.stopped = false;\n /**\n * Whether or not the last song was skipped to next song.\n */\n this._next = false;\n /**\n * Whether or not the last song was skipped to previous song.\n */\n this._prev = false;\n /**\n * Whether or not the stream is currently playing.\n */\n this.playing = true;\n /**\n * Whether or not the stream is currently paused.\n */\n this.paused = false;\n /**\n * Type of repeat mode (`0` is disabled, `1` is repeating a song, `2` is repeating\n * all the queue). Default value: `0` (disabled)\n */\n this.repeatMode = RepeatMode.DISABLED;\n /**\n * Whether or not the autoplay mode is enabled. Default value: `false`\n */\n this.autoplay = false;\n this.#filters = new FilterManager(this);\n /**\n * What time in the song to begin (in seconds).\n */\n this.beginTime = 0;\n /**\n * The text channel of the Queue. (Default: where the first command is called).\n */\n this.textChannel = textChannel;\n /**\n * Timeout for checking empty channel\n */\n this._emptyTimeout = undefined;\n /**\n * Task queuing system\n */\n this._taskQueue = new TaskQueue();\n /**\n * DisTubeVoice listener\n */\n this._listeners = undefined;\n }\n /**\n * The client user as a `GuildMember` of this queue's guild\n */\n get clientMember() {\n return this.voice.channel.guild.members.me ?? undefined;\n }\n /**\n * The filter manager of the queue\n */\n get filters() {\n return this.#filters;\n }\n /**\n * Formatted duration string.\n */\n get formattedDuration() {\n return formatDuration(this.duration);\n }\n /**\n * Queue's duration.\n */\n get duration() {\n return this.songs.length ? this.songs.reduce((prev, next) => prev + next.duration, 0) : 0;\n }\n /**\n * What time in the song is playing (in seconds).\n */\n get currentTime() {\n return this.voice.playbackDuration + this.beginTime;\n }\n /**\n * Formatted {@link Queue#currentTime} string.\n */\n get formattedCurrentTime() {\n return formatDuration(this.currentTime);\n }\n /**\n * The voice channel playing in.\n */\n get voiceChannel() {\n return this.clientMember?.voice?.channel ?? null;\n }\n get volume() {\n return this.voice.volume;\n }\n set volume(value: number) {\n this.voice.volume = value;\n }\n /**\n * @throws {DisTubeError}\n *\n * @param song - Song to add\n * @param position - Position to add, \\<= 0 to add to the end of the queue\n *\n * @returns The guild queue\n */\n addToQueue(song: Song | Song[], position = 0): Queue {\n if (!song || (Array.isArray(song) && !song.length)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Song\", \"Array<Song>\"], song, \"song\");\n }\n if (typeof position !== \"number\" || !Number.isInteger(position)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"integer\", position, \"position\");\n }\n if (position <= 0) {\n if (Array.isArray(song)) this.songs.push(...song);\n else this.songs.push(song);\n } else if (Array.isArray(song)) {\n this.songs.splice(position, 0, ...song);\n } else {\n this.songs.splice(position, 0, song);\n }\n if (Array.isArray(song)) song.forEach(s => delete s.formats);\n else delete song.formats;\n return this;\n }\n /**\n * Pause the guild stream\n *\n * @returns The guild queue\n */\n pause(): Queue {\n if (this.paused) throw new DisTubeError(\"PAUSED\");\n this.playing = false;\n this.paused = true;\n this.voice.pause();\n return this;\n }\n /**\n * Resume the guild stream\n *\n * @returns The guild queue\n */\n resume(): Queue {\n if (this.playing) throw new DisTubeError(\"RESUMED\");\n this.playing = true;\n this.paused = false;\n this.voice.unpause();\n return this;\n }\n /**\n * Set the guild stream's volume\n *\n * @param percent - The percentage of volume you want to set\n *\n * @returns The guild queue\n */\n setVolume(percent: number): Queue {\n this.volume = percent;\n return this;\n }\n\n /**\n * Skip the playing song if there is a next song in the queue. <info>If {@link\n * Queue#autoplay} is `true` and there is no up next song, DisTube will add and\n * play a related song.</info>\n *\n * @returns The song will skip to\n */\n async skip(): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (this.songs.length <= 1) {\n if (this.autoplay) await this.addRelatedSong();\n else throw new DisTubeError(\"NO_UP_NEXT\");\n }\n const song = this.songs[1];\n this._next = true;\n this.voice.stop();\n return song;\n } finally {\n this._taskQueue.resolve();\n }\n }\n\n /**\n * Play the previous song if exists\n *\n * @returns The guild queue\n */\n async previous(): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (!this.options.savePreviousSongs) throw new DisTubeError(\"DISABLED_OPTION\", \"savePreviousSongs\");\n if (this.previousSongs?.length === 0 && this.repeatMode !== RepeatMode.QUEUE) {\n throw new DisTubeError(\"NO_PREVIOUS\");\n }\n const song =\n this.repeatMode === 2 ? this.songs[this.songs.length - 1] : this.previousSongs[this.previousSongs.length - 1];\n this._prev = true;\n this.voice.stop();\n return song;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Shuffle the queue's songs\n *\n * @returns The guild queue\n */\n async shuffle(): Promise<Queue> {\n await this._taskQueue.queuing();\n try {\n const playing = this.songs.shift();\n if (playing === undefined) return this;\n for (let i = this.songs.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [this.songs[i], this.songs[j]] = [this.songs[j], this.songs[i]];\n }\n this.songs.unshift(playing);\n return this;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Jump to the song position in the queue. The next one is 1, 2,... The previous\n * one is -1, -2,...\n * if `num` is invalid number\n *\n * @param position - The song position to play\n *\n * @returns The new Song will be played\n */\n async jump(position: number): Promise<Song> {\n await this._taskQueue.queuing();\n try {\n if (typeof position !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", position, \"position\");\n if (!position || position > this.songs.length || -position > this.previousSongs.length) {\n throw new DisTubeError(\"NO_SONG_POSITION\");\n }\n let nextSong: Song;\n if (position > 0) {\n const nextSongs = this.songs.splice(position - 1);\n if (this.options.savePreviousSongs) {\n this.previousSongs.push(...this.songs);\n } else {\n this.previousSongs.push(...this.songs.map(s => ({ id: s.id }) as Song));\n }\n this.songs = nextSongs;\n this._next = true;\n nextSong = nextSongs[1];\n } else if (!this.options.savePreviousSongs) {\n throw new DisTubeError(\"DISABLED_OPTION\", \"savePreviousSongs\");\n } else {\n this._prev = true;\n if (position !== -1) this.songs.unshift(...this.previousSongs.splice(position + 1));\n nextSong = this.previousSongs[this.previousSongs.length - 1];\n }\n this.voice.stop();\n return nextSong;\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Set the repeat mode of the guild queue.\n * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`\n *\n * @param mode - The repeat modes (toggle if `undefined`)\n *\n * @returns The new repeat mode\n */\n setRepeatMode(mode?: RepeatMode): RepeatMode {\n if (mode !== undefined && !Object.values(RepeatMode).includes(mode)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"RepeatMode\", \"undefined\"], mode, \"mode\");\n }\n if (mode === undefined) this.repeatMode = (this.repeatMode + 1) % 3;\n else if (this.repeatMode === mode) this.repeatMode = RepeatMode.DISABLED;\n else this.repeatMode = mode;\n return this.repeatMode;\n }\n /**\n * Set the playing time to another position\n *\n * @param time - Time in seconds\n *\n * @returns The guild queue\n */\n seek(time: number): Queue {\n if (typeof time !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", time, \"time\");\n if (isNaN(time) || time < 0) throw new DisTubeError(\"NUMBER_COMPARE\", \"time\", \"bigger or equal to\", 0);\n this.beginTime = time;\n this.queues.playSong(this);\n return this;\n }\n /**\n * Add a related song of the playing song to the queue\n *\n * @returns The added song\n */\n async addRelatedSong(): Promise<Song> {\n if (!this.songs?.[0]) throw new DisTubeError(\"NO_PLAYING\");\n const related = this.songs[0].related.find(v => !this.previousSongs.map(s => s.id).includes(v.id));\n if (!related || !(related instanceof Song)) throw new DisTubeError(\"NO_RELATED\");\n const song = await this.handler.resolve(related, { member: this.clientMember, metadata: related.metadata });\n if (!(song instanceof Song)) throw new DisTubeError(\"CANNOT_PLAY_RELATED\");\n this.addToQueue(song);\n return song;\n }\n /**\n * Stop the guild stream and delete the queue\n */\n async stop() {\n await this._taskQueue.queuing();\n try {\n this.playing = false;\n this.paused = false;\n this.stopped = true;\n if (this.options.leaveOnStop) this.voice.leave();\n else this.voice.stop();\n this.remove();\n } finally {\n this._taskQueue.resolve();\n }\n }\n /**\n * Remove the queue from the manager (This does not leave the voice channel even if\n * {@link DisTubeOptions | DisTubeOptions.leaveOnStop} is enabled)\n */\n remove() {\n this.stopped = true;\n this.songs = [];\n this.previousSongs = [];\n if (this._listeners) {\n for (const event of objectKeys(this._listeners)) {\n this.voice.removeListener(event, this._listeners[event]);\n }\n }\n this.queues.remove(this.id);\n this.emit(Events.DELETE_QUEUE, this);\n }\n /**\n * Toggle autoplay mode\n *\n * @returns Autoplay mode state\n */\n toggleAutoplay(): boolean {\n this.autoplay = !this.autoplay;\n return this.autoplay;\n }\n}\n","/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { Client, GuildTextBasedChannel } from \"discord.js\";\nimport type {\n Awaitable,\n DisTube,\n DisTubeEvents,\n DisTubeHandler,\n DisTubeVoiceManager,\n Options,\n PluginType,\n QueueManager,\n RelatedSong,\n} from \"..\";\n\n/**\n * DisTube Plugin\n *\n * @virtual\n */\nexport abstract class Plugin {\n abstract type: PluginType;\n distube!: DisTube;\n init(distube: DisTube) {\n /**\n * DisTube\n */\n this.distube = distube;\n }\n /**\n * Type of the plugin\n */\n /**\n * Emit an event to the {@link DisTube} class\n *\n * @param eventName - Event name\n * @param args - arguments\n */\n emit(eventName: keyof DisTubeEvents, ...args: any): boolean {\n return this.distube.emit(eventName, ...args);\n }\n /**\n * Emit error event to the {@link DisTube} class\n *\n * @param error - error\n * @param channel - Text channel where the error is encountered.\n */\n emitError(error: Error, channel?: GuildTextBasedChannel) {\n this.distube.emitError(error, channel);\n }\n /**\n * The queue manager\n */\n get queues(): QueueManager {\n return this.distube.queues;\n }\n /**\n * The voice manager\n */\n get voices(): DisTubeVoiceManager {\n return this.distube.voices;\n }\n /**\n * Discord.js client\n */\n get client(): Client {\n return this.distube.client;\n }\n /**\n * DisTube options\n */\n get options(): Options {\n return this.distube.options;\n }\n /**\n * DisTube handler\n */\n get handler(): DisTubeHandler {\n return this.distube.handler;\n }\n /**\n * Check if the string is working with this plugin\n *\n * @param _string - Input string\n */\n validate(_string: string): Awaitable<boolean> {\n return false;\n }\n /**\n * Get the stream url from {@link Song#url}. Returns {@link Song#url} by default.\n * Not needed if the plugin plays song from YouTube.\n *\n * @param url - Input url\n */\n getStreamURL(url: string): Awaitable<string> {\n return url;\n }\n /**\n * Get related songs from a supported url. {@link Song#member} should be\n * `undefined`. Not needed to add {@link Song#related} because it will be added\n * with this function later.\n *\n * @param _url - Input url\n */\n getRelatedSongs(_url: string): Awaitable<RelatedSong[]> {\n return [];\n }\n}\n","import { Plugin } from \".\";\nimport { PluginType } from \"..\";\nimport type { VoiceBasedChannel } from \"discord.js\";\nimport type { Awaitable, PlayOptions } from \"..\";\n\n/**\n * Custom Plugin\n *\n * @virtual\n */\nexport abstract class CustomPlugin extends Plugin {\n readonly type = PluginType.CUSTOM;\n abstract play(voiceChannel: VoiceBasedChannel, song: string, options: PlayOptions): Awaitable<void>;\n}\n\n/**\n * This method will be executed if the url is validated.\n *\n * @virtual\n *\n * @param voiceChannel - The voice channel will be joined\n * @param song - Validated `song`\n * @param options - Optional options\n */\n\n/**\n * Check if the string is working with this plugin\n *\n * @param string - String need to validate\n */\n","import { Plugin } from \".\";\nimport { PluginType } from \"..\";\nimport type { GuildMember } from \"discord.js\";\nimport type { Awaitable, Playlist, Song } from \"..\";\n\n/**\n * Extractor Plugin\n *\n * @virtual\n */\nexport abstract class ExtractorPlugin extends Plugin {\n readonly type = PluginType.EXTRACTOR;\n abstract resolve<T = unknown>(\n url: string,\n options: { member?: GuildMember; metadata?: T },\n ): Awaitable<Song<T> | Playlist<T>>;\n}\n\n/**\n * Resolve the validated url to a {@link Song} or a {@link Playlist}.\n *\n * @virtual\n *\n * @param url - URL\n * @param options - Optional options\n * @param options.member - Requested user\n * @param options.metadata - Metadata\n */\n\n/**\n * Check if the url is working with this plugin\n *\n * @param url - Input url\n */\n","import { URL } from \"url\";\nimport { DisTubeError, DisTubeVoice, Queue } from \".\";\nimport { Constants, GatewayIntentBits, IntentsBitField, SnowflakeUtil } from \"discord.js\";\nimport type { GuildIdResolvable } from \".\";\nimport type {\n Client,\n ClientOptions,\n Guild,\n GuildMember,\n GuildTextBasedChannel,\n Message,\n Snowflake,\n VoiceBasedChannel,\n VoiceState,\n} from \"discord.js\";\n\nconst formatInt = (int: number) => (int < 10 ? `0${int}` : int);\n\n/**\n * Format duration to string\n *\n * @param sec - Duration in seconds\n */\nexport function formatDuration(sec: number): string {\n if (!sec || !Number(sec)) return \"00:00\";\n const seconds = Math.floor(sec % 60);\n const minutes = Math.floor((sec % 3600) / 60);\n const hours = Math.floor(sec / 3600);\n if (hours > 0) return `${formatInt(hours)}:${formatInt(minutes)}:${formatInt(seconds)}`;\n if (minutes > 0) return `${formatInt(minutes)}:${formatInt(seconds)}`;\n return `00:${formatInt(seconds)}`;\n}\n/**\n * Convert formatted duration to seconds\n *\n * @param input - Formatted duration string\n */\nexport function toSecond(input: any): number {\n if (!input) return 0;\n if (typeof input !== \"string\") return Number(input) || 0;\n if (input.includes(\":\")) {\n const time = input.split(\":\").reverse();\n let seconds = 0;\n for (let i = 0; i < 3; i++) if (time[i]) seconds += Number(time[i].replace(/[^\\d.]+/g, \"\")) * Math.pow(60, i);\n if (time.length > 3) seconds += Number(time[3].replace(/[^\\d.]+/g, \"\")) * 24 * 60 * 60;\n return seconds;\n } else {\n return Number(input.replace(/[^\\d.]+/g, \"\")) || 0;\n }\n}\n/**\n * Parse number from input\n *\n * @param input - Any\n */\nexport function parseNumber(input: any): number {\n if (typeof input === \"string\") return Number(input.replace(/[^\\d.]+/g, \"\")) || 0;\n return Number(input) || 0;\n}\nconst SUPPORTED_PROTOCOL = [\"https:\", \"http:\", \"file:\"] as const;\n/**\n * Check if the string is an URL\n *\n * @param input - input\n */\nexport function isURL(input: any): input is `${(typeof SUPPORTED_PROTOCOL)[number]}//${string}` {\n if (typeof input !== \"string\" || input.includes(\" \")) return false;\n try {\n const url = new URL(input);\n if (!SUPPORTED_PROTOCOL.some(p => p === url.protocol)) return false;\n } catch {\n return false;\n }\n return true;\n}\n/**\n * Check if the Client has enough intents to using DisTube\n *\n * @param options - options\n */\nexport function checkIntents(options: ClientOptions): void {\n const intents = new IntentsBitField(options.intents);\n if (!intents.has(GatewayIntentBits.GuildVoiceStates)) throw new DisTubeError(\"MISSING_INTENTS\", \"GuildVoiceStates\");\n}\n\n/**\n * Check if the voice channel is empty\n *\n * @param voiceState - voiceState\n */\nexport function isVoiceChannelEmpty(voiceState: VoiceState): boolean {\n const guild = voiceState.guild;\n const clientId = voiceState.client.user?.id;\n if (!guild || !clientId) return false;\n const voiceChannel = guild.members.me?.voice?.channel;\n if (!voiceChannel) return false;\n const members = voiceChannel.members.filter(m => !m.user.bot);\n return !members.size;\n}\n\nexport function isSnowflake(id: any): id is Snowflake {\n try {\n return SnowflakeUtil.deconstruct(id).timestamp > SnowflakeUtil.epoch;\n } catch {\n return false;\n }\n}\n\nexport function isMemberInstance(member: any): member is GuildMember {\n return (\n Boolean(member) &&\n isSnowflake(member.id) &&\n isSnowflake(member.guild?.id) &&\n isSnowflake(member.user?.id) &&\n member.id === member.user.id\n );\n}\n\nexport function isTextChannelInstance(channel: any): channel is GuildTextBasedChannel {\n return (\n Boolean(channel) &&\n isSnowflake(channel.id) &&\n isSnowflake(channel.guildId || channel.guild?.id) &&\n Constants.TextBasedChannelTypes.includes(channel.type) &&\n typeof channel.send === \"function\" &&\n (typeof channel.nsfw === \"boolean\" || typeof channel.parent?.nsfw === \"boolean\")\n );\n}\n\nexport function isMessageInstance(message: any): message is Message<true> {\n // Simple check for using distube normally\n return (\n Boolean(message) &&\n isSnowflake(message.id) &&\n isSnowflake(message.guildId || message.guild?.id) &&\n isMemberInstance(message.member) &&\n isTextChannelInstance(message.channel) &&\n Constants.NonSystemMessageTypes.includes(message.type) &&\n message.member.id === message.author?.id\n );\n}\n\nexport function isSupportedVoiceChannel(channel: any): channel is VoiceBasedChannel {\n return (\n Boolean(channel) &&\n isSnowflake(channel.id) &&\n isSnowflake(channel.guildId || channel.guild?.id) &&\n Constants.VoiceBasedChannelTypes.includes(channel.type)\n );\n}\n\nexport function isGuildInstance(guild: any): guild is Guild {\n return Boolean(guild) && isSnowflake(guild.id) && isSnowflake(guild.ownerId) && typeof guild.name === \"string\";\n}\n\nexport function resolveGuildId(resolvable: GuildIdResolvable): Snowflake {\n let guildId: string | undefined;\n if (typeof resolvable === \"string\") {\n guildId = resolvable;\n } else if (isObject(resolvable)) {\n if (\"guildId\" in resolvable && resolvable.guildId) {\n guildId = resolvable.guildId;\n } else if (resolvable instanceof Queue || resolvable instanceof DisTubeVoice || isGuildInstance(resolvable)) {\n guildId = resolvable.id;\n } else if (\"guild\" in resolvable && isGuildInstance(resolvable.guild)) {\n guildId = resolvable.guild.id;\n }\n }\n if (!isSnowflake(guildId)) throw new DisTubeError(\"INVALID_TYPE\", \"GuildIdResolvable\", resolvable);\n return guildId;\n}\n\nexport function isClientInstance(client: any): client is Client {\n return Boolean(client) && typeof client.login === \"function\";\n}\n\nexport function checkInvalidKey(\n target: Record<string, any>,\n source: Record<string, any> | string[],\n sourceName: string,\n) {\n if (!isObject(target)) throw new DisTubeError(\"INVALID_TYPE\", \"object\", target, sourceName);\n const sourceKeys = Array.isArray(source) ? source : objectKeys(source);\n const invalidKey = objectKeys(target).find(key => !sourceKeys.includes(key));\n if (invalidKey) throw new DisTubeError(\"INVALID_KEY\", sourceName, invalidKey);\n}\n\nexport function isObject(obj: any): obj is object {\n return typeof obj === \"object\" && obj !== null && !Array.isArray(obj);\n}\n\nexport function isRecord<T = unknown>(obj: any): obj is Record<string, T> {\n return isObject(obj);\n}\n\ntype KeyOf<T> = T extends object ? (keyof T)[] : [];\nexport function objectKeys<T>(obj: T): KeyOf<T> {\n if (!isObject(obj)) return [] as KeyOf<T>;\n return Object.keys(obj) as KeyOf<T>;\n}\n\nexport function isNsfwChannel(channel?: GuildTextBasedChannel): boolean {\n if (!isTextChannelInstance(channel)) return false;\n if (channel.isThread()) return channel.parent?.nsfw ?? false;\n return channel.nsfw;\n}\n\ntype Falsy = undefined | null | false | 0 | \"\";\nexport const isTruthy = <T>(x: T | Falsy): x is T => Boolean(x);\n","import { request } from \"undici\";\nimport { ExtractorPlugin, Song } from \"..\";\nimport type { GuildMember } from \"discord.js\";\n\nexport class DirectLinkPlugin extends ExtractorPlugin {\n override async validate(url: string) {\n try {\n const headers = await request(url, { method: \"HEAD\" }).then(res => res.headers);\n const types = headers[\"content-type\"];\n const type = Array.isArray(types) ? types[0] : types;\n if ([\"audio/\", \"video/\", \"application/ogg\"].some(s => type?.startsWith(s))) return true;\n } catch {\n // invalid URL\n }\n return false;\n }\n\n resolve(url: string, options: { member?: GuildMember; metadata?: any } = {}) {\n const u = new URL(url);\n const name = u.pathname.split(\"/\").pop() || u.href;\n return new Song({ name, url, src: \"direct_link\" }, options);\n }\n}\n","import ytsr from \"@distube/ytsr\";\nimport { TypedEmitter } from \"tiny-typed-emitter\";\nimport {\n DirectLinkPlugin,\n DisTubeError,\n DisTubeHandler,\n DisTubeVoiceManager,\n Events,\n Options,\n Playlist,\n QueueManager,\n SearchResultPlaylist,\n SearchResultType,\n SearchResultVideo,\n Song,\n checkIntents,\n defaultFilters,\n isClientInstance,\n isMemberInstance,\n isMessageInstance,\n isObject,\n isSupportedVoiceChannel,\n isTextChannelInstance,\n isURL,\n} from \".\";\nimport type { Client, GuildTextBasedChannel, Message, VoiceBasedChannel } from \"discord.js\";\nimport type {\n Awaitable,\n CustomPlaylistOptions,\n CustomPlugin,\n DisTubeOptions,\n ExtractorPlugin,\n Filters,\n GuildIdResolvable,\n PlayOptions,\n Queue,\n SearchResult,\n TypedDisTubeEvents,\n} from \".\";\n\n// Cannot be `import` as it's not under TS root dir\n// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports\nexport const { version }: { version: string } = require(\"../package.json\");\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nexport interface DisTube extends TypedEmitter<TypedDisTubeEvents> {\n /**\n * @event\n * Emitted after DisTube add a new playlist to the playing {@link Queue}.\n *\n * @example\n * ```ts\n * distube.on(\"addList\", (queue, playlist) => queue.textChannel.send(\n * `Added \\`${playlist.name}\\` playlist (${playlist.songs.length} songs) to the queue!`\n * ));\n * ```\n *\n * @param queue - The guild queue\n * @param playlist - Playlist info\n */\n [Events.ADD_LIST]: (queue: Queue, playlist: Playlist) => Awaitable;\n /**\n * @event\n * Emitted after DisTube add a new song to the playing {@link Queue}.\n *\n * @example\n * ```ts\n * distube.on(\"addSong\", (queue, song) => queue.textChannel.send(\n * `Added ${song.name} - \\`${song.formattedDuration}\\` to the queue by ${song.user}.`\n * ));\n * ```\n *\n * @param queue - The guild queue\n * @param song - Added song\n */\n [Events.ADD_SONG]: (queue: Queue, song: Song) => Awaitable;\n /**\n * @event\n * Emitted when a {@link Queue} is deleted with any reasons.\n *\n * @param queue - The guild queue\n */\n [Events.DELETE_QUEUE]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when the bot is disconnected to a voice channel.\n *\n * @param queue - The guild queue\n */\n [Events.DISCONNECT]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when there is no user in the voice channel, {@link DisTubeOptions}.leaveOnEmpty\n * is `true` and there is a playing queue.\n *\n * If there is no playing queue (stopped and {@link DisTubeOptions}.leaveOnStop is\n * `false`), it will leave the channel without emitting this event.\n *\n * @example\n * ```ts\n * distube.on(\"empty\", queue => queue.textChannel.send(\"Channel is empty. Leaving the channel\"))\n * ```\n *\n * @param queue - The guild queue\n */\n [Events.EMPTY]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when DisTube encounters an error while playing songs.\n *\n * @example\n * ```ts\n * distube.on('error', (channel, e) => {\n * if (channel) channel.send(`An error encountered: ${e}`)\n * else console.error(e)\n * })\n * ```\n *\n * @param channel - Text channel where the error is encountered.\n * @param error - The error encountered\n */\n [Events.ERROR]: (channel: GuildTextBasedChannel | undefined, error: Error) => Awaitable;\n /**\n * @event\n * Emitted for FFmpeg debugging information.\n *\n * @param debug - The debug information\n */\n [Events.FFMPEG_DEBUG]: (debug: string) => Awaitable;\n /**\n * @event\n * Emitted when there is no more song in the queue and {@link Queue#autoplay} is\n * `false`. DisTube will leave voice channel if {@link\n * DisTubeOptions}.leaveOnFinish is `true`.\n *\n * @example\n * ```ts\n * distube.on(\"finish\", queue => queue.textChannel.send(\"No more song in queue\"));\n * ```\n *\n * @param queue - The guild queue\n */\n [Events.FINISH]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when DisTube finished a song.\n *\n * @example\n * ```ts\n * distube.on(\"finishSong\", (queue, song) => queue.textChannel.send(`${song.name} has finished!`));\n * ```\n *\n * @param queue - The guild queue\n * @param song - Finished song\n */\n [Events.FINISH_SONG]: (queue: Queue, song: Song) => Awaitable;\n /**\n * @event\n * Emitted when DisTube initialize a queue to change queue default properties.\n *\n * @example\n * ```ts\n * distube.on(\"initQueue\", queue => {\n * queue.autoplay = false;\n * queue.volume = 100;\n * });\n * ```ts\n *\n * @param queue - The guild queue\n */\n [Events.INIT_QUEUE]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when {@link Queue#autoplay} is `true`, {@link Queue#songs} is empty, and\n * DisTube cannot find related songs to play.\n *\n * @example\n * ```ts\n * distube.on(\"noRelated\", queue => queue.textChannel.send(\"Can't find related video to play.\"));\n * ```ts\n *\n * @param queue - The guild queue\n */\n [Events.NO_RELATED]: (queue: Queue) => Awaitable;\n /**\n * @event\n * Emitted when DisTube play a song.\n *\n * If {@link DisTubeOptions}.emitNewSongOnly is `true`, this event is not emitted\n * when looping a song or next song is the previous one.\n *\n * @example\n * ```ts\n * distube.on(\"playSong\", (queue, song) => queue.textChannel.send(\n * `Playing \\`${song.name}\\` - \\`${song.formattedDuration}\\`\\nRequested by: ${song.user}`\n * ));\n * ```ts\n *\n * @param queue - The guild queue\n * @param song - Playing song\n */\n [Events.PLAY_SONG]: (queue: Queue, song: Song) => Awaitable;\n /**\n * @event\n * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,\n * and the search canceled due to {@link DisTubeOptions |\n * DisTubeOptions.searchTimeout}.\n *\n * @example\n * ```ts\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchCancel\", (message) => message.channel.send(`Searching canceled`));\n * ```ts\n *\n * @param message - The user message called play method\n * @param query - The search query\n */\n [Events.SEARCH_CANCEL]: (message: Message, query: string) => Awaitable;\n /**\n * @event\n * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,\n * and after the user chose a search result to play.\n *\n * @param message - The user message called play method\n * @param answer - The answered message of user\n * @param query - The search query\n */\n [Events.SEARCH_DONE]: (message: Message, answer: string, query: string) => Awaitable;\n /**\n * @event\n * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,\n * and the search canceled due to user's next message is not a number or out of\n * results range.\n *\n * @example\n * ```ts\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchInvalidAnswer\", (message) => message.channel.send(`You answered an invalid number!`));\n * ```ts\n *\n * @param message - The user message called play method\n * @param answer - The answered message of user\n * @param query - The search query\n */\n [Events.SEARCH_INVALID_ANSWER]: (message: Message, answer: string, query: string) => Awaitable;\n /**\n * @event\n * Emitted when DisTube cannot find any results for the query.\n *\n * @example\n * ```ts\n * distube.on(\"searchNoResult\", (message, query) => message.channel.send(`No result found for ${query}!`));\n * ```ts\n *\n * @param message - The user message called play method\n * @param query - The search query\n */\n [Events.SEARCH_NO_RESULT]: (message: Message, query: string) => Awaitable;\n /**\n * @event\n * Emitted when {@link DisTubeOptions | DisTubeOptions.searchSongs} bigger than 0,\n * and song param of {@link DisTube#play} is invalid url. DisTube will wait for\n * user's next message to choose a song manually. <info>{@link\n * https://support.google.com/youtube/answer/7354993 | Safe search} is enabled if\n * {@link DisTubeOptions}.nsfw is disabled and the message's channel is not a nsfw\n * channel.</info>\n *\n * @example\n * ```ts\n * // DisTubeOptions.searchSongs > 0\n * distube.on(\"searchResult\", (message, results) => {\n * message.channel.send(`**Choose an option from below**\\n${\n * results.map((song, i) => `**${i + 1}**. ${song.name} - \\`${song.formattedDuration}\\``).join(\"\\n\")\n * }\\n*Enter anything else or wait 60 seconds to cancel*`);\n * });\n * ```ts\n *\n * @param message - The user message called play method\n * @param results - Searched results\n * @param query - The search query\n */\n [Events.SEARCH_RESULT]: (message: Message, results: SearchResult[], query: string) => Awaitable;\n}\n\n/**\n * DisTube class\n */\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nexport class DisTube extends TypedEmitter<TypedDisTubeEvents> {\n readonly handler: DisTubeHandler;\n readonly options: Options;\n readonly client: Client;\n readonly queues: QueueManager;\n readonly voices: DisTubeVoiceManager;\n readonly extractorPlugins: ExtractorPlugin[];\n readonly customPlugins: CustomPlugin[];\n readonly filters: Filters;\n\n /**\n * @deprecated Use `youtubeCookie: Cookie[]` instead. Guide: {@link\n * https://github.com/skick1234/DisTube/wiki/YouTube-Cookies | YouTube Cookies}\n */\n constructor(\n client: Client,\n opts: DisTubeOptions & {\n youtubeCookie: string;\n },\n );\n /**\n * Create a new DisTube class.\n *\n * @example\n * ```ts\n * const Discord = require('discord.js'),\n * DisTube = require('distube'),\n * client = new Discord.Client();\n * // Create a new DisTube\n * const distube = new DisTube.default(client, { searchSongs: 10 });\n * // client.DisTube = distube // make it access easily\n * client.login(\"Your Discord Bot Token\")\n * ```ts\n *\n * @throws {@link DisTubeError}\n *\n * @param client - Discord.JS client\n * @param opts - Custom DisTube options\n */\n constructor(client: Client, opts?: DisTubeOptions);\n constructor(client: Client, opts: DisTubeOptions = {}) {\n super();\n this.setMaxListeners(1);\n if (!isClientInstance(client)) throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Client\", client, \"client\");\n /**\n * Discord.JS client\n */\n this.client = client;\n checkIntents(client.options);\n /**\n * DisTube options\n */\n this.options = new Options(opts);\n /**\n * Voice connections manager\n */\n this.voices = new DisTubeVoiceManager(this);\n /**\n * DisTube's Handler\n */\n this.handler = new DisTubeHandler(this);\n /**\n * Queues manager\n */\n this.queues = new QueueManager(this);\n /**\n * DisTube filters\n */\n this.filters = { ...defaultFilters, ...this.options.customFilters };\n // Default plugin\n if (this.options.directLink) this.options.plugins.push(new DirectLinkPlugin());\n this.options.plugins.forEach(p => p.init(this));\n /**\n * Extractor Plugins\n */\n this.extractorPlugins = this.options.plugins.filter((p): p is ExtractorPlugin => p.type === \"extractor\");\n /**\n * Custom Plugins\n */\n this.customPlugins = this.options.plugins.filter((p): p is CustomPlugin => p.type === \"custom\");\n }\n\n static get version() {\n return version;\n }\n\n /**\n * DisTube version\n */\n get version() {\n return version;\n }\n\n /**\n * Play / add a song or playlist from url. Search and play a song if it is not a\n * valid url.\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"play\")\n * distube.play(message.member.voice.channel, args.join(\" \"), {\n * member: message.member,\n * textChannel: message.channel,\n * message\n * });\n * });\n * ```ts\n *\n * @throws {@link DisTubeError}\n *\n * @param voiceChannel - The channel will be joined if the bot isn't in any channels, the bot will be\n * moved to this channel if {@link DisTubeOptions}.joinNewVoiceChannel is `true`\n * @param song - URL | Search string | {@link Song} | {@link SearchResult} | {@link Playlist}\n * @param options - Optional options\n */\n async play(\n voiceChannel: VoiceBasedChannel,\n song: string | Song | SearchResult | Playlist,\n options: PlayOptions = {},\n ): Promise<void> {\n if (!isSupportedVoiceChannel(voiceChannel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"BaseGuildVoiceChannel\", voiceChannel, \"voiceChannel\");\n }\n if (!isObject(options)) throw new DisTubeError(\"INVALID_TYPE\", \"object\", options, \"options\");\n\n const { textChannel, member, skip, message, metadata } = {\n member: voiceChannel.guild.members.me ?? undefined,\n textChannel: options?.message?.channel,\n skip: false,\n ...options,\n };\n const position = Number(options.position) || (skip ? 1 : 0);\n\n if (message && !isMessageInstance(message)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"Discord.Message\", \"a falsy value\"], message, \"options.message\");\n }\n if (textChannel && !isTextChannelInstance(textChannel)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.GuildTextBasedChannel\", textChannel, \"options.textChannel\");\n }\n if (member && !isMemberInstance(member)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.GuildMember\", member, \"options.member\");\n }\n const queue = this.getQueue(voiceChannel);\n const queuing = queue && !queue._taskQueue.hasResolveTask;\n if (queuing) await queue?._taskQueue.queuing(true);\n try {\n if (typeof song === \"string\") {\n for (const plugin of this.customPlugins) {\n if (await plugin.validate(song)) {\n await plugin.play(voiceChannel, song, options);\n return;\n }\n }\n }\n if (typeof song === \"string\" && !isURL(song)) {\n if (!message) {\n song = (await this.search(song, { limit: 1 }))[0];\n } else {\n const result = await this.handler.searchSong(message, song);\n if (!result) return;\n song = result;\n }\n }\n song = await this.handler.resolve(song, { member, metadata });\n if (song instanceof Playlist) {\n await this.handler.playPlaylist(voiceChannel, song, { textChannel, skip, position });\n } else {\n await this.handler.playSong(voiceChannel, song, { textChannel, skip, position });\n }\n } catch (e: any) {\n if (!(e instanceof DisTubeError)) {\n try {\n e.name = \"PlayError\";\n e.message = `${typeof song === \"string\" ? song : song.url}\\n${e.message}`;\n } catch {\n // Throw original error\n }\n }\n throw e;\n } finally {\n if (queuing) queue?._taskQueue.resolve();\n }\n }\n\n /**\n * Create a custom playlist\n *\n * @example\n * ```ts\n * const songs = [\"https://www.youtube.com/watch?v=xxx\", \"https://www.youtube.com/watch?v=yyy\"];\n * const playlist = await distube.createCustomPlaylist(songs, {\n * member: message.member,\n * properties: { name: \"My playlist name\", source: \"custom\" },\n * parallel: true\n * });\n * distube.play(voiceChannel, playlist, { ... });\n * ```ts\n *\n * @param songs - Array of url, Song or SearchResult\n * @param options - Optional options\n */\n async createCustomPlaylist(\n songs: (string | Song | SearchResult)[],\n options: CustomPlaylistOptions = {},\n ): Promise<Playlist> {\n const { member, properties, parallel, metadata } = { parallel: true, ...options };\n if (!Array.isArray(songs)) throw new DisTubeError(\"INVALID_TYPE\", \"Array\", songs, \"songs\");\n if (!songs.length) throw new DisTubeError(\"EMPTY_ARRAY\", \"songs\");\n const filteredSongs = songs.filter(\n song => song instanceof Song || isURL(song) || (typeof song !== \"string\" && song.type === SearchResultType.VIDEO),\n );\n if (!filteredSongs.length) throw new DisTubeError(\"NO_VALID_SONG\");\n if (member && !isMemberInstance(member)) {\n throw new DisTubeError(\"INVALID_TYPE\", \"Discord.Member\", member, \"options.member\");\n }\n let resolvedSongs: Song[];\n if (parallel) {\n const promises = filteredSongs.map((song: string | Song | SearchResult) =>\n this.handler.resolve(song, { member, metadata }).catch(() => undefined),\n );\n resolvedSongs = (await Promise.all(promises)).filter((s): s is Song => s instanceof Song);\n } else {\n resolvedSongs = [];\n for (const song of filteredSongs) {\n const resolved = await this.handler.resolve(song, { member, metadata }).catch(() => undefined);\n if (resolved instanceof Song) resolvedSongs.push(resolved);\n }\n }\n return new Playlist(resolvedSongs, { member, properties, metadata });\n }\n\n search(\n string: string,\n options?: { type?: SearchResultType.VIDEO; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResultVideo>>;\n search(\n string: string,\n options: { type: SearchResultType.PLAYLIST; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResultPlaylist>>;\n search(\n string: string,\n options?: { type?: SearchResultType; limit?: number; safeSearch?: boolean; retried?: boolean },\n ): Promise<Array<SearchResult>>;\n /**\n * Search for a song. You can customize how user answers instead of send a number.\n * Then use {@link DisTube#play} to play it.\n *\n * @param string - The string search for\n * @param options - Search options\n * @param options.limit - Limit the results\n * @param options.type - Type of results (`video` or `playlist`).\n * @param options.safeSearch - Whether or not use safe search (YouTube restricted mode)\n *\n * @returns Array of results\n */\n async search(\n string: string,\n options: {\n type?: SearchResultType;\n limit?: number;\n safeSearch?: boolean;\n retried?: boolean;\n } = {},\n ): Promise<Array<SearchResult>> {\n const opts = { type: SearchResultType.VIDEO, limit: 10, safeSearch: false, ...options };\n if (typeof opts.type !== \"string\" || ![\"video\", \"playlist\"].includes(opts.type)) {\n throw new DisTubeError(\"INVALID_TYPE\", [\"video\", \"playlist\"], opts.type, \"options.type\");\n }\n if (typeof opts.limit !== \"number\") throw new DisTubeError(\"INVALID_TYPE\", \"number\", opts.limit, \"options.limit\");\n if (opts.limit < 1) throw new DisTubeError(\"NUMBER_COMPARE\", \"option.limit\", \"bigger or equal to\", 1);\n if (typeof opts.safeSearch !== \"boolean\") {\n throw new DisTubeError(\"INVALID_TYPE\", \"boolean\", opts.safeSearch, \"options.safeSearch\");\n }\n\n try {\n const search = await ytsr(string, { ...opts, requestOptions: { headers: { cookie: this.handler.ytCookie } } });\n const results = search.items.map(i => {\n if (i.type === \"video\") return new SearchResultVideo(i);\n return new SearchResultPlaylist(i as any);\n });\n if (results.length === 0) throw new DisTubeError(\"NO_RESULT\");\n return results;\n } catch (e) {\n if (options.retried) throw e;\n options.retried = true;\n return this.search(string, options);\n }\n }\n\n /**\n * Get the guild queue\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"queue\") {\n * const queue = distube.getQueue(message);\n * message.channel.send('Current queue:\\n' + queue.songs.map((song, id) =>\n * `**${id+1}**. [${song.name}](${song.url}) - \\`${song.formattedDuration}\\``\n * ).join(\"\\n\"));\n * }\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n */\n getQueue(guild: GuildIdResolvable): Queue | undefined {\n return this.queues.get(guild);\n }\n\n #getQueue(guild: GuildIdResolvable): Queue {\n const queue = this.getQueue(guild);\n if (!queue) throw new DisTubeError(\"NO_QUEUE\");\n return queue;\n }\n\n /**\n * Pause the guild stream\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The guild queue\n */\n pause(guild: GuildIdResolvable): Queue {\n return this.#getQueue(guild).pause();\n }\n\n /**\n * Resume the guild stream\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The guild queue\n */\n resume(guild: GuildIdResolvable): Queue {\n return this.#getQueue(guild).resume();\n }\n\n /**\n * Stop the guild stream\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"stop\") {\n * distube.stop(message);\n * message.channel.send(\"Stopped the queue!\");\n * }\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n */\n stop(guild: GuildIdResolvable): Promise<void> {\n return this.#getQueue(guild).stop();\n }\n\n /**\n * Set the guild stream's volume\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"volume\")\n * distube.setVolume(message, Number(args[0]));\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n * @param percent - The percentage of volume you want to set\n *\n * @returns The guild queue\n */\n setVolume(guild: GuildIdResolvable, percent: number): Queue {\n return this.#getQueue(guild).setVolume(percent);\n }\n\n /**\n * Skip the playing song if there is a next song in the queue. <info>If {@link\n * Queue#autoplay} is `true` and there is no up next song, DisTube will add and\n * play a related song.</info>\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"skip\")\n * distube.skip(message);\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The new Song will be played\n */\n skip(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).skip();\n }\n\n /**\n * Play the previous song\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"previous\")\n * distube.previous(message);\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The new Song will be played\n */\n previous(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).previous();\n }\n\n /**\n * Shuffle the guild queue songs\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"shuffle\")\n * distube.shuffle(message);\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The guild queue\n */\n shuffle(guild: GuildIdResolvable): Promise<Queue> {\n return this.#getQueue(guild).shuffle();\n }\n\n /**\n * Jump to the song number in the queue. The next one is 1, 2,... The previous one\n * is -1, -2,...\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"jump\")\n * distube.jump(message, parseInt(args[0]))\n * .catch(err => message.channel.send(\"Invalid song number.\"));\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n * @param num - The song number to play\n *\n * @returns The new Song will be played\n */\n jump(guild: GuildIdResolvable, num: number): Promise<Song> {\n return this.#getQueue(guild).jump(num);\n }\n\n /**\n * Set the repeat mode of the guild queue.\n * Toggle mode `(Disabled -> Song -> Queue -> Disabled ->...)` if `mode` is `undefined`\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"repeat\") {\n * let mode = distube.setRepeatMode(message, parseInt(args[0]));\n * mode = mode ? mode == 2 ? \"Repeat queue\" : \"Repeat song\" : \"Off\";\n * message.channel.send(\"Set repeat mode to `\" + mode + \"`\");\n * }\n * });\n * ```ts\n * @example\n * ```ts\n * const { RepeatMode } = require(\"distube\");\n * let mode;\n * switch(distube.setRepeatMode(message, parseInt(args[0]))) {\n * case RepeatMode.DISABLED:\n * mode = \"Off\";\n * break;\n * case RepeatMode.SONG:\n * mode = \"Repeat a song\";\n * break;\n * case RepeatMode.QUEUE:\n * mode = \"Repeat all queue\";\n * break;\n * }\n * message.channel.send(\"Set repeat mode to `\" + mode + \"`\");\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n * @param mode - The repeat modes (toggle if `undefined`)\n *\n * @returns The new repeat mode\n */\n setRepeatMode(guild: GuildIdResolvable, mode?: number): number {\n return this.#getQueue(guild).setRepeatMode(mode);\n }\n\n /**\n * Toggle autoplay mode\n *\n * @example\n * ```ts\n * client.on('message', (message) => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command == \"autoplay\") {\n * const mode = distube.toggleAutoplay(message);\n * message.channel.send(\"Set autoplay mode to `\" + (mode ? \"On\" : \"Off\") + \"`\");\n * }\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns Autoplay mode state\n */\n toggleAutoplay(guild: GuildIdResolvable): boolean {\n const queue = this.#getQueue(guild);\n queue.autoplay = !queue.autoplay;\n return queue.autoplay;\n }\n\n /**\n * Add related song to the queue\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n *\n * @returns The guild queue\n */\n addRelatedSong(guild: GuildIdResolvable): Promise<Song> {\n return this.#getQueue(guild).addRelatedSong();\n }\n\n /**\n * Set the playing time to another position\n *\n * @example\n * ```ts\n * client.on('message', message => {\n * if (!message.content.startsWith(config.prefix)) return;\n * const args = message.content.slice(config.prefix.length).trim().split(/ +/g);\n * const command = args.shift();\n * if (command = 'seek')\n * distube.seek(message, Number(args[0]));\n * });\n * ```ts\n *\n * @param guild - The type can be resolved to give a {@link Queue}\n * @param time - Time in seconds\n *\n * @returns Seeked queue\n */\n seek(guild: GuildIdResolvable, time: number): Queue {\n return this.#getQueue(guild).seek(time);\n }\n\n /**\n * Emit error event\n *\n * @param error - error\n * @param channel - Text channel where the error is encountered.\n */\n emitError(error: Error, channel?: GuildTextBasedChannel): void {\n if (this.listeners(Events.ERROR).length) {\n this.emit(Events.ERROR, channel, error);\n } else {\n /* eslint-disable no-console */\n console.error(error);\n console.warn(\"Unhandled 'error' event.\");\n console.warn(\n \"See: https://distube.js.org/classes/DisTube.html#error and https://nodejs.org/api/events.html#events_error_events\",\n );\n /* eslint-enable no-console */\n }\n }\n}\n\nexport default DisTube;\n"],"mappings":"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","names":["exports","module","RepeatMode","PluginType","SearchResultType","StreamType","Events","_metadata","_member","import_tiny_typed_emitter","import_voice","process","version","DiscordVoiceStreamType","ytdl","ytpl","import_discord","import_voice","import_discord","import_tiny_typed_emitter","ytsr"]}
|