discord-player 5.2.3-dev → 6.0.0-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
@@ -26,7 +26,6 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
26
26
  * @param {PlayerInitOptions} [options={}] The player init options
27
27
  */
28
28
  constructor(client, options = {}) {
29
- var _a, _b, _c, _d, _e;
30
29
  super();
31
30
  this.options = {
32
31
  autoRegisterExtractor: true,
@@ -44,8 +43,8 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
44
43
  * @type {Client}
45
44
  */
46
45
  this.client = client;
47
- if (((_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.intents) && !new discord_js_1.Intents((_d = (_c = this.client) === null || _c === void 0 ? void 0 : _c.options) === null || _d === void 0 ? void 0 : _d.intents).has(discord_js_1.Intents.FLAGS.GUILD_VOICE_STATES)) {
48
- throw new PlayerError_1.PlayerError('client is missing "GUILD_VOICE_STATES" intent');
46
+ if (this.client?.options?.intents && !new discord_js_1.IntentsBitField(this.client?.options?.intents).has(discord_js_1.IntentsBitField.Flags.GuildVoiceStates)) {
47
+ throw new PlayerError_1.PlayerError('client is missing "GuildVoiceStates" intent');
49
48
  }
50
49
  /**
51
50
  * The extractors collection
@@ -53,7 +52,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
53
52
  */
54
53
  this.options = Object.assign(this.options, options);
55
54
  this.client.on("voiceStateUpdate", this._handleVoiceState.bind(this));
56
- if ((_e = this.options) === null || _e === void 0 ? void 0 : _e.autoRegisterExtractor) {
55
+ if (this.options?.autoRegisterExtractor) {
57
56
  let nv; // eslint-disable-line @typescript-eslint/no-explicit-any
58
57
  if ((nv = Util_1.Util.require("@discord-player/extractor"))) {
59
58
  ["Attachment", "Facebook", "Reverbnation", "Vimeo"].forEach((ext) => void this.use(ext, nv[ext]));
@@ -71,69 +70,14 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
71
70
  const queue = this.getQueue(oldState.guild.id);
72
71
  if (!queue)
73
72
  return;
74
- if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.me.id) {
75
- try {
76
- queue.destroy();
77
- }
78
- catch (_a) {
79
- /* noop */
80
- }
81
- return void this.emit("botDisconnect", queue);
82
- }
83
- if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.me.id) {
84
- if (newState.serverMute || !newState.serverMute) {
85
- queue.setPaused(newState.serverMute);
86
- }
87
- else if (newState.suppress || !newState.suppress) {
88
- if (newState.suppress)
89
- newState.guild.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
90
- queue.setPaused(newState.suppress);
91
- }
92
- }
93
- if (oldState.channelId === newState.channelId && newState.member.id === newState.guild.me.id) {
94
- if (oldState.serverMute !== newState.serverMute) {
95
- queue.setPaused(newState.serverMute);
96
- }
97
- else if (oldState.suppress !== newState.suppress) {
98
- if (newState.suppress)
99
- newState.guild.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
100
- queue.setPaused(newState.suppress);
101
- }
102
- }
103
- if (queue.connection && !newState.channelId && oldState.channelId === queue.connection.channel.id) {
104
- if (!Util_1.Util.isVoiceEmpty(queue.connection.channel))
105
- return;
106
- const timeout = setTimeout(() => {
73
+ if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
74
+ if (queue?.connection && newState.member.id === newState.guild.members.me.id)
75
+ queue.connection.channel = newState.channel;
76
+ if (newState.member.id === newState.guild.members.me.id || (newState.member.id !== newState.guild.members.me.id && oldState.channelId === queue.connection.channel.id)) {
107
77
  if (!Util_1.Util.isVoiceEmpty(queue.connection.channel))
108
78
  return;
109
- if (!this.queues.has(queue.guild.id))
110
- return;
111
- if (queue.options.leaveOnEmpty)
112
- queue.destroy();
113
- this.emit("channelEmpty", queue);
114
- }, queue.options.leaveOnEmptyCooldown || 0).unref();
115
- queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
116
- }
117
- if (queue.connection && newState.channelId && newState.channelId === queue.connection.channel.id) {
118
- const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
119
- const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel);
120
- if (!channelEmpty && emptyTimeout) {
121
- clearTimeout(emptyTimeout);
122
- queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
123
- }
124
- }
125
- if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId && newState.member.id === newState.guild.me.id) {
126
- if (queue.connection && newState.member.id === newState.guild.me.id)
127
- queue.connection.channel = newState.channel;
128
- const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
129
- const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel);
130
- if (!channelEmpty && emptyTimeout) {
131
- clearTimeout(emptyTimeout);
132
- queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
133
- }
134
- else {
135
79
  const timeout = setTimeout(() => {
136
- if (queue.connection && !Util_1.Util.isVoiceEmpty(queue.connection.channel))
80
+ if (!Util_1.Util.isVoiceEmpty(queue.connection.channel))
137
81
  return;
138
82
  if (!this.queues.has(queue.guild.id))
139
83
  return;
@@ -143,6 +87,58 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
143
87
  }, queue.options.leaveOnEmptyCooldown || 0).unref();
144
88
  queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
145
89
  }
90
+ if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) {
91
+ if (newState.serverMute || !newState.serverMute) {
92
+ queue.setPaused(newState.serverMute);
93
+ }
94
+ else if (newState.suppress || !newState.suppress) {
95
+ if (newState.suppress)
96
+ newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
97
+ queue.setPaused(newState.suppress);
98
+ }
99
+ }
100
+ if (oldState.channelId === newState.channelId && oldState.member.id === newState.guild.members.me.id) {
101
+ if (oldState.serverMute !== newState.serverMute) {
102
+ queue.setPaused(newState.serverMute);
103
+ }
104
+ else if (oldState.suppress !== newState.suppress) {
105
+ if (newState.suppress)
106
+ newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
107
+ queue.setPaused(newState.suppress);
108
+ }
109
+ }
110
+ if (oldState.member.id === this.client.user.id && !newState.channelId) {
111
+ queue.destroy();
112
+ return void this.emit("botDisconnect", queue);
113
+ }
114
+ if (!queue.connection || !queue.connection.channel)
115
+ return;
116
+ if (!oldState.channelId || newState.channelId) {
117
+ const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
118
+ const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel);
119
+ if (newState.channelId === queue.connection.channel.id) {
120
+ if (!channelEmpty && emptyTimeout) {
121
+ clearTimeout(emptyTimeout);
122
+ queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
123
+ }
124
+ }
125
+ }
126
+ else {
127
+ if (oldState.channelId === queue.connection.channel.id) {
128
+ if (!Util_1.Util.isVoiceEmpty(queue.connection.channel))
129
+ return;
130
+ const timeout = setTimeout(() => {
131
+ if (!Util_1.Util.isVoiceEmpty(queue.connection.channel))
132
+ return;
133
+ if (!this.queues.has(queue.guild.id))
134
+ return;
135
+ if (queue.options.leaveOnEmpty)
136
+ queue.destroy();
137
+ this.emit("channelEmpty", queue);
138
+ }, queue.options.leaveOnEmptyCooldown || 0).unref();
139
+ queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
140
+ }
141
+ }
146
142
  }
147
143
  }
148
144
  /**
@@ -152,7 +148,6 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
152
148
  * @returns {Queue}
153
149
  */
154
150
  createQueue(guild, queueInitOptions = {}) {
155
- var _a, _b;
156
151
  guild = this.client.guilds.resolve(guild);
157
152
  if (!guild)
158
153
  throw new PlayerError_1.PlayerError("Unknown Guild", PlayerError_1.ErrorStatusCode.UNKNOWN_GUILD);
@@ -160,8 +155,8 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
160
155
  return this.queues.get(guild.id);
161
156
  const _meta = queueInitOptions.metadata;
162
157
  delete queueInitOptions["metadata"];
163
- (_a = queueInitOptions.volumeSmoothness) !== null && _a !== void 0 ? _a : (queueInitOptions.volumeSmoothness = 0.08);
164
- (_b = queueInitOptions.ytdlOptions) !== null && _b !== void 0 ? _b : (queueInitOptions.ytdlOptions = this.options.ytdlOptions);
158
+ queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = 0.08);
159
+ queueInitOptions.ytdlOptions ?? (queueInitOptions.ytdlOptions = this.options.ytdlOptions);
165
160
  const queue = new Queue_1.Queue(this, guild, queueInitOptions);
166
161
  queue.metadata = _meta;
167
162
  this.queues.set(guild.id, queue);
@@ -191,7 +186,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
191
186
  try {
192
187
  prev.destroy();
193
188
  }
194
- catch (_a) { } // eslint-disable-line no-empty
189
+ catch { } // eslint-disable-line no-empty
195
190
  this.queues.delete(guild.id);
196
191
  return prev;
197
192
  }
@@ -206,281 +201,290 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
206
201
  * @param {SearchOptions} options The search options
207
202
  * @returns {Promise<PlayerSearchResult>}
208
203
  */
209
- search(query, options) {
210
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18;
211
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
212
- if (query instanceof Track_1.default)
213
- return { playlist: query.playlist || null, tracks: [query] };
214
- if (!options)
215
- throw new PlayerError_1.PlayerError("DiscordPlayer#search needs search options!", PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE);
216
- options.requestedBy = this.client.users.resolve(options.requestedBy);
217
- if (!("searchEngine" in options))
218
- options.searchEngine = types_1.QueryType.AUTO;
219
- if (typeof options.searchEngine === "string" && this.extractors.has(options.searchEngine)) {
220
- const extractor = this.extractors.get(options.searchEngine);
221
- if (!extractor.validate(query))
204
+ async search(query, options) {
205
+ if (query instanceof Track_1.default)
206
+ return { playlist: query.playlist || null, tracks: [query] };
207
+ if (!options)
208
+ throw new PlayerError_1.PlayerError("DiscordPlayer#search needs search options!", PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE);
209
+ options.requestedBy = this.client.users.resolve(options.requestedBy);
210
+ if (!("searchEngine" in options))
211
+ options.searchEngine = types_1.QueryType.AUTO;
212
+ if (typeof options.searchEngine === "string" && this.extractors.has(options.searchEngine)) {
213
+ const extractor = this.extractors.get(options.searchEngine);
214
+ if (!extractor.validate(query))
215
+ return { playlist: null, tracks: [] };
216
+ const data = await extractor.handle(query);
217
+ if (data && data.data.length) {
218
+ const playlist = !data.playlist
219
+ ? null
220
+ : new Playlist_1.Playlist(this, {
221
+ ...data.playlist,
222
+ tracks: []
223
+ });
224
+ const tracks = data.data.map((m) => new Track_1.default(this, {
225
+ ...m,
226
+ requestedBy: options.requestedBy,
227
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)),
228
+ playlist: playlist
229
+ }));
230
+ if (playlist)
231
+ playlist.tracks = tracks;
232
+ return { playlist: playlist, tracks: tracks };
233
+ }
234
+ }
235
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
236
+ for (const [_, extractor] of this.extractors) {
237
+ if (options.blockExtractor)
238
+ break;
239
+ if (!extractor.validate(query))
240
+ continue;
241
+ const data = await extractor.handle(query);
242
+ if (data && data.data.length) {
243
+ const playlist = !data.playlist
244
+ ? null
245
+ : new Playlist_1.Playlist(this, {
246
+ ...data.playlist,
247
+ tracks: []
248
+ });
249
+ const tracks = data.data.map((m) => new Track_1.default(this, {
250
+ ...m,
251
+ requestedBy: options.requestedBy,
252
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)),
253
+ playlist: playlist
254
+ }));
255
+ if (playlist)
256
+ playlist.tracks = tracks;
257
+ return { playlist: playlist, tracks: tracks };
258
+ }
259
+ }
260
+ const qt = options.searchEngine === types_1.QueryType.AUTO ? QueryResolver_1.QueryResolver.resolve(query) : options.searchEngine;
261
+ switch (qt) {
262
+ case types_1.QueryType.YOUTUBE_VIDEO: {
263
+ const info = await (0, ytdl_core_1.getInfo)(query, this.options.ytdlOptions).catch(Util_1.Util.noop);
264
+ if (!info)
222
265
  return { playlist: null, tracks: [] };
223
- const data = yield extractor.handle(query);
224
- if (data && data.data.length) {
225
- const playlist = !data.playlist
226
- ? null
227
- : new Playlist_1.Playlist(this, Object.assign(Object.assign({}, data.playlist), { tracks: [] }));
228
- const tracks = data.data.map((m) => new Track_1.default(this, Object.assign(Object.assign({}, m), { requestedBy: options.requestedBy, duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)), playlist: playlist })));
229
- if (playlist)
230
- playlist.tracks = tracks;
231
- return { playlist: playlist, tracks: tracks };
232
- }
266
+ const track = new Track_1.default(this, {
267
+ title: info.videoDetails.title,
268
+ description: info.videoDetails.description,
269
+ author: info.videoDetails.author?.name,
270
+ url: info.videoDetails.video_url,
271
+ requestedBy: options.requestedBy,
272
+ thumbnail: Util_1.Util.last(info.videoDetails.thumbnails)?.url,
273
+ views: parseInt(info.videoDetails.viewCount.replace(/[^0-9]/g, "")) || 0,
274
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(parseInt(info.videoDetails.lengthSeconds) * 1000)),
275
+ source: "youtube",
276
+ raw: info
277
+ });
278
+ return { playlist: null, tracks: [track] };
233
279
  }
234
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
235
- for (const [_, extractor] of this.extractors) {
236
- if (options.blockExtractor)
237
- break;
238
- if (!extractor.validate(query))
239
- continue;
240
- const data = yield extractor.handle(query);
241
- if (data && data.data.length) {
242
- const playlist = !data.playlist
243
- ? null
244
- : new Playlist_1.Playlist(this, Object.assign(Object.assign({}, data.playlist), { tracks: [] }));
245
- const tracks = data.data.map((m) => new Track_1.default(this, Object.assign(Object.assign({}, m), { requestedBy: options.requestedBy, duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)), playlist: playlist })));
246
- if (playlist)
247
- playlist.tracks = tracks;
248
- return { playlist: playlist, tracks: tracks };
249
- }
280
+ case types_1.QueryType.YOUTUBE_SEARCH: {
281
+ const videos = await youtube_sr_1.default.search(query, {
282
+ type: "video"
283
+ }).catch(Util_1.Util.noop);
284
+ if (!videos)
285
+ return { playlist: null, tracks: [] };
286
+ const tracks = videos.map((m) => {
287
+ m.source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any
288
+ return new Track_1.default(this, {
289
+ title: m.title,
290
+ description: m.description,
291
+ author: m.channel?.name,
292
+ url: m.url,
293
+ requestedBy: options.requestedBy,
294
+ thumbnail: m.thumbnail?.displayThumbnailURL("maxresdefault"),
295
+ views: m.views,
296
+ duration: m.durationFormatted,
297
+ source: "youtube",
298
+ raw: m
299
+ });
300
+ });
301
+ return { playlist: null, tracks };
250
302
  }
251
- const qt = options.searchEngine === types_1.QueryType.AUTO ? QueryResolver_1.QueryResolver.resolve(query) : options.searchEngine;
252
- switch (qt) {
253
- case types_1.QueryType.YOUTUBE_VIDEO: {
254
- const info = yield (0, ytdl_core_1.getInfo)(query, this.options.ytdlOptions).catch(Util_1.Util.noop);
255
- if (!info)
256
- return { playlist: null, tracks: [] };
303
+ case types_1.QueryType.SOUNDCLOUD_TRACK:
304
+ case types_1.QueryType.SOUNDCLOUD_SEARCH: {
305
+ const result = QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await soundcloud.search(query, "track").catch(() => []);
306
+ if (!result || !result.length)
307
+ return { playlist: null, tracks: [] };
308
+ const res = [];
309
+ for (const r of result) {
310
+ const trackInfo = await soundcloud.getSongInfo(r.url).catch(Util_1.Util.noop);
311
+ if (!trackInfo)
312
+ continue;
257
313
  const track = new Track_1.default(this, {
258
- title: info.videoDetails.title,
259
- description: info.videoDetails.description,
260
- author: (_a = info.videoDetails.author) === null || _a === void 0 ? void 0 : _a.name,
261
- url: info.videoDetails.video_url,
314
+ title: trackInfo.title,
315
+ url: trackInfo.url,
316
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(trackInfo.duration)),
317
+ description: trackInfo.description,
318
+ thumbnail: trackInfo.thumbnail,
319
+ views: trackInfo.playCount,
320
+ author: trackInfo.author.name,
262
321
  requestedBy: options.requestedBy,
263
- thumbnail: (_b = Util_1.Util.last(info.videoDetails.thumbnails)) === null || _b === void 0 ? void 0 : _b.url,
264
- views: parseInt(info.videoDetails.viewCount.replace(/[^0-9]/g, "")) || 0,
265
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(parseInt(info.videoDetails.lengthSeconds) * 1000)),
266
- source: "youtube",
267
- raw: info
322
+ source: "soundcloud",
323
+ engine: trackInfo
268
324
  });
269
- return { playlist: null, tracks: [track] };
325
+ res.push(track);
270
326
  }
271
- case types_1.QueryType.YOUTUBE_SEARCH: {
272
- const videos = yield youtube_sr_1.default.search(query, {
273
- type: "video"
274
- }).catch(Util_1.Util.noop);
275
- if (!videos)
276
- return { playlist: null, tracks: [] };
277
- const tracks = videos.map((m) => {
278
- var _a, _b;
279
- m.source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any
280
- return new Track_1.default(this, {
281
- title: m.title,
282
- description: m.description,
283
- author: (_a = m.channel) === null || _a === void 0 ? void 0 : _a.name,
284
- url: m.url,
327
+ return { playlist: null, tracks: res };
328
+ }
329
+ case types_1.QueryType.SPOTIFY_SONG: {
330
+ const spotifyData = await (0, spotify_url_info_1.default)(Util_1.Util.getFetch()).getData(query).catch(Util_1.Util.noop);
331
+ if (!spotifyData)
332
+ return { playlist: null, tracks: [] };
333
+ const spotifyTrack = new Track_1.default(this, {
334
+ title: spotifyData.name,
335
+ description: spotifyData.description ?? "",
336
+ author: spotifyData.artists[0]?.name ?? "Unknown Artist",
337
+ url: spotifyData.external_urls?.spotify ?? query,
338
+ thumbnail: spotifyData.album?.images[0]?.url ?? spotifyData.preview_url?.length
339
+ ? `https://i.scdn.co/image/${spotifyData.preview_url?.split("?cid=")[1]}`
340
+ : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
341
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms)),
342
+ views: 0,
343
+ requestedBy: options.requestedBy,
344
+ source: "spotify"
345
+ });
346
+ return { playlist: null, tracks: [spotifyTrack] };
347
+ }
348
+ case types_1.QueryType.SPOTIFY_PLAYLIST:
349
+ case types_1.QueryType.SPOTIFY_ALBUM: {
350
+ const spotifyPlaylist = await (0, spotify_url_info_1.default)(await Util_1.Util.getFetch())
351
+ .getData(query)
352
+ .catch(Util_1.Util.noop);
353
+ if (!spotifyPlaylist)
354
+ return { playlist: null, tracks: [] };
355
+ const playlist = new Playlist_1.Playlist(this, {
356
+ title: spotifyPlaylist.name ?? spotifyPlaylist.title,
357
+ description: spotifyPlaylist.description ?? "",
358
+ thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
359
+ type: spotifyPlaylist.type,
360
+ source: "spotify",
361
+ author: spotifyPlaylist.type !== "playlist"
362
+ ? {
363
+ name: spotifyPlaylist.artists[0]?.name ?? "Unknown Artist",
364
+ url: spotifyPlaylist.artists[0]?.external_urls?.spotify ?? null
365
+ }
366
+ : {
367
+ name: spotifyPlaylist.owner?.display_name ?? spotifyPlaylist.owner?.id ?? "Unknown Artist",
368
+ url: spotifyPlaylist.owner?.external_urls?.spotify ?? null
369
+ },
370
+ tracks: [],
371
+ id: spotifyPlaylist.id,
372
+ url: spotifyPlaylist.external_urls?.spotify ?? query,
373
+ rawPlaylist: spotifyPlaylist
374
+ });
375
+ if (spotifyPlaylist.type !== "playlist") {
376
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
377
+ playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
378
+ const data = new Track_1.default(this, {
379
+ title: m.name ?? "",
380
+ description: m.description ?? "",
381
+ author: m.artists[0]?.name ?? "Unknown Artist",
382
+ url: m.external_urls?.spotify ?? query,
383
+ thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
384
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration_ms)),
385
+ views: 0,
285
386
  requestedBy: options.requestedBy,
286
- thumbnail: (_b = m.thumbnail) === null || _b === void 0 ? void 0 : _b.displayThumbnailURL("maxresdefault"),
287
- views: m.views,
288
- duration: m.durationFormatted,
289
- source: "youtube",
290
- raw: m
387
+ playlist,
388
+ source: "spotify"
291
389
  });
390
+ return data;
292
391
  });
293
- return { playlist: null, tracks };
294
392
  }
295
- case types_1.QueryType.SOUNDCLOUD_TRACK:
296
- case types_1.QueryType.SOUNDCLOUD_SEARCH: {
297
- const result = QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : yield soundcloud.search(query, "track").catch(() => []);
298
- if (!result || !result.length)
299
- return { playlist: null, tracks: [] };
300
- const res = [];
301
- for (const r of result) {
302
- const trackInfo = yield soundcloud.getSongInfo(r.url).catch(Util_1.Util.noop);
303
- if (!trackInfo)
304
- continue;
305
- const track = new Track_1.default(this, {
306
- title: trackInfo.title,
307
- url: trackInfo.url,
308
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(trackInfo.duration)),
309
- description: trackInfo.description,
310
- thumbnail: trackInfo.thumbnail,
311
- views: trackInfo.playCount,
312
- author: trackInfo.author.name,
393
+ else {
394
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
395
+ playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
396
+ const data = new Track_1.default(this, {
397
+ title: m.track.name ?? "",
398
+ description: m.track.description ?? "",
399
+ author: m.track.artists[0]?.name ?? "Unknown Artist",
400
+ url: m.track.external_urls?.spotify ?? query,
401
+ thumbnail: m.track.album?.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
402
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.track.duration_ms)),
403
+ views: 0,
313
404
  requestedBy: options.requestedBy,
314
- source: "soundcloud",
315
- engine: trackInfo
405
+ playlist,
406
+ source: "spotify"
316
407
  });
317
- res.push(track);
318
- }
319
- return { playlist: null, tracks: res };
320
- }
321
- case types_1.QueryType.SPOTIFY_SONG: {
322
- const spotifyData = yield spotify_url_info_1.default.getData(query).catch(Util_1.Util.noop);
323
- if (!spotifyData)
324
- return { playlist: null, tracks: [] };
325
- const spotifyTrack = new Track_1.default(this, {
326
- title: spotifyData.name,
327
- description: (_c = spotifyData.description) !== null && _c !== void 0 ? _c : "",
328
- author: (_e = (_d = spotifyData.artists[0]) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : "Unknown Artist",
329
- url: (_g = (_f = spotifyData.external_urls) === null || _f === void 0 ? void 0 : _f.spotify) !== null && _g !== void 0 ? _g : query,
330
- thumbnail: ((_k = (_j = (_h = spotifyData.album) === null || _h === void 0 ? void 0 : _h.images[0]) === null || _j === void 0 ? void 0 : _j.url) !== null && _k !== void 0 ? _k : (_l = spotifyData.preview_url) === null || _l === void 0 ? void 0 : _l.length)
331
- ? `https://i.scdn.co/image/${(_m = spotifyData.preview_url) === null || _m === void 0 ? void 0 : _m.split("?cid=")[1]}`
332
- : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
333
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(spotifyData.duration_ms)),
334
- views: 0,
335
- requestedBy: options.requestedBy,
336
- source: "spotify"
408
+ return data;
337
409
  });
338
- return { playlist: null, tracks: [spotifyTrack] };
339
- }
340
- case types_1.QueryType.SPOTIFY_PLAYLIST:
341
- case types_1.QueryType.SPOTIFY_ALBUM: {
342
- const spotifyPlaylist = yield spotify_url_info_1.default.getData(query).catch(Util_1.Util.noop);
343
- if (!spotifyPlaylist)
344
- return { playlist: null, tracks: [] };
345
- const playlist = new Playlist_1.Playlist(this, {
346
- title: (_o = spotifyPlaylist.name) !== null && _o !== void 0 ? _o : spotifyPlaylist.title,
347
- description: (_p = spotifyPlaylist.description) !== null && _p !== void 0 ? _p : "",
348
- thumbnail: (_r = (_q = spotifyPlaylist.images[0]) === null || _q === void 0 ? void 0 : _q.url) !== null && _r !== void 0 ? _r : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
349
- type: spotifyPlaylist.type,
350
- source: "spotify",
351
- author: spotifyPlaylist.type !== "playlist"
352
- ? {
353
- name: (_t = (_s = spotifyPlaylist.artists[0]) === null || _s === void 0 ? void 0 : _s.name) !== null && _t !== void 0 ? _t : "Unknown Artist",
354
- url: (_w = (_v = (_u = spotifyPlaylist.artists[0]) === null || _u === void 0 ? void 0 : _u.external_urls) === null || _v === void 0 ? void 0 : _v.spotify) !== null && _w !== void 0 ? _w : null
355
- }
356
- : {
357
- name: (_0 = (_y = (_x = spotifyPlaylist.owner) === null || _x === void 0 ? void 0 : _x.display_name) !== null && _y !== void 0 ? _y : (_z = spotifyPlaylist.owner) === null || _z === void 0 ? void 0 : _z.id) !== null && _0 !== void 0 ? _0 : "Unknown Artist",
358
- url: (_3 = (_2 = (_1 = spotifyPlaylist.owner) === null || _1 === void 0 ? void 0 : _1.external_urls) === null || _2 === void 0 ? void 0 : _2.spotify) !== null && _3 !== void 0 ? _3 : null
359
- },
360
- tracks: [],
361
- id: spotifyPlaylist.id,
362
- url: (_5 = (_4 = spotifyPlaylist.external_urls) === null || _4 === void 0 ? void 0 : _4.spotify) !== null && _5 !== void 0 ? _5 : query,
363
- rawPlaylist: spotifyPlaylist
364
- });
365
- if (spotifyPlaylist.type !== "playlist") {
366
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
367
- playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
368
- var _a, _b, _c, _d, _e, _f, _g, _h;
369
- const data = new Track_1.default(this, {
370
- title: (_a = m.name) !== null && _a !== void 0 ? _a : "",
371
- description: (_b = m.description) !== null && _b !== void 0 ? _b : "",
372
- author: (_d = (_c = m.artists[0]) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "Unknown Artist",
373
- url: (_f = (_e = m.external_urls) === null || _e === void 0 ? void 0 : _e.spotify) !== null && _f !== void 0 ? _f : query,
374
- thumbnail: (_h = (_g = spotifyPlaylist.images[0]) === null || _g === void 0 ? void 0 : _g.url) !== null && _h !== void 0 ? _h : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
375
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration_ms)),
376
- views: 0,
377
- requestedBy: options.requestedBy,
378
- playlist,
379
- source: "spotify"
380
- });
381
- return data;
382
- });
383
- }
384
- else {
385
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
386
- playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
387
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
388
- const data = new Track_1.default(this, {
389
- title: (_a = m.track.name) !== null && _a !== void 0 ? _a : "",
390
- description: (_b = m.track.description) !== null && _b !== void 0 ? _b : "",
391
- author: (_d = (_c = m.track.artists[0]) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "Unknown Artist",
392
- url: (_f = (_e = m.track.external_urls) === null || _e === void 0 ? void 0 : _e.spotify) !== null && _f !== void 0 ? _f : query,
393
- thumbnail: (_j = (_h = (_g = m.track.album) === null || _g === void 0 ? void 0 : _g.images[0]) === null || _h === void 0 ? void 0 : _h.url) !== null && _j !== void 0 ? _j : "https://www.scdn.co/i/_global/twitter_card-default.jpg",
394
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.track.duration_ms)),
395
- views: 0,
396
- requestedBy: options.requestedBy,
397
- playlist,
398
- source: "spotify"
399
- });
400
- return data;
401
- });
402
- }
403
- return { playlist: playlist, tracks: playlist.tracks };
404
410
  }
405
- case types_1.QueryType.SOUNDCLOUD_PLAYLIST: {
406
- const data = yield soundcloud.getPlaylist(query).catch(Util_1.Util.noop);
407
- if (!data)
408
- return { playlist: null, tracks: [] };
409
- const res = new Playlist_1.Playlist(this, {
410
- title: data.title,
411
- description: (_6 = data.description) !== null && _6 !== void 0 ? _6 : "",
412
- thumbnail: (_7 = data.thumbnail) !== null && _7 !== void 0 ? _7 : "https://soundcloud.com/pwa-icon-192.png",
413
- type: "playlist",
411
+ return { playlist: playlist, tracks: playlist.tracks };
412
+ }
413
+ case types_1.QueryType.SOUNDCLOUD_PLAYLIST: {
414
+ const data = await soundcloud.getPlaylist(query).catch(Util_1.Util.noop);
415
+ if (!data)
416
+ return { playlist: null, tracks: [] };
417
+ const res = new Playlist_1.Playlist(this, {
418
+ title: data.title,
419
+ description: data.description ?? "",
420
+ thumbnail: data.thumbnail ?? "https://soundcloud.com/pwa-icon-192.png",
421
+ type: "playlist",
422
+ source: "soundcloud",
423
+ author: {
424
+ name: data.author?.name ?? data.author?.username ?? "Unknown Artist",
425
+ url: data.author?.profile
426
+ },
427
+ tracks: [],
428
+ id: `${data.id}`,
429
+ url: data.url,
430
+ rawPlaylist: data
431
+ });
432
+ for (const song of data.tracks) {
433
+ const track = new Track_1.default(this, {
434
+ title: song.title,
435
+ description: song.description ?? "",
436
+ author: song.author?.username ?? song.author?.name ?? "Unknown Artist",
437
+ url: song.url,
438
+ thumbnail: song.thumbnail,
439
+ duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(song.duration)),
440
+ views: song.playCount ?? 0,
441
+ requestedBy: options.requestedBy,
442
+ playlist: res,
414
443
  source: "soundcloud",
415
- author: {
416
- name: (_11 = (_9 = (_8 = data.author) === null || _8 === void 0 ? void 0 : _8.name) !== null && _9 !== void 0 ? _9 : (_10 = data.author) === null || _10 === void 0 ? void 0 : _10.username) !== null && _11 !== void 0 ? _11 : "Unknown Artist",
417
- url: (_12 = data.author) === null || _12 === void 0 ? void 0 : _12.profile
418
- },
419
- tracks: [],
420
- id: `${data.id}`,
421
- url: data.url,
422
- rawPlaylist: data
423
- });
424
- for (const song of data.tracks) {
425
- const track = new Track_1.default(this, {
426
- title: song.title,
427
- description: (_13 = song.description) !== null && _13 !== void 0 ? _13 : "",
428
- author: (_17 = (_15 = (_14 = song.author) === null || _14 === void 0 ? void 0 : _14.username) !== null && _15 !== void 0 ? _15 : (_16 = song.author) === null || _16 === void 0 ? void 0 : _16.name) !== null && _17 !== void 0 ? _17 : "Unknown Artist",
429
- url: song.url,
430
- thumbnail: song.thumbnail,
431
- duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(song.duration)),
432
- views: (_18 = song.playCount) !== null && _18 !== void 0 ? _18 : 0,
433
- requestedBy: options.requestedBy,
434
- playlist: res,
435
- source: "soundcloud",
436
- engine: song
437
- });
438
- res.tracks.push(track);
439
- }
440
- return { playlist: res, tracks: res.tracks };
441
- }
442
- case types_1.QueryType.YOUTUBE_PLAYLIST: {
443
- const ytpl = yield youtube_sr_1.default.getPlaylist(query).catch(Util_1.Util.noop);
444
- if (!ytpl)
445
- return { playlist: null, tracks: [] };
446
- yield ytpl.fetch().catch(Util_1.Util.noop);
447
- const playlist = new Playlist_1.Playlist(this, {
448
- title: ytpl.title,
449
- thumbnail: ytpl.thumbnail,
450
- description: "",
451
- type: "playlist",
452
- source: "youtube",
453
- author: {
454
- name: ytpl.channel.name,
455
- url: ytpl.channel.url
456
- },
457
- tracks: [],
458
- id: ytpl.id,
459
- url: ytpl.url,
460
- rawPlaylist: ytpl
444
+ engine: song
461
445
  });
462
- playlist.tracks = ytpl.videos.map((video) => {
463
- var _a;
464
- return new Track_1.default(this, {
465
- title: video.title,
466
- description: video.description,
467
- author: (_a = video.channel) === null || _a === void 0 ? void 0 : _a.name,
468
- url: video.url,
469
- requestedBy: options.requestedBy,
470
- thumbnail: video.thumbnail.url,
471
- views: video.views,
472
- duration: video.durationFormatted,
473
- raw: video,
474
- playlist: playlist,
475
- source: "youtube"
476
- });
477
- });
478
- return { playlist: playlist, tracks: playlist.tracks };
446
+ res.tracks.push(track);
479
447
  }
480
- default:
448
+ return { playlist: res, tracks: res.tracks };
449
+ }
450
+ case types_1.QueryType.YOUTUBE_PLAYLIST: {
451
+ const ytpl = await youtube_sr_1.default.getPlaylist(query).catch(Util_1.Util.noop);
452
+ if (!ytpl)
481
453
  return { playlist: null, tracks: [] };
454
+ await ytpl.fetch().catch(Util_1.Util.noop);
455
+ const playlist = new Playlist_1.Playlist(this, {
456
+ title: ytpl.title,
457
+ thumbnail: ytpl.thumbnail,
458
+ description: "",
459
+ type: "playlist",
460
+ source: "youtube",
461
+ author: {
462
+ name: ytpl.channel.name,
463
+ url: ytpl.channel.url
464
+ },
465
+ tracks: [],
466
+ id: ytpl.id,
467
+ url: ytpl.url,
468
+ rawPlaylist: ytpl
469
+ });
470
+ playlist.tracks = ytpl.videos.map((video) => new Track_1.default(this, {
471
+ title: video.title,
472
+ description: video.description,
473
+ author: video.channel?.name,
474
+ url: video.url,
475
+ requestedBy: options.requestedBy,
476
+ thumbnail: video.thumbnail.url,
477
+ views: video.views,
478
+ duration: video.durationFormatted,
479
+ raw: video,
480
+ playlist: playlist,
481
+ source: "youtube"
482
+ }));
483
+ return { playlist: playlist, tracks: playlist.tracks };
482
484
  }
483
- });
485
+ default:
486
+ return { playlist: null, tracks: [] };
487
+ }
484
488
  }
485
489
  /**
486
490
  * Registers extractor