discord-player 5.3.1 → 5.3.2-dev.2

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/dist/Player.js CHANGED
@@ -32,7 +32,8 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
32
32
  ytdlOptions: {
33
33
  highWaterMark: 1 << 25
34
34
  },
35
- connectionTimeout: 20000
35
+ connectionTimeout: 20000,
36
+ smoothVolume: true
36
37
  };
37
38
  this.queues = new discord_js_1.Collection();
38
39
  this.voiceUtils = new VoiceUtils_1.VoiceUtils();
@@ -164,7 +165,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
164
165
  return this.queues.get(guild.id);
165
166
  const _meta = queueInitOptions.metadata;
166
167
  delete queueInitOptions["metadata"];
167
- queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = 0.08);
168
+ queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = this.options.smoothVolume ? 0.08 : 0);
168
169
  queueInitOptions.ytdlOptions ?? (queueInitOptions.ytdlOptions = this.options.ytdlOptions);
169
170
  const queue = new Queue_1.Queue(this, guild, queueInitOptions);
170
171
  queue.metadata = _meta;
@@ -174,7 +175,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
174
175
  /**
175
176
  * Returns the queue if available
176
177
  * @param {GuildResolvable} guild The guild id
177
- * @returns {Queue}
178
+ * @returns {Queue | undefined}
178
179
  */
179
180
  getQueue(guild) {
180
181
  guild = this.client.guilds.resolve(guild);
@@ -346,10 +347,11 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
346
347
  description: spotifyData.description ?? "",
347
348
  author: spotifyData.artists[0]?.name ?? "Unknown Artist",
348
349
  url: spotifyData.external_urls?.spotify ?? query,
349
- thumbnail: spotifyData.album?.images[0]?.url ?? spotifyData.preview_url?.length
350
- ? `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}`
351
- : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
352
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms)),
350
+ thumbnail: (spotifyData.coverArt?.sources?.[0]?.url ??
351
+ spotifyData.album?.images[0]?.url ??
352
+ (spotifyData.preview_url?.length && `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}`)) ||
353
+ "https://www.scdn.co/i/_global/twitter_card-default.jpg",
354
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms ?? spotifyData.duration ?? spotifyData.maxDuration)),
353
355
  views: 0,
354
356
  requestedBy: options.requestedBy,
355
357
  source: "spotify"
@@ -366,7 +368,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
366
368
  const playlist = new Playlist_1.Playlist(this, {
367
369
  title: spotifyPlaylist.name ?? spotifyPlaylist.title,
368
370
  description: spotifyPlaylist.description ?? "",
369
- thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
371
+ thumbnail: spotifyPlaylist.coverArt?.sources?.[0]?.url ?? spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
370
372
  type: spotifyPlaylist.type,
371
373
  source: "spotify",
372
374
  author: spotifyPlaylist.type !== "playlist"
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var _Queue_instances, _Queue_lastVolume, _Queue_destroyed, _Queue_watchDestroyed, _Queue_getBufferingTimeout;
2
+ var _Queue_instances, _Queue_destroyed, _Queue_watchDestroyed, _Queue_getBufferingTimeout;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.Queue = void 0;
5
5
  const tslib_1 = require("tslib");
@@ -32,7 +32,6 @@ class Queue {
32
32
  this._cooldownsTimeout = new discord_js_1.Collection();
33
33
  this._activeFilters = []; // eslint-disable-line @typescript-eslint/no-explicit-any
34
34
  this._filtersUpdate = false;
35
- _Queue_lastVolume.set(this, 0);
36
35
  _Queue_destroyed.set(this, false);
37
36
  this.onBeforeCreateStream = null;
38
37
  /**
@@ -86,6 +85,7 @@ class Queue {
86
85
  leaveOnEnd: true,
87
86
  leaveOnStop: true,
88
87
  leaveOnEmpty: true,
88
+ leaveOnEndCooldown: 1000,
89
89
  leaveOnEmptyCooldown: 1000,
90
90
  autoSelfDeaf: true,
91
91
  ytdlOptions: {
@@ -100,6 +100,18 @@ class Queue {
100
100
  this.onBeforeCreateStream = this.options.onBeforeCreateStream;
101
101
  this.player.emit("debug", this, `Queue initialized:\n\n${this.player.scanDeps()}`);
102
102
  }
103
+ /**
104
+ * Forces next play
105
+ * @returns {Promise<void>}
106
+ */
107
+ async forceNext() {
108
+ if (this.connection.audioResource) {
109
+ this.connection.emit("finish", this.connection.audioResource);
110
+ }
111
+ else if (this.tracks.length) {
112
+ await this.play();
113
+ }
114
+ }
103
115
  /**
104
116
  * Returns current track
105
117
  * @type {Track}
@@ -175,9 +187,7 @@ class Queue {
175
187
  this.previousTracks.push(resource.metadata);
176
188
  this.player.emit("trackEnd", this, resource.metadata);
177
189
  if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) {
178
- if (this.options.leaveOnEnd)
179
- this.destroy();
180
- this.player.emit("queueEnd", this);
190
+ this.emitEnd();
181
191
  }
182
192
  else if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.AUTOPLAY) {
183
193
  this._handleAutoplay(Util_1.Util.last(this.previousTracks));
@@ -194,6 +204,25 @@ class Queue {
194
204
  });
195
205
  return this;
196
206
  }
207
+ emitEnd() {
208
+ const timeout = setTimeout(() => {
209
+ if (!this.player.queues.has(this.guild.id))
210
+ return;
211
+ if (this.tracks.length || this.current)
212
+ return;
213
+ if (this.options.leaveOnEnd)
214
+ this.destroy();
215
+ this.player.emit("queueEnd", this);
216
+ }, this.options.leaveOnEndCooldown || 0).unref();
217
+ this._cooldownsTimeout.set(`queueEnd_${this.guild.id}`, timeout);
218
+ }
219
+ refreshEndCooldown() {
220
+ const existingTimeout = this._cooldownsTimeout.get(`queueEnd_${this.guild.id}`);
221
+ if (this.tracks.length || this.current) {
222
+ clearTimeout(existingTimeout);
223
+ this._cooldownsTimeout.delete(`queueEnd_${this.guild.id}`);
224
+ }
225
+ }
197
226
  /**
198
227
  * Destroys this queue
199
228
  * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy
@@ -234,6 +263,7 @@ class Queue {
234
263
  if (!(track instanceof Track_1.default))
235
264
  throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
236
265
  this.tracks.push(track);
266
+ this.refreshEndCooldown();
237
267
  this.player.emit("trackAdd", this, track);
238
268
  }
239
269
  /**
@@ -246,6 +276,7 @@ class Queue {
246
276
  if (!tracks.every((y) => y instanceof Track_1.default))
247
277
  throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
248
278
  this.tracks.push(...tracks);
279
+ this.refreshEndCooldown();
249
280
  this.player.emit("tracksAdd", this, tracks);
250
281
  }
251
282
  /**
@@ -284,7 +315,6 @@ class Queue {
284
315
  return;
285
316
  if (!this.connection)
286
317
  return false;
287
- tslib_1.__classPrivateFieldSet(this, _Queue_lastVolume, amount, "f");
288
318
  this.options.initialVolume = amount;
289
319
  return this.connection.setVolume(amount);
290
320
  }
@@ -630,7 +660,9 @@ class Queue {
630
660
  if (this.options.spotifyBridge && track.raw.source === "spotify" && !track.raw.engine) {
631
661
  track.raw.engine = await youtube_sr_1.default.search(`${track.author} ${track.title}`, { type: "video" })
632
662
  .then((res) => res[0].url)
633
- .catch(() => null);
663
+ .catch(() => {
664
+ /* void */
665
+ });
634
666
  spotifyResolved = true;
635
667
  }
636
668
  const url = track.raw.source === "spotify" ? track.raw.engine : track.url;
@@ -670,7 +702,7 @@ class Queue {
670
702
  this._filtersUpdate = options.filtersUpdate;
671
703
  const volumeTransformer = resource.volume;
672
704
  if (volumeTransformer && typeof this.options.initialVolume === "number")
673
- Reflect.set(volumeTransformer, "volume", Math.pow(this.options.initialVolume / 100, 1.660964));
705
+ volumeTransformer.setVolume(Math.pow(this.options.initialVolume / 100, 1.660964));
674
706
  if (volumeTransformer?.hasSmoothness && typeof this.options.volumeSmoothness === "number") {
675
707
  if (typeof volumeTransformer.setSmoothness === "function")
676
708
  volumeTransformer.setSmoothness(this.options.volumeSmoothness || 0);
@@ -689,9 +721,7 @@ class Queue {
689
721
  if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
690
722
  return;
691
723
  if (!track || ![track.source, track.raw?.source].includes("youtube")) {
692
- if (this.options.leaveOnEnd)
693
- this.destroy();
694
- return void this.player.emit("queueEnd", this);
724
+ return this.emitEnd();
695
725
  }
696
726
  let info = await youtube_sr_1.default.getVideo(track.url)
697
727
  .then((x) => x.videos[0])
@@ -702,9 +732,7 @@ class Queue {
702
732
  .then((x) => x[0])
703
733
  .catch(Util_1.Util.noop);
704
734
  if (!info) {
705
- if (this.options.leaveOnEnd)
706
- this.destroy();
707
- return void this.player.emit("queueEnd", this);
735
+ return this.emitEnd();
708
736
  }
709
737
  const nextTrack = new Track_1.default(this.player, {
710
738
  title: info.title,
@@ -719,7 +747,7 @@ class Queue {
719
747
  });
720
748
  this.play(nextTrack, { immediate: true });
721
749
  }
722
- *[(_Queue_lastVolume = new WeakMap(), _Queue_destroyed = new WeakMap(), _Queue_instances = new WeakSet(), Symbol.iterator)]() {
750
+ *[(_Queue_destroyed = new WeakMap(), _Queue_instances = new WeakSet(), Symbol.iterator)]() {
723
751
  if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
724
752
  return;
725
753
  yield* this.tracks;
@@ -171,8 +171,9 @@ class StreamDispatcher extends tiny_typed_emitter_1.TypedEmitter {
171
171
  async playStream(resource = this.audioResource) {
172
172
  if (!resource)
173
173
  throw new PlayerError_1.PlayerError("Audio resource is not available!", PlayerError_1.ErrorStatusCode.NO_AUDIO_RESOURCE);
174
- if (resource.ended)
175
- return void this.emit("error", new PlayerError_1.PlayerError("Cannot play a resource that has already ended."));
174
+ if (resource.ended) {
175
+ return void this.emit("finish", resource);
176
+ }
176
177
  if (!this.audioResource)
177
178
  this.audioResource = resource;
178
179
  if (this.voiceConnection.state.status !== voice_1.VoiceConnectionStatus.Ready) {
@@ -108,7 +108,7 @@ class VolumeTransformer extends stream_1.Transform {
108
108
  this._smoothing = smoothness;
109
109
  }
110
110
  smoothingEnabled() {
111
- return Number.isFinite(this._smoothing) && this._smoothing > 0;
111
+ return typeof this._smoothing === "number" && !Number.isNaN(this._smoothing) && Number.isFinite(this._smoothing) && this._smoothing > 0;
112
112
  }
113
113
  get hasSmoothness() {
114
114
  return true;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { User, VoiceChannel, StageChannel, Collection, Snowflake, Client, GuildResolvable, Guild, GuildChannelResolvable, UserResolvable } from 'discord.js';
3
- import { Readable, Duplex } from 'stream';
3
+ import { Readable, Duplex, TransformOptions, Transform } from 'stream';
4
4
  import { TypedEmitter } from 'tiny-typed-emitter';
5
5
  import { AudioPlayerError, AudioResource, VoiceConnection, AudioPlayer, StreamType, AudioPlayerStatus } from '@discordjs/voice';
6
6
  import { downloadOptions } from 'ytdl-core';
@@ -266,9 +266,9 @@ declare class Player extends TypedEmitter<PlayerEvents> {
266
266
  /**
267
267
  * Returns the queue if available
268
268
  * @param {GuildResolvable} guild The guild id
269
- * @returns {Queue}
269
+ * @returns {Queue | undefined}
270
270
  */
271
- getQueue<T = unknown>(guild: GuildResolvable): Queue<T>;
271
+ getQueue<T = unknown>(guild: GuildResolvable): Queue<T> | undefined;
272
272
  /**
273
273
  * Deletes a queue and returns deleted queue object
274
274
  * @param {GuildResolvable} guild The guild id to remove
@@ -345,6 +345,11 @@ declare class Queue<T = unknown> {
345
345
  * @param {PlayerOptions} [options] Player options for the queue
346
346
  */
347
347
  constructor(player: Player, guild: Guild, options?: PlayerOptions);
348
+ /**
349
+ * Forces next play
350
+ * @returns {Promise<void>}
351
+ */
352
+ forceNext(): Promise<void>;
348
353
  /**
349
354
  * Returns current track
350
355
  * @type {Track}
@@ -366,6 +371,8 @@ declare class Queue<T = unknown> {
366
371
  * @returns {Promise<Queue>}
367
372
  */
368
373
  connect(channel: GuildChannelResolvable): Promise<this>;
374
+ private emitEnd;
375
+ private refreshEndCooldown;
369
376
  /**
370
377
  * Destroys this queue
371
378
  * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy
@@ -671,6 +678,7 @@ interface PlayerProgressbarOptions {
671
678
  * @property {boolean} [leaveOnStop=true] If it should leave on stop
672
679
  * @property {boolean} [leaveOnEmpty=true] If it should leave on empty
673
680
  * @property {number} [leaveOnEmptyCooldown=1000] The cooldown in ms
681
+ * @property {number} [leaveOnEndCooldown=1000] The cooldown in ms
674
682
  * @property {boolean} [autoSelfDeaf=true] If it should set the bot in deaf mode
675
683
  * @property {YTDLDownloadOptions} [ytdlOptions] The youtube download options
676
684
  * @property {number} [initialVolume=100] The initial player volume
@@ -683,6 +691,7 @@ interface PlayerProgressbarOptions {
683
691
  */
684
692
  interface PlayerOptions {
685
693
  leaveOnEnd?: boolean;
694
+ leaveOnEndCooldown?: number;
686
695
  leaveOnStop?: boolean;
687
696
  leaveOnEmpty?: boolean;
688
697
  leaveOnEmptyCooldown?: number;
@@ -995,11 +1004,13 @@ interface PlaylistJSON {
995
1004
  * @property {boolean} [autoRegisterExtractor=true] If it should automatically register `@discord-player/extractor`
996
1005
  * @property {YTDLDownloadOptions} [ytdlOptions] The options passed to `ytdl-core`
997
1006
  * @property {number} [connectionTimeout=20000] The voice connection timeout
1007
+ * @property {boolean} [smoothVolume=true] Toggle smooth volume transition
998
1008
  */
999
1009
  interface PlayerInitOptions {
1000
1010
  autoRegisterExtractor?: boolean;
1001
1011
  ytdlOptions?: downloadOptions;
1002
1012
  connectionTimeout?: number;
1013
+ smoothVolume?: boolean;
1003
1014
  }
1004
1015
 
1005
1016
  declare class AudioFilters {
@@ -1087,6 +1098,38 @@ declare class QueryResolver {
1087
1098
  static getVimeoID(query: string): string;
1088
1099
  }
1089
1100
 
1101
+ interface VolumeTransformerOptions extends TransformOptions {
1102
+ type?: "s16le" | "s16be" | "s32le" | "s32be";
1103
+ smoothness?: number;
1104
+ volume?: number;
1105
+ }
1106
+ declare class VolumeTransformer extends Transform {
1107
+ private _bits;
1108
+ private _smoothing;
1109
+ private _bytes;
1110
+ private _extremum;
1111
+ private _chunk;
1112
+ volume: number;
1113
+ private _targetVolume;
1114
+ type: "s16le" | "s32le" | "s16be" | "s32be";
1115
+ constructor(options?: VolumeTransformerOptions);
1116
+ _readInt(buffer: Buffer, index: number): number;
1117
+ _writeInt(buffer: Buffer, int: number, index: number): number;
1118
+ _applySmoothness(): void;
1119
+ _transform(chunk: Buffer, encoding: BufferEncoding, done: () => unknown): unknown;
1120
+ _destroy(err: Error, cb: (error: Error) => void): void;
1121
+ setVolume(volume: number): void;
1122
+ setVolumeDecibels(db: number): void;
1123
+ setVolumeLogarithmic(value: number): void;
1124
+ get volumeDecibels(): number;
1125
+ get volumeLogarithmic(): number;
1126
+ get smoothness(): number;
1127
+ setSmoothness(smoothness: number): void;
1128
+ smoothingEnabled(): boolean;
1129
+ get hasSmoothness(): boolean;
1130
+ static get hasSmoothing(): boolean;
1131
+ }
1132
+
1090
1133
  declare class Util {
1091
1134
  /**
1092
1135
  * Utils
@@ -1155,4 +1198,4 @@ declare function createFFmpegStream(stream: Readable | Duplex | string, options?
1155
1198
 
1156
1199
  declare const version: string;
1157
1200
 
1158
- export { AudioFilters, ErrorStatusCode, ExtractorModel, ExtractorModelData, FFMPEG_ARGS_PIPED, FFMPEG_ARGS_STRING, FFmpegStreamOptions, FiltersName, PlayOptions, Player, PlayerError, PlayerEvents, PlayerInitOptions, PlayerOptions, PlayerProgressbarOptions, PlayerSearchResult, Playlist, PlaylistInitData, PlaylistJSON, QueryResolver, QueryType, Queue, QueueFilters, QueueRepeatMode, RawTrackData, SearchOptions, StreamDispatcher, TimeData, Track, TrackJSON, TrackSource, Util, VoiceEvents, VoiceUtils, createFFmpegStream, version };
1201
+ export { AudioFilters, ErrorStatusCode, ExtractorModel, ExtractorModelData, FFMPEG_ARGS_PIPED, FFMPEG_ARGS_STRING, FFmpegStreamOptions, FiltersName, PlayOptions, Player, PlayerError, PlayerEvents, PlayerInitOptions, PlayerOptions, PlayerProgressbarOptions, PlayerSearchResult, Playlist, PlaylistInitData, PlaylistJSON, QueryResolver, QueryType, Queue, QueueFilters, QueueRepeatMode, RawTrackData, SearchOptions, StreamDispatcher, TimeData, Track, TrackJSON, TrackSource, Util, VoiceEvents, VoiceUtils, VolumeTransformer, VolumeTransformerOptions, createFFmpegStream, version };
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ var VoiceUtils_1 = require("./VoiceInterface/VoiceUtils");
25
25
  Object.defineProperty(exports, "VoiceUtils", { enumerable: true, get: function () { return VoiceUtils_1.VoiceUtils; } });
26
26
  var StreamDispatcher_1 = require("./VoiceInterface/StreamDispatcher");
27
27
  Object.defineProperty(exports, "StreamDispatcher", { enumerable: true, get: function () { return StreamDispatcher_1.StreamDispatcher; } });
28
+ tslib_1.__exportStar(require("./VoiceInterface/VolumeTransformer"), exports);
28
29
  var Util_1 = require("./utils/Util");
29
30
  Object.defineProperty(exports, "Util", { enumerable: true, get: function () { return Util_1.Util; } });
30
31
  tslib_1.__exportStar(require("./types/types"), exports);
package/dist/index.mjs CHANGED
@@ -17,5 +17,6 @@ export const StreamDispatcher = mod.StreamDispatcher;
17
17
  export const Track = mod.Track;
18
18
  export const Util = mod.Util;
19
19
  export const VoiceUtils = mod.VoiceUtils;
20
+ export const VolumeTransformer = mod.VolumeTransformer;
20
21
  export const createFFmpegStream = mod.createFFmpegStream;
21
22
  export const version = mod.version;
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const VolumeTransformer_1 = require("./VoiceInterface/VolumeTransformer");
4
- try {
5
- // eslint-disable-next-line
6
- const mod = require("prism-media");
7
- if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") {
8
- Reflect.set(mod, "VolumeTransformer", VolumeTransformer_1.VolumeTransformer);
4
+ if (!("DISABLE_DISCORD_PLAYER_SMOOTH_VOLUME" in process.env)) {
5
+ try {
6
+ // eslint-disable-next-line
7
+ const mod = require("prism-media");
8
+ if (typeof mod.VolumeTransformer.hasSmoothing !== "boolean") {
9
+ Reflect.set(mod, "VolumeTransformer", VolumeTransformer_1.VolumeTransformer);
10
+ }
11
+ }
12
+ catch {
13
+ /* do nothing */
9
14
  }
10
- }
11
- catch {
12
- /* do nothing */
13
15
  }
@@ -7,7 +7,7 @@ const types_1 = require("../types/types");
7
7
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
8
8
  // @ts-ignore
9
9
  const soundcloud_scraper_1 = require("soundcloud-scraper");
10
- // scary things below *sigh*
10
+ // #region scary things below *sigh*
11
11
  const spotifySongRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/;
12
12
  const spotifyPlaylistRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/;
13
13
  const spotifyAlbumRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/;
@@ -15,7 +15,7 @@ const vimeoRegex = /(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/
15
15
  const facebookRegex = /(https?:\/\/)(www\.|m\.)?(facebook|fb).com\/.*\/videos\/.*/;
16
16
  const reverbnationRegex = /https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/;
17
17
  const attachmentRegex = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/;
18
- // scary things above *sigh*
18
+ // #endregion scary things above *sigh*
19
19
  class QueryResolver {
20
20
  /**
21
21
  * Query resolver
@@ -45,6 +45,8 @@ class Util {
45
45
  * @returns {TimeData}
46
46
  */
47
47
  static parseMS(milliseconds) {
48
+ if (isNaN(milliseconds))
49
+ milliseconds = 0;
48
50
  const round = milliseconds > 0 ? Math.floor : Math.ceil;
49
51
  return {
50
52
  days: round(milliseconds / 86400000),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-player",
3
- "version": "5.3.1",
3
+ "version": "5.3.2-dev.2",
4
4
  "description": "Complete framework to facilitate music commands using discord.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -67,12 +67,14 @@
67
67
  "dependencies": {
68
68
  "@discordjs/voice": "^0.11.0",
69
69
  "libsodium-wrappers": "^0.7.10",
70
- "soundcloud-scraper": "^5.0.3",
71
- "spotify-url-info": "^3.1.2",
72
70
  "tiny-typed-emitter": "^2.1.0",
73
- "tslib": "^2.4.0",
74
- "youtube-sr": "^4.3.0",
75
- "ytdl-core": "^4.11.0"
71
+ "tslib": "^2.4.0"
72
+ },
73
+ "peerDependencies": {
74
+ "soundcloud-scraper": "5.x",
75
+ "spotify-url-info": "3.x",
76
+ "youtube-sr": "4.x",
77
+ "ytdl-core": "4.x"
76
78
  },
77
79
  "devDependencies": {
78
80
  "@discordjs/ts-docgen": "^0.4.1",
@@ -89,8 +91,12 @@
89
91
  "opusscript": "^0.0.8",
90
92
  "prettier": "^2.7.1",
91
93
  "rimraf": "^3.0.2",
94
+ "soundcloud-scraper": "^5.0.3",
95
+ "spotify-url-info": "^3.1.7",
92
96
  "ts-node": "^10.9.1",
93
97
  "typedoc": "^0.23.10",
94
- "typescript": "^4.7.4"
98
+ "typescript": "^4.7.4",
99
+ "youtube-sr": "^4.3.4",
100
+ "ytdl-core": "^4.11.2"
95
101
  }
96
102
  }