discord-player 5.3.1 → 5.3.2-dev.0

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
@@ -174,7 +174,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
174
174
  /**
175
175
  * Returns the queue if available
176
176
  * @param {GuildResolvable} guild The guild id
177
- * @returns {Queue}
177
+ * @returns {Queue | undefined}
178
178
  */
179
179
  getQueue(guild) {
180
180
  guild = this.client.guilds.resolve(guild);
@@ -346,10 +346,11 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
346
346
  description: spotifyData.description ?? "",
347
347
  author: spotifyData.artists[0]?.name ?? "Unknown Artist",
348
348
  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)),
349
+ thumbnail: (spotifyData.coverArt?.sources?.[0]?.url ??
350
+ spotifyData.album?.images[0]?.url ??
351
+ (spotifyData.preview_url?.length && `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}`)) ||
352
+ "https://www.scdn.co/i/_global/twitter_card-default.jpg",
353
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms ?? spotifyData.duration ?? spotifyData.maxDuration)),
353
354
  views: 0,
354
355
  requestedBy: options.requestedBy,
355
356
  source: "spotify"
@@ -366,7 +367,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
366
367
  const playlist = new Playlist_1.Playlist(this, {
367
368
  title: spotifyPlaylist.name ?? spotifyPlaylist.title,
368
369
  description: spotifyPlaylist.description ?? "",
369
- thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
370
+ thumbnail: spotifyPlaylist.coverArt?.sources?.[0]?.url ?? spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
370
371
  type: spotifyPlaylist.type,
371
372
  source: "spotify",
372
373
  author: spotifyPlaylist.type !== "playlist"
@@ -86,6 +86,7 @@ class Queue {
86
86
  leaveOnEnd: true,
87
87
  leaveOnStop: true,
88
88
  leaveOnEmpty: true,
89
+ leaveOnEndCooldown: 1000,
89
90
  leaveOnEmptyCooldown: 1000,
90
91
  autoSelfDeaf: true,
91
92
  ytdlOptions: {
@@ -175,9 +176,7 @@ class Queue {
175
176
  this.previousTracks.push(resource.metadata);
176
177
  this.player.emit("trackEnd", this, resource.metadata);
177
178
  if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.OFF) {
178
- if (this.options.leaveOnEnd)
179
- this.destroy();
180
- this.player.emit("queueEnd", this);
179
+ this.emitEnd();
181
180
  }
182
181
  else if (!this.tracks.length && this.repeatMode === types_1.QueueRepeatMode.AUTOPLAY) {
183
182
  this._handleAutoplay(Util_1.Util.last(this.previousTracks));
@@ -194,6 +193,25 @@ class Queue {
194
193
  });
195
194
  return this;
196
195
  }
196
+ emitEnd() {
197
+ const timeout = setTimeout(() => {
198
+ if (!this.player.queues.has(this.guild.id))
199
+ return;
200
+ if (this.tracks.length || this.current)
201
+ return;
202
+ if (this.options.leaveOnEnd)
203
+ this.destroy();
204
+ this.player.emit("queueEnd", this);
205
+ }, this.options.leaveOnEndCooldown || 0).unref();
206
+ this._cooldownsTimeout.set(`queueEnd_${this.guild.id}`, timeout);
207
+ }
208
+ refreshEndCooldown() {
209
+ const existingTimeout = this._cooldownsTimeout.get(`queueEnd_${this.guild.id}`);
210
+ if (this.tracks.length || this.current) {
211
+ clearTimeout(existingTimeout);
212
+ this._cooldownsTimeout.delete(`queueEnd_${this.guild.id}`);
213
+ }
214
+ }
197
215
  /**
198
216
  * Destroys this queue
199
217
  * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy
@@ -234,6 +252,7 @@ class Queue {
234
252
  if (!(track instanceof Track_1.default))
235
253
  throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
236
254
  this.tracks.push(track);
255
+ this.refreshEndCooldown();
237
256
  this.player.emit("trackAdd", this, track);
238
257
  }
239
258
  /**
@@ -246,6 +265,7 @@ class Queue {
246
265
  if (!tracks.every((y) => y instanceof Track_1.default))
247
266
  throw new PlayerError_1.PlayerError("invalid track", PlayerError_1.ErrorStatusCode.INVALID_TRACK);
248
267
  this.tracks.push(...tracks);
268
+ this.refreshEndCooldown();
249
269
  this.player.emit("tracksAdd", this, tracks);
250
270
  }
251
271
  /**
@@ -630,7 +650,9 @@ class Queue {
630
650
  if (this.options.spotifyBridge && track.raw.source === "spotify" && !track.raw.engine) {
631
651
  track.raw.engine = await youtube_sr_1.default.search(`${track.author} ${track.title}`, { type: "video" })
632
652
  .then((res) => res[0].url)
633
- .catch(() => null);
653
+ .catch(() => {
654
+ /* void */
655
+ });
634
656
  spotifyResolved = true;
635
657
  }
636
658
  const url = track.raw.source === "spotify" ? track.raw.engine : track.url;
@@ -689,9 +711,7 @@ class Queue {
689
711
  if (tslib_1.__classPrivateFieldGet(this, _Queue_instances, "m", _Queue_watchDestroyed).call(this))
690
712
  return;
691
713
  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);
714
+ return this.emitEnd();
695
715
  }
696
716
  let info = await youtube_sr_1.default.getVideo(track.url)
697
717
  .then((x) => x.videos[0])
@@ -702,9 +722,7 @@ class Queue {
702
722
  .then((x) => x[0])
703
723
  .catch(Util_1.Util.noop);
704
724
  if (!info) {
705
- if (this.options.leaveOnEnd)
706
- this.destroy();
707
- return void this.player.emit("queueEnd", this);
725
+ return this.emitEnd();
708
726
  }
709
727
  const nextTrack = new Track_1.default(this.player, {
710
728
  title: info.title,
package/dist/index.d.ts CHANGED
@@ -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
@@ -366,6 +366,8 @@ declare class Queue<T = unknown> {
366
366
  * @returns {Promise<Queue>}
367
367
  */
368
368
  connect(channel: GuildChannelResolvable): Promise<this>;
369
+ private emitEnd;
370
+ private refreshEndCooldown;
369
371
  /**
370
372
  * Destroys this queue
371
373
  * @param {boolean} [disconnect=this.options.leaveOnStop] If it should leave on destroy
@@ -671,6 +673,7 @@ interface PlayerProgressbarOptions {
671
673
  * @property {boolean} [leaveOnStop=true] If it should leave on stop
672
674
  * @property {boolean} [leaveOnEmpty=true] If it should leave on empty
673
675
  * @property {number} [leaveOnEmptyCooldown=1000] The cooldown in ms
676
+ * @property {number} [leaveOnEndCooldown=1000] The cooldown in ms
674
677
  * @property {boolean} [autoSelfDeaf=true] If it should set the bot in deaf mode
675
678
  * @property {YTDLDownloadOptions} [ytdlOptions] The youtube download options
676
679
  * @property {number} [initialVolume=100] The initial player volume
@@ -683,6 +686,7 @@ interface PlayerProgressbarOptions {
683
686
  */
684
687
  interface PlayerOptions {
685
688
  leaveOnEnd?: boolean;
689
+ leaveOnEndCooldown?: number;
686
690
  leaveOnStop?: boolean;
687
691
  leaveOnEmpty?: boolean;
688
692
  leaveOnEmptyCooldown?: number;
@@ -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.0",
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
  }