From fad0a102ce5e198973f87f5ad556499a0f15bcdd Mon Sep 17 00:00:00 2001 From: twlite <46562212+twlite@users.noreply.github.com> Date: Sun, 9 Jun 2024 17:32:08 +0545 Subject: [PATCH] chore(discord-player): release 6.6.10 --- packages/discord-player/package.json | 4 +- packages/discord-player/src/Player.ts | 14 +-- .../discord-player/src/queue/GuildQueue.ts | 91 +++++++++++++------ .../src/queue/GuildQueueAudioFilters.ts | 4 +- packages/discord-player/src/types/types.ts | 14 ++- .../discord-player/src/utils/AudioFilters.ts | 4 +- .../discord-player/src/utils/FFmpegStream.ts | 75 ++++++--------- 7 files changed, 113 insertions(+), 93 deletions(-) diff --git a/packages/discord-player/package.json b/packages/discord-player/package.json index e3d44a025c..da3fd98fb2 100644 --- a/packages/discord-player/package.json +++ b/packages/discord-player/package.json @@ -1,6 +1,6 @@ { "name": "discord-player", - "version": "6.6.9", + "version": "6.6.10", "description": "Complete framework to facilitate music commands using discord.js", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -78,4 +78,4 @@ "readmeFile": "./README.md", "tsconfig": "./tsconfig.json" } -} +} \ No newline at end of file diff --git a/packages/discord-player/src/Player.ts b/packages/discord-player/src/Player.ts index 56343008f0..446c7dd4e3 100644 --- a/packages/discord-player/src/Player.ts +++ b/packages/discord-player/src/Player.ts @@ -1,9 +1,9 @@ import { FFmpeg } from '@discord-player/ffmpeg'; -import { Client, SnowflakeUtil, VoiceState, IntentsBitField, User, GuildVoiceChannelResolvable, version as djsVersion } from 'discord.js'; +import { Client, SnowflakeUtil, VoiceState, IntentsBitField, User, GuildVoiceChannelResolvable, version as djsVersion, Events } from 'discord.js'; import { Playlist, Track, SearchResult } from './fabric'; import { GuildQueueEvents, VoiceConnectConfig, GuildNodeCreateOptions, GuildNodeManager, GuildQueue, ResourcePlayOptions, GuildQueueEvent } from './queue'; import { VoiceUtils } from './VoiceInterface/VoiceUtils'; -import { PlayerEvents, QueryType, SearchOptions, PlayerInitOptions, PlaylistInitData, SearchQueryType } from './types/types'; +import { PlayerEvents, QueryType, SearchOptions, PlayerInitOptions, PlaylistInitData, SearchQueryType, PlayerEvent } from './types/types'; import { QueryResolver, ResolvedQuery } from './utils/QueryResolver'; import { Util } from './utils/Util'; import { generateDependencyReport, version as dVoiceVersion } from 'discord-voip'; @@ -79,7 +79,7 @@ export class Player extends PlayerEventsEmitter { /** * The player events channel */ - public events = new PlayerEventsEmitter(['error', 'playerError']); + public events = new PlayerEventsEmitter([GuildQueueEvent.Error, GuildQueueEvent.PlayerError]); /** * The route planner */ @@ -102,7 +102,7 @@ export class Player extends PlayerEventsEmitter { // eslint-disable-next-line @typescript-eslint/no-explicit-any if (!options.ignoreInstance && kSingleton in Player) return (Player)[kSingleton] as Player; - super(['error']); + super([PlayerEvent.Error]); /** * The discord.js client @@ -144,7 +144,8 @@ export class Player extends PlayerEventsEmitter { } } as PlayerInitOptions; - this.client.on('voiceStateUpdate', this.#voiceStateUpdateListener); + this.client.setMaxListeners(this.client.getMaxListeners() + 1); + this.client.on(Events.VoiceStateUpdate, this.#voiceStateUpdateListener); if (typeof this.options.lagMonitor === 'number' && this.options.lagMonitor > 0) { this.#lagMonitorInterval = setInterval(() => { @@ -295,7 +296,8 @@ export class Player extends PlayerEventsEmitter { */ public async destroy() { this.nodes.cache.forEach((node) => node.delete()); - this.client.off('voiceStateUpdate', this.#voiceStateUpdateListener); + this.client.off(Events.VoiceStateUpdate, this.#voiceStateUpdateListener); + this.client.setMaxListeners(this.client.getMaxListeners() - 1); this.removeAllListeners(); this.events.removeAllListeners(); await this.extractors.unregisterAll(); diff --git a/packages/discord-player/src/queue/GuildQueue.ts b/packages/discord-player/src/queue/GuildQueue.ts index f1ad48eaad..53f9e9013f 100644 --- a/packages/discord-player/src/queue/GuildQueue.ts +++ b/packages/discord-player/src/queue/GuildQueue.ts @@ -77,120 +77,151 @@ export const GuildQueueEvent = { * Emitted when audio track is added to the queue */ audioTrackAdd: 'audioTrackAdd', + AudioTrackAdd: 'audioTrackAdd', /** * Emitted when audio tracks were added to the queue */ audioTracksAdd: 'audioTracksAdd', + AudioTracksAdd: 'audioTracksAdd', /** * Emitted when audio track is removed from the queue */ audioTrackRemove: 'audioTrackRemove', + AudioTrackRemove: 'audioTrackRemove', /** * Emitted when audio tracks are removed from the queue */ audioTracksRemove: 'audioTracksRemove', + AudioTracksRemove: 'audioTracksRemove', /** * Emitted when a connection is created */ connection: 'connection', + Connection: 'connection', /** * Emitted when a voice connection is destroyed */ connectionDestroyed: 'connectionDestroyed', + ConnectionDestroyed: 'connectionDestroyed', /** * Emitted when the bot is disconnected from the channel */ disconnect: 'disconnect', + Disconnect: 'disconnect', /** * Emitted when the queue sends a debug info */ debug: 'debug', + Debug: 'debug', /** * Emitted when the queue encounters error */ error: 'error', + Error: 'error', /** * Emitted when the voice channel is empty */ emptyChannel: 'emptyChannel', + EmptyChannel: 'emptyChannel', /** * Emitted when the queue is empty */ emptyQueue: 'emptyQueue', + EmptyQueue: 'emptyQueue', /** * Emitted when the audio player starts streaming audio track */ playerStart: 'playerStart', + PlayerStart: 'playerStart', /** * Emitted when the audio player errors while streaming audio track */ playerError: 'playerError', + PlayerError: 'playerError', /** * Emitted when the audio player finishes streaming audio track */ playerFinish: 'playerFinish', + PlayerFinish: 'playerFinish', /** * Emitted when the audio player skips current track */ playerSkip: 'playerSkip', + PlayerSkip: 'playerSkip', /** * Emitted when the audio player is triggered */ playerTrigger: 'playerTrigger', + PlayerTrigger: 'playerTrigger', /** * Emitted when the voice state is updated. Consuming this event may disable default voice state update handler if `Player.isVoiceStateHandlerLocked()` returns `false`. */ voiceStateUpdate: 'voiceStateUpdate', + VoiceStateUpdate: 'voiceStateUpdate', /** * Emitted when volume is updated */ volumeChange: 'volumeChange', + VolumeChange: 'volumeChange', /** * Emitted when player is paused */ playerPause: 'playerPause', + PlayerPause: 'playerPause', /** * Emitted when player is resumed */ playerResume: 'playerResume', + PlayerResume: 'playerResume', /** * Biquad Filters Update */ biquadFiltersUpdate: 'biquadFiltersUpdate', + BiquadFiltersUpdate: 'biquadFiltersUpdate', /** * Equalizer Update */ equalizerUpdate: 'equalizerUpdate', + EqualizerUpdate: 'equalizerUpdate', /** * DSP update */ dspUpdate: 'dspUpdate', + DSPUpdate: 'dspUpdate', /** * Audio Filters Update */ audioFiltersUpdate: 'audioFiltersUpdate', + AudioFiltersUpdate: 'audioFiltersUpdate', /** * Audio player will play next track */ willPlayTrack: 'willPlayTrack', + WillPlayTrack: 'willPlayTrack', /** * Emitted when a voice channel is repopulated */ channelPopulate: 'channelPopulate', + ChannelPopulate: 'channelPopulate', /** * Emitted when a queue is successfully created */ queueCreate: 'queueCreate', + QueueCreate: 'queueCreate', /** * Emitted when a queue is deleted */ queueDelete: 'queueDelete', + QueueDelete: 'queueDelete', /** * Emitted when a queue is trying to add similar track for autoplay */ - willAutoPlay: 'willAutoPlay' + willAutoPlay: 'willAutoPlay', + WillAutoPlay: 'willAutoPlay' } as const; +export type GuildQueueEvent = (typeof GuildQueueEvent)[keyof typeof GuildQueueEvent]; + export enum TrackSkipReason { NoStream = 'ERR_NO_STREAM', Manual = 'MANUAL', @@ -207,81 +238,81 @@ export interface GuildQueueEvents { * @param queue The queue where this event occurred * @param track The track */ - audioTrackAdd: (queue: GuildQueue, track: Track) => unknown; + [GuildQueueEvent.AudioTrackAdd]: (queue: GuildQueue, track: Track) => unknown; /** * Emitted when audio tracks were added to the queue * @param queue The queue where this event occurred * @param tracks The tracks array */ - audioTracksAdd: (queue: GuildQueue, track: Track[]) => unknown; + [GuildQueueEvent.AudioTracksAdd]: (queue: GuildQueue, track: Track[]) => unknown; /** * Emitted when audio track is removed from the queue * @param queue The queue where this event occurred * @param track The track */ - audioTrackRemove: (queue: GuildQueue, track: Track) => unknown; + [GuildQueueEvent.AudioTrackRemove]: (queue: GuildQueue, track: Track) => unknown; /** * Emitted when audio tracks are removed from the queue * @param queue The queue where this event occurred * @param track The track */ - audioTracksRemove: (queue: GuildQueue, track: Track[]) => unknown; + [GuildQueueEvent.AudioTracksRemove]: (queue: GuildQueue, track: Track[]) => unknown; /** * Emitted when a connection is created * @param queue The queue where this event occurred */ - connection: (queue: GuildQueue) => unknown; + [GuildQueueEvent.Connection]: (queue: GuildQueue) => unknown; /** * Emitted when a connection is destroyed * @param queue The queue where this event occurred */ - connectionDestroyed: (queue: GuildQueue) => unknown; + [GuildQueueEvent.ConnectionDestroyed]: (queue: GuildQueue) => unknown; /** * Emitted when the bot is disconnected from the channel * @param queue The queue where this event occurred */ - disconnect: (queue: GuildQueue) => unknown; + [GuildQueueEvent.Disconnect]: (queue: GuildQueue) => unknown; /** * Emitted when the queue sends a debug info * @param queue The queue where this event occurred * @param message The debug message */ - debug: (queue: GuildQueue, message: string) => unknown; + [GuildQueueEvent.Debug]: (queue: GuildQueue, message: string) => unknown; /** * Emitted when the queue encounters error * @param queue The queue where this event occurred * @param error The error */ - error: (queue: GuildQueue, error: Error) => unknown; + [GuildQueueEvent.Error]: (queue: GuildQueue, error: Error) => unknown; /** * Emitted when the voice channel is empty * @param queue The queue where this event occurred */ - emptyChannel: (queue: GuildQueue) => unknown; + [GuildQueueEvent.EmptyChannel]: (queue: GuildQueue) => unknown; /** * Emitted when the queue is empty * @param queue The queue where this event occurred */ - emptyQueue: (queue: GuildQueue) => unknown; + [GuildQueueEvent.EmptyQueue]: (queue: GuildQueue) => unknown; /** * Emitted when the audio player starts streaming audio track * @param queue The queue where this event occurred * @param track The track that is being streamed */ - playerStart: (queue: GuildQueue, track: Track) => unknown; + [GuildQueueEvent.PlayerStart]: (queue: GuildQueue, track: Track) => unknown; /** * Emitted when the audio player errors while streaming audio track * @param queue The queue where this event occurred * @param error The error * @param track The track that is being streamed */ - playerError: (queue: GuildQueue, error: Error, track: Track) => unknown; + [GuildQueueEvent.PlayerError]: (queue: GuildQueue, error: Error, track: Track) => unknown; /** * Emitted when the audio player finishes streaming audio track * @param queue The queue where this event occurred * @param track The track that was being streamed */ - playerFinish: (queue: GuildQueue, track: Track) => unknown; + [GuildQueueEvent.PlayerFinish]: (queue: GuildQueue, track: Track) => unknown; /** * Emitted when the audio player skips current track * @param queue The queue where this event occurred @@ -289,65 +320,65 @@ export interface GuildQueueEvents { * @param reason The reason for skipping * @param description The description for skipping */ - playerSkip: (queue: GuildQueue, track: Track, reason: TrackSkipReason, description: string) => unknown; + [GuildQueueEvent.PlayerSkip]: (queue: GuildQueue, track: Track, reason: TrackSkipReason, description: string) => unknown; /** * Emitted when the audio player is triggered * @param queue The queue where this event occurred * @param track The track which was played in this event */ - playerTrigger: (queue: GuildQueue, track: Track, reason: PlayerTriggeredReason) => unknown; + [GuildQueueEvent.PlayerTrigger]: (queue: GuildQueue, track: Track, reason: PlayerTriggeredReason) => unknown; /** * Emitted when the voice state is updated. Consuming this event may disable default voice state update handler if `Player.isVoiceStateHandlerLocked()` returns `false`. * @param queue The queue where this event occurred * @param oldState The old voice state * @param newState The new voice state */ - voiceStateUpdate: (queue: GuildQueue, oldState: VoiceState, newState: VoiceState) => unknown; + [GuildQueueEvent.VoiceStateUpdate]: (queue: GuildQueue, oldState: VoiceState, newState: VoiceState) => unknown; /** * Emitted when audio player is paused * @param queue The queue where this event occurred */ - playerPause: (queue: GuildQueue) => unknown; + [GuildQueueEvent.PlayerPause]: (queue: GuildQueue) => unknown; /** * Emitted when audio player is resumed * @param queue The queue where this event occurred */ - playerResume: (queue: GuildQueue) => unknown; + [GuildQueueEvent.PlayerResume]: (queue: GuildQueue) => unknown; /** * Emitted when audio player's volume is changed * @param queue The queue where this event occurred * @param oldVolume The old volume * @param newVolume The updated volume */ - volumeChange: (queue: GuildQueue, oldVolume: number, newVolume: number) => unknown; + [GuildQueueEvent.VolumeChange]: (queue: GuildQueue, oldVolume: number, newVolume: number) => unknown; /** * Emitted when equalizer config is updated * @param queue The queue where this event occurred * @param oldFilters Old filters * @param newFilters New filters */ - equalizerUpdate: (queue: GuildQueue, oldFilters: EqualizerBand[], newFilters: EqualizerBand[]) => unknown; + [GuildQueueEvent.EqualizerUpdate]: (queue: GuildQueue, oldFilters: EqualizerBand[], newFilters: EqualizerBand[]) => unknown; /** * Emitted when biquad filters is updated * @param queue The queue where this event occurred * @param oldFilters Old filters * @param newFilters New filters */ - biquadFiltersUpdate: (queue: GuildQueue, oldFilters: BiquadFilters | null, newFilters: BiquadFilters | null) => unknown; + [GuildQueueEvent.BiquadFiltersUpdate]: (queue: GuildQueue, oldFilters: BiquadFilters | null, newFilters: BiquadFilters | null) => unknown; /** * Emitted when dsp filters is updated * @param queue The queue where this event occurred * @param oldFilters Old filters * @param newFilters New filters */ - dspUpdate: (queue: GuildQueue, oldFilters: PCMFilters[], newFilters: PCMFilters[]) => unknown; + [GuildQueueEvent.DSPUpdate]: (queue: GuildQueue, oldFilters: PCMFilters[], newFilters: PCMFilters[]) => unknown; /** * Emitted when ffmpeg audio filters is updated * @param queue The queue where this event occurred * @param oldFilters Old filters * @param newFilters New filters */ - audioFiltersUpdate: (queue: GuildQueue, oldFilters: FiltersName[], newFilters: FiltersName[]) => unknown; + [GuildQueueEvent.AudioFiltersUpdate]: (queue: GuildQueue, oldFilters: FiltersName[], newFilters: FiltersName[]) => unknown; /** * Emitted before streaming an audio track. This event can be used to modify stream config before playing a track. @@ -357,29 +388,29 @@ export interface GuildQueueEvents { * @param config Configurations for streaming * @param done Done callback */ - willPlayTrack: (queue: GuildQueue, track: Track, config: StreamConfig, done: () => void) => unknown; + [GuildQueueEvent.WillPlayTrack]: (queue: GuildQueue, track: Track, config: StreamConfig, done: () => void) => unknown; /** * Emitted when a voice channel is populated * @param queue The queue where this event occurred */ - channelPopulate: (queue: GuildQueue) => unknown; + [GuildQueueEvent.ChannelPopulate]: (queue: GuildQueue) => unknown; /** * Emitted when a queue is successfully created * @param queue The queue where this event occurred */ - queueCreate: (queue: GuildQueue) => unknown; + [GuildQueueEvent.QueueCreate]: (queue: GuildQueue) => unknown; /** * Emitted when a queue is successfully deleted * @param queue The queue where this event occurred */ - queueDelete: (queue: GuildQueue) => unknown; + [GuildQueueEvent.QueueDelete]: (queue: GuildQueue) => unknown; /** * Emitted when a queue is trying to add similar track for autoplay * @param queue The queue where this event occurred * @param tracks The similar tracks that were found * @param done Done callback */ - willAutoPlay: (queue: GuildQueue, tracks: Track[], done: (track: Track | null) => void) => unknown; + [GuildQueueEvent.WillAutoPlay]: (queue: GuildQueue, tracks: Track[], done: (track: Track | null) => void) => unknown; } export class GuildQueue { diff --git a/packages/discord-player/src/queue/GuildQueueAudioFilters.ts b/packages/discord-player/src/queue/GuildQueueAudioFilters.ts index 405a07d30b..cd263cde44 100644 --- a/packages/discord-player/src/queue/GuildQueueAudioFilters.ts +++ b/packages/discord-player/src/queue/GuildQueueAudioFilters.ts @@ -134,12 +134,12 @@ export class FFmpegFilterer { * Set ffmpeg filters * @param filters The filters */ - public setFilters(filters: Filters[] | Record | boolean) { + public setFilters(filters: Filters[] | Record | string[] | boolean) { let _filters: Filters[] = []; if (typeof filters === 'boolean') { _filters = !filters ? [] : (Object.keys(AudioFilters.filters) as Filters[]); } else if (Array.isArray(filters)) { - _filters = filters; + _filters = filters as Filters[]; } else { _filters = Object.entries(filters) .filter((res) => res[1] === true) diff --git a/packages/discord-player/src/types/types.ts b/packages/discord-player/src/types/types.ts index fdb45d8f8d..f66e5df006 100644 --- a/packages/discord-player/src/types/types.ts +++ b/packages/discord-player/src/types/types.ts @@ -243,11 +243,15 @@ export interface PlayerEvents { voiceStateUpdate: (queue: GuildQueue, oldState: VoiceState, newState: VoiceState) => any; } -export enum PlayerEvent { - debug = 'debug', - error = 'error', - voiceStateUpdate = 'voiceStateUpdate' -} +export const PlayerEvent = { + debug: 'debug', + Debug: 'debug', + error: 'error', + Error: 'error', + voiceStateUpdate: 'voiceStateUpdate', + VoiceStateUpdate: 'voiceStateUpdate' +} as const; +export type PlayerEvent = (typeof PlayerEvent)[keyof typeof PlayerEvent]; /* eslint-enable @typescript-eslint/no-explicit-any */ diff --git a/packages/discord-player/src/utils/AudioFilters.ts b/packages/discord-player/src/utils/AudioFilters.ts index 74785b630c..489c127a58 100644 --- a/packages/discord-player/src/utils/AudioFilters.ts +++ b/packages/discord-player/src/utils/AudioFilters.ts @@ -77,11 +77,11 @@ export class AudioFilters { * @param filter The filter name * @returns */ - public static create(filters?: K[]) { + public static create(filters?: (K | string)[]) { if (!filters || !Array.isArray(filters)) return this.toString(); return filters .filter((predicate) => typeof predicate === 'string') - .map((m) => this.get(m)) + .map((m) => this.get(m as K)) .join(','); } diff --git a/packages/discord-player/src/utils/FFmpegStream.ts b/packages/discord-player/src/utils/FFmpegStream.ts index f0f3fe2de2..846c463c40 100644 --- a/packages/discord-player/src/utils/FFmpegStream.ts +++ b/packages/discord-player/src/utils/FFmpegStream.ts @@ -13,58 +13,41 @@ export interface FFmpegStreamOptions { const getFFmpegProvider = (legacy = false) => (legacy ? (prism as typeof prism & { default: typeof prism }).default?.FFmpeg || prism.FFmpeg : FFmpeg); -export function FFMPEG_ARGS_STRING(stream: string, fmt?: string, cookies?: string) { - const args = [ - '-reconnect', - '1', - '-reconnect_streamed', - '1', - '-reconnect_delay_max', - '5', - '-i', - stream, - '-analyzeduration', - '0', - '-loglevel', - '0', - '-ar', - '48000', - '-ac', - '2', - '-f', - `${typeof fmt === 'string' ? fmt : 's16le'}` - ]; - - if (fmt === 'opus') { - args.push('-acodec', 'libopus'); - } +const resolveArgs = (config: Record): string[] => { + return Object.entries(config).reduce((acc, [key, value]) => { + if (value == null) return acc; + acc.push(`-${key}`, String(value)); + return acc; + }, [] as string[]); +}; - if (typeof cookies === 'string') { - // https://ffmpeg.org/ffmpeg-protocols.html#HTTP-Cookies - args.push('-cookies', cookies.startsWith('"') ? cookies : `"${cookies}"`); - } +export function FFMPEG_ARGS_STRING(stream: string, fmt?: string, cookies?: string) { + const args = resolveArgs({ + reconnect: 1, + reconnect_streamed: 1, + reconnect_delay_max: 5, + i: stream, + analyzeduration: 0, + loglevel: 0, + ar: 48000, + ac: 2, + f: `${typeof fmt === 'string' ? fmt : 's16le'}`, + acodec: fmt === 'opus' ? 'libopus' : null, + cookies: typeof cookies === 'string' ? (!cookies.includes(' ') ? cookies : `"${cookies}"`) : null + }); return args; } export function FFMPEG_ARGS_PIPED(fmt?: string) { - // prettier-ignore - const args = [ - '-analyzeduration', - '0', - '-loglevel', - '0', - '-ar', - '48000', - '-ac', - '2', - '-f', - `${typeof fmt === 'string' ? fmt : 's16le'}`, - ]; - - if (fmt === 'opus') { - args.push('-acodec', 'libopus'); - } + const args = resolveArgs({ + analyzeduration: 0, + loglevel: 0, + ar: 48000, + ac: 2, + f: `${typeof fmt === 'string' ? fmt : 's16le'}`, + acodec: fmt === 'opus' ? 'libopus' : null + }); return args; }