discord-player 5.2.3-dev → 5.3.0-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/LICENSE +21 -21
- package/README.md +23 -19
- package/dist/Player.js +307 -285
- package/dist/Structures/ExtractorModel.js +19 -24
- package/dist/Structures/Playlist.js +1 -2
- package/dist/Structures/Queue.js +226 -237
- package/dist/Structures/Track.js +11 -14
- package/dist/VoiceInterface/StreamDispatcher.js +33 -41
- package/dist/VoiceInterface/VoiceUtils.js +14 -32
- package/dist/index.d.ts +24 -20
- package/dist/smoothVolume.js +1 -1
- package/dist/utils/AudioFilters.js +2 -2
- package/dist/utils/Util.js +36 -1
- package/package.json +24 -28
package/dist/Player.js
CHANGED
|
@@ -23,10 +23,9 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
23
23
|
/**
|
|
24
24
|
* Creates new Discord Player
|
|
25
25
|
* @param {Client} client The Discord Client
|
|
26
|
-
* @param {PlayerInitOptions} [options
|
|
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 (
|
|
48
|
-
throw new PlayerError_1.PlayerError('client is missing "
|
|
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 (
|
|
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]));
|
|
@@ -69,35 +68,41 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
69
68
|
*/
|
|
70
69
|
_handleVoiceState(oldState, newState) {
|
|
71
70
|
const queue = this.getQueue(oldState.guild.id);
|
|
72
|
-
if (!queue)
|
|
71
|
+
if (!queue || !queue.connection)
|
|
73
72
|
return;
|
|
74
|
-
if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.me.id) {
|
|
73
|
+
if (oldState.channelId && !newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
75
74
|
try {
|
|
76
75
|
queue.destroy();
|
|
77
76
|
}
|
|
78
|
-
catch
|
|
77
|
+
catch {
|
|
79
78
|
/* noop */
|
|
80
79
|
}
|
|
81
80
|
return void this.emit("botDisconnect", queue);
|
|
82
81
|
}
|
|
83
|
-
if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.me.id) {
|
|
84
|
-
if (
|
|
85
|
-
|
|
82
|
+
if (!oldState.channelId && newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
83
|
+
if (!oldState.serverMute && newState.serverMute) {
|
|
84
|
+
// state.serverMute can be null
|
|
85
|
+
queue.setPaused(!!newState.serverMute);
|
|
86
86
|
}
|
|
87
|
-
else if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
else if (!oldState.suppress && newState.suppress) {
|
|
88
|
+
// state.suppress can be null
|
|
89
|
+
queue.setPaused(!!newState.suppress);
|
|
90
|
+
if (newState.suppress) {
|
|
91
|
+
newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
|
|
92
|
+
}
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
|
-
if (oldState.channelId === newState.channelId && newState.member.id === newState.guild.me.id) {
|
|
94
|
-
if (oldState.serverMute
|
|
95
|
-
|
|
95
|
+
if (oldState.channelId === newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
96
|
+
if (!oldState.serverMute && newState.serverMute) {
|
|
97
|
+
// state.serverMute can be null
|
|
98
|
+
queue.setPaused(!!newState.serverMute);
|
|
96
99
|
}
|
|
97
|
-
else if (oldState.suppress
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
else if (!oldState.suppress && newState.suppress) {
|
|
101
|
+
// state.suppress can be null
|
|
102
|
+
queue.setPaused(!!newState.suppress);
|
|
103
|
+
if (newState.suppress) {
|
|
104
|
+
newState.guild.members.me.voice.setRequestToSpeak(true).catch(Util_1.Util.noop);
|
|
105
|
+
}
|
|
101
106
|
}
|
|
102
107
|
}
|
|
103
108
|
if (queue.connection && !newState.channelId && oldState.channelId === queue.connection.channel.id) {
|
|
@@ -109,7 +114,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
109
114
|
if (!this.queues.has(queue.guild.id))
|
|
110
115
|
return;
|
|
111
116
|
if (queue.options.leaveOnEmpty)
|
|
112
|
-
queue.destroy();
|
|
117
|
+
queue.destroy(true);
|
|
113
118
|
this.emit("channelEmpty", queue);
|
|
114
119
|
}, queue.options.leaveOnEmptyCooldown || 0).unref();
|
|
115
120
|
queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
|
|
@@ -122,8 +127,8 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
122
127
|
queue._cooldownsTimeout.delete(`empty_${oldState.guild.id}`);
|
|
123
128
|
}
|
|
124
129
|
}
|
|
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)
|
|
130
|
+
if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId && newState.member.id === newState.guild.members.me.id) {
|
|
131
|
+
if (queue.connection && newState.member.id === newState.guild.members.me.id)
|
|
127
132
|
queue.connection.channel = newState.channel;
|
|
128
133
|
const emptyTimeout = queue._cooldownsTimeout.get(`empty_${oldState.guild.id}`);
|
|
129
134
|
const channelEmpty = Util_1.Util.isVoiceEmpty(queue.connection.channel);
|
|
@@ -138,7 +143,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
138
143
|
if (!this.queues.has(queue.guild.id))
|
|
139
144
|
return;
|
|
140
145
|
if (queue.options.leaveOnEmpty)
|
|
141
|
-
queue.destroy();
|
|
146
|
+
queue.destroy(true);
|
|
142
147
|
this.emit("channelEmpty", queue);
|
|
143
148
|
}, queue.options.leaveOnEmptyCooldown || 0).unref();
|
|
144
149
|
queue._cooldownsTimeout.set(`empty_${oldState.guild.id}`, timeout);
|
|
@@ -152,7 +157,6 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
152
157
|
* @returns {Queue}
|
|
153
158
|
*/
|
|
154
159
|
createQueue(guild, queueInitOptions = {}) {
|
|
155
|
-
var _a, _b;
|
|
156
160
|
guild = this.client.guilds.resolve(guild);
|
|
157
161
|
if (!guild)
|
|
158
162
|
throw new PlayerError_1.PlayerError("Unknown Guild", PlayerError_1.ErrorStatusCode.UNKNOWN_GUILD);
|
|
@@ -160,8 +164,8 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
160
164
|
return this.queues.get(guild.id);
|
|
161
165
|
const _meta = queueInitOptions.metadata;
|
|
162
166
|
delete queueInitOptions["metadata"];
|
|
163
|
-
|
|
164
|
-
|
|
167
|
+
queueInitOptions.volumeSmoothness ?? (queueInitOptions.volumeSmoothness = 0.08);
|
|
168
|
+
queueInitOptions.ytdlOptions ?? (queueInitOptions.ytdlOptions = this.options.ytdlOptions);
|
|
165
169
|
const queue = new Queue_1.Queue(this, guild, queueInitOptions);
|
|
166
170
|
queue.metadata = _meta;
|
|
167
171
|
this.queues.set(guild.id, queue);
|
|
@@ -191,7 +195,7 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
191
195
|
try {
|
|
192
196
|
prev.destroy();
|
|
193
197
|
}
|
|
194
|
-
catch
|
|
198
|
+
catch { } // eslint-disable-line no-empty
|
|
195
199
|
this.queues.delete(guild.id);
|
|
196
200
|
return prev;
|
|
197
201
|
}
|
|
@@ -206,281 +210,292 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
206
210
|
* @param {SearchOptions} options The search options
|
|
207
211
|
* @returns {Promise<PlayerSearchResult>}
|
|
208
212
|
*/
|
|
209
|
-
search(query, options) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
options.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
213
|
+
async search(query, options) {
|
|
214
|
+
if (query instanceof Track_1.default)
|
|
215
|
+
return { playlist: query.playlist || null, tracks: [query] };
|
|
216
|
+
if (!options)
|
|
217
|
+
throw new PlayerError_1.PlayerError("DiscordPlayer#search needs search options!", PlayerError_1.ErrorStatusCode.INVALID_ARG_TYPE);
|
|
218
|
+
options.requestedBy = this.client.users.resolve(options.requestedBy);
|
|
219
|
+
if (!("searchEngine" in options))
|
|
220
|
+
options.searchEngine = types_1.QueryType.AUTO;
|
|
221
|
+
if (typeof options.searchEngine === "string" && this.extractors.has(options.searchEngine)) {
|
|
222
|
+
const extractor = this.extractors.get(options.searchEngine);
|
|
223
|
+
if (!extractor.validate(query))
|
|
224
|
+
return { playlist: null, tracks: [] };
|
|
225
|
+
const data = await extractor.handle(query);
|
|
226
|
+
if (data && data.data.length) {
|
|
227
|
+
const playlist = !data.playlist
|
|
228
|
+
? null
|
|
229
|
+
: new Playlist_1.Playlist(this, {
|
|
230
|
+
...data.playlist,
|
|
231
|
+
tracks: []
|
|
232
|
+
});
|
|
233
|
+
const tracks = data.data.map((m) => new Track_1.default(this, {
|
|
234
|
+
...m,
|
|
235
|
+
requestedBy: options.requestedBy,
|
|
236
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)),
|
|
237
|
+
playlist: playlist
|
|
238
|
+
}));
|
|
239
|
+
if (playlist)
|
|
240
|
+
playlist.tracks = tracks;
|
|
241
|
+
return { playlist: playlist, tracks: tracks };
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
245
|
+
for (const [_, extractor] of this.extractors) {
|
|
246
|
+
if (options.blockExtractor)
|
|
247
|
+
break;
|
|
248
|
+
if (!extractor.validate(query))
|
|
249
|
+
continue;
|
|
250
|
+
const data = await extractor.handle(query);
|
|
251
|
+
if (data && data.data.length) {
|
|
252
|
+
const playlist = !data.playlist
|
|
253
|
+
? null
|
|
254
|
+
: new Playlist_1.Playlist(this, {
|
|
255
|
+
...data.playlist,
|
|
256
|
+
tracks: []
|
|
257
|
+
});
|
|
258
|
+
const tracks = data.data.map((m) => new Track_1.default(this, {
|
|
259
|
+
...m,
|
|
260
|
+
requestedBy: options.requestedBy,
|
|
261
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration)),
|
|
262
|
+
playlist: playlist
|
|
263
|
+
}));
|
|
264
|
+
if (playlist)
|
|
265
|
+
playlist.tracks = tracks;
|
|
266
|
+
return { playlist: playlist, tracks: tracks };
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const qt = options.searchEngine === types_1.QueryType.AUTO ? QueryResolver_1.QueryResolver.resolve(query) : options.searchEngine;
|
|
270
|
+
switch (qt) {
|
|
271
|
+
case types_1.QueryType.YOUTUBE_VIDEO: {
|
|
272
|
+
const info = await (0, ytdl_core_1.getInfo)(query, this.options.ytdlOptions).catch(Util_1.Util.noop);
|
|
273
|
+
if (!info)
|
|
222
274
|
return { playlist: null, tracks: [] };
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
275
|
+
const track = new Track_1.default(this, {
|
|
276
|
+
title: info.videoDetails.title,
|
|
277
|
+
description: info.videoDetails.description,
|
|
278
|
+
author: info.videoDetails.author?.name,
|
|
279
|
+
url: info.videoDetails.video_url,
|
|
280
|
+
requestedBy: options.requestedBy,
|
|
281
|
+
thumbnail: Util_1.Util.last(info.videoDetails.thumbnails)?.url,
|
|
282
|
+
views: parseInt(info.videoDetails.viewCount.replace(/[^0-9]/g, "")) || 0,
|
|
283
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(parseInt(info.videoDetails.lengthSeconds) * 1000)),
|
|
284
|
+
source: "youtube",
|
|
285
|
+
raw: info
|
|
286
|
+
});
|
|
287
|
+
return { playlist: null, tracks: [track] };
|
|
233
288
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
289
|
+
case types_1.QueryType.YOUTUBE_SEARCH: {
|
|
290
|
+
const videos = await youtube_sr_1.default.search(query, {
|
|
291
|
+
type: "video"
|
|
292
|
+
}).catch(Util_1.Util.noop);
|
|
293
|
+
if (!videos)
|
|
294
|
+
return { playlist: null, tracks: [] };
|
|
295
|
+
const tracks = videos.map((m) => {
|
|
296
|
+
m.source = "youtube"; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
297
|
+
return new Track_1.default(this, {
|
|
298
|
+
title: m.title,
|
|
299
|
+
description: m.description,
|
|
300
|
+
author: m.channel?.name,
|
|
301
|
+
url: m.url,
|
|
302
|
+
requestedBy: options.requestedBy,
|
|
303
|
+
thumbnail: m.thumbnail?.displayThumbnailURL("maxresdefault"),
|
|
304
|
+
views: m.views,
|
|
305
|
+
duration: m.durationFormatted,
|
|
306
|
+
source: "youtube",
|
|
307
|
+
raw: m
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
return { playlist: null, tracks };
|
|
250
311
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
312
|
+
case types_1.QueryType.SOUNDCLOUD_TRACK:
|
|
313
|
+
case types_1.QueryType.SOUNDCLOUD_SEARCH: {
|
|
314
|
+
const result = QueryResolver_1.QueryResolver.resolve(query) === types_1.QueryType.SOUNDCLOUD_TRACK ? [{ url: query }] : await soundcloud.search(query, "track").catch(() => []);
|
|
315
|
+
if (!result || !result.length)
|
|
316
|
+
return { playlist: null, tracks: [] };
|
|
317
|
+
const res = [];
|
|
318
|
+
for (const r of result) {
|
|
319
|
+
const trackInfo = await soundcloud.getSongInfo(r.url).catch(Util_1.Util.noop);
|
|
320
|
+
if (!trackInfo)
|
|
321
|
+
continue;
|
|
257
322
|
const track = new Track_1.default(this, {
|
|
258
|
-
title:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
323
|
+
title: trackInfo.title,
|
|
324
|
+
url: trackInfo.url,
|
|
325
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(trackInfo.duration)),
|
|
326
|
+
description: trackInfo.description,
|
|
327
|
+
thumbnail: trackInfo.thumbnail,
|
|
328
|
+
views: trackInfo.playCount,
|
|
329
|
+
author: trackInfo.author.name,
|
|
262
330
|
requestedBy: options.requestedBy,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(parseInt(info.videoDetails.lengthSeconds) * 1000)),
|
|
266
|
-
source: "youtube",
|
|
267
|
-
raw: info
|
|
331
|
+
source: "soundcloud",
|
|
332
|
+
engine: trackInfo
|
|
268
333
|
});
|
|
269
|
-
|
|
334
|
+
res.push(track);
|
|
270
335
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
336
|
+
return { playlist: null, tracks: res };
|
|
337
|
+
}
|
|
338
|
+
case types_1.QueryType.SPOTIFY_SONG: {
|
|
339
|
+
const spotifyData = await (0, spotify_url_info_1.default)(await Util_1.Util.getFetch())
|
|
340
|
+
.getData(query)
|
|
341
|
+
.catch(Util_1.Util.noop);
|
|
342
|
+
if (!spotifyData)
|
|
343
|
+
return { playlist: null, tracks: [] };
|
|
344
|
+
const spotifyTrack = new Track_1.default(this, {
|
|
345
|
+
title: spotifyData.name,
|
|
346
|
+
description: spotifyData.description ?? "",
|
|
347
|
+
author: spotifyData.artists[0]?.name ?? "Unknown Artist",
|
|
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)),
|
|
353
|
+
views: 0,
|
|
354
|
+
requestedBy: options.requestedBy,
|
|
355
|
+
source: "spotify"
|
|
356
|
+
});
|
|
357
|
+
return { playlist: null, tracks: [spotifyTrack] };
|
|
358
|
+
}
|
|
359
|
+
case types_1.QueryType.SPOTIFY_PLAYLIST:
|
|
360
|
+
case types_1.QueryType.SPOTIFY_ALBUM: {
|
|
361
|
+
const spotifyPlaylist = await (0, spotify_url_info_1.default)(await Util_1.Util.getFetch())
|
|
362
|
+
.getData(query)
|
|
363
|
+
.catch(Util_1.Util.noop);
|
|
364
|
+
if (!spotifyPlaylist)
|
|
365
|
+
return { playlist: null, tracks: [] };
|
|
366
|
+
const playlist = new Playlist_1.Playlist(this, {
|
|
367
|
+
title: spotifyPlaylist.name ?? spotifyPlaylist.title,
|
|
368
|
+
description: spotifyPlaylist.description ?? "",
|
|
369
|
+
thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
|
|
370
|
+
type: spotifyPlaylist.type,
|
|
371
|
+
source: "spotify",
|
|
372
|
+
author: spotifyPlaylist.type !== "playlist"
|
|
373
|
+
? {
|
|
374
|
+
name: spotifyPlaylist.artists[0]?.name ?? "Unknown Artist",
|
|
375
|
+
url: spotifyPlaylist.artists[0]?.external_urls?.spotify ?? null
|
|
376
|
+
}
|
|
377
|
+
: {
|
|
378
|
+
name: spotifyPlaylist.owner?.display_name ?? spotifyPlaylist.owner?.id ?? "Unknown Artist",
|
|
379
|
+
url: spotifyPlaylist.owner?.external_urls?.spotify ?? null
|
|
380
|
+
},
|
|
381
|
+
tracks: [],
|
|
382
|
+
id: spotifyPlaylist.id,
|
|
383
|
+
url: spotifyPlaylist.external_urls?.spotify ?? query,
|
|
384
|
+
rawPlaylist: spotifyPlaylist
|
|
385
|
+
});
|
|
386
|
+
if (spotifyPlaylist.type !== "playlist") {
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
388
|
+
playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
|
|
389
|
+
const data = new Track_1.default(this, {
|
|
390
|
+
title: m.name ?? "",
|
|
391
|
+
description: m.description ?? "",
|
|
392
|
+
author: m.artists[0]?.name ?? "Unknown Artist",
|
|
393
|
+
url: m.external_urls?.spotify ?? query,
|
|
394
|
+
thumbnail: spotifyPlaylist.images[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
|
|
395
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.duration_ms)),
|
|
396
|
+
views: 0,
|
|
285
397
|
requestedBy: options.requestedBy,
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
duration: m.durationFormatted,
|
|
289
|
-
source: "youtube",
|
|
290
|
-
raw: m
|
|
398
|
+
playlist,
|
|
399
|
+
source: "spotify"
|
|
291
400
|
});
|
|
401
|
+
return data;
|
|
292
402
|
});
|
|
293
|
-
return { playlist: null, tracks };
|
|
294
403
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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,
|
|
404
|
+
else {
|
|
405
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
406
|
+
playlist.tracks = spotifyPlaylist.tracks.items.map((m) => {
|
|
407
|
+
const data = new Track_1.default(this, {
|
|
408
|
+
title: m.track.name ?? "",
|
|
409
|
+
description: m.track.description ?? "",
|
|
410
|
+
author: m.track.artists?.[0]?.name ?? "Unknown Artist",
|
|
411
|
+
url: m.track.external_urls?.spotify ?? query,
|
|
412
|
+
thumbnail: m.track.album?.images?.[0]?.url ?? "https://www.scdn.co/i/_global/twitter_card-default.jpg",
|
|
413
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(m.track.duration_ms)),
|
|
414
|
+
views: 0,
|
|
313
415
|
requestedBy: options.requestedBy,
|
|
314
|
-
|
|
315
|
-
|
|
416
|
+
playlist,
|
|
417
|
+
source: "spotify"
|
|
316
418
|
});
|
|
317
|
-
|
|
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"
|
|
419
|
+
return data;
|
|
337
420
|
});
|
|
338
|
-
return { playlist: null, tracks: [spotifyTrack] };
|
|
339
421
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
-
}
|
|
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",
|
|
422
|
+
return { playlist: playlist, tracks: playlist.tracks };
|
|
423
|
+
}
|
|
424
|
+
case types_1.QueryType.SOUNDCLOUD_PLAYLIST: {
|
|
425
|
+
const data = await soundcloud.getPlaylist(query).catch(Util_1.Util.noop);
|
|
426
|
+
if (!data)
|
|
427
|
+
return { playlist: null, tracks: [] };
|
|
428
|
+
const res = new Playlist_1.Playlist(this, {
|
|
429
|
+
title: data.title,
|
|
430
|
+
description: data.description ?? "",
|
|
431
|
+
thumbnail: data.thumbnail ?? "https://soundcloud.com/pwa-icon-192.png",
|
|
432
|
+
type: "playlist",
|
|
433
|
+
source: "soundcloud",
|
|
434
|
+
author: {
|
|
435
|
+
name: data.author?.name ?? data.author?.username ?? "Unknown Artist",
|
|
436
|
+
url: data.author?.profile
|
|
437
|
+
},
|
|
438
|
+
tracks: [],
|
|
439
|
+
id: `${data.id}`,
|
|
440
|
+
url: data.url,
|
|
441
|
+
rawPlaylist: data
|
|
442
|
+
});
|
|
443
|
+
for (const song of data.tracks) {
|
|
444
|
+
const track = new Track_1.default(this, {
|
|
445
|
+
title: song.title,
|
|
446
|
+
description: song.description ?? "",
|
|
447
|
+
author: song.author?.username ?? song.author?.name ?? "Unknown Artist",
|
|
448
|
+
url: song.url,
|
|
449
|
+
thumbnail: song.thumbnail,
|
|
450
|
+
duration: Util_1.Util.buildTimeCode(Util_1.Util.parseMS(song.duration)),
|
|
451
|
+
views: song.playCount ?? 0,
|
|
452
|
+
requestedBy: options.requestedBy,
|
|
453
|
+
playlist: res,
|
|
414
454
|
source: "soundcloud",
|
|
415
|
-
|
|
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
|
|
455
|
+
engine: song
|
|
423
456
|
});
|
|
424
|
-
|
|
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 };
|
|
457
|
+
res.tracks.push(track);
|
|
441
458
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
|
461
|
-
});
|
|
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 };
|
|
479
|
-
}
|
|
480
|
-
default:
|
|
459
|
+
return { playlist: res, tracks: res.tracks };
|
|
460
|
+
}
|
|
461
|
+
case types_1.QueryType.YOUTUBE_PLAYLIST: {
|
|
462
|
+
const ytpl = await youtube_sr_1.default.getPlaylist(query).catch(Util_1.Util.noop);
|
|
463
|
+
if (!ytpl)
|
|
481
464
|
return { playlist: null, tracks: [] };
|
|
465
|
+
await ytpl.fetch().catch(Util_1.Util.noop);
|
|
466
|
+
const playlist = new Playlist_1.Playlist(this, {
|
|
467
|
+
title: ytpl.title,
|
|
468
|
+
thumbnail: ytpl.thumbnail,
|
|
469
|
+
description: "",
|
|
470
|
+
type: "playlist",
|
|
471
|
+
source: "youtube",
|
|
472
|
+
author: {
|
|
473
|
+
name: ytpl.channel.name,
|
|
474
|
+
url: ytpl.channel.url
|
|
475
|
+
},
|
|
476
|
+
tracks: [],
|
|
477
|
+
id: ytpl.id,
|
|
478
|
+
url: ytpl.url,
|
|
479
|
+
rawPlaylist: ytpl
|
|
480
|
+
});
|
|
481
|
+
playlist.tracks = ytpl.videos.map((video) => new Track_1.default(this, {
|
|
482
|
+
title: video.title,
|
|
483
|
+
description: video.description,
|
|
484
|
+
author: video.channel?.name,
|
|
485
|
+
url: video.url,
|
|
486
|
+
requestedBy: options.requestedBy,
|
|
487
|
+
thumbnail: video.thumbnail.url,
|
|
488
|
+
views: video.views,
|
|
489
|
+
duration: video.durationFormatted,
|
|
490
|
+
raw: video,
|
|
491
|
+
playlist: playlist,
|
|
492
|
+
source: "youtube"
|
|
493
|
+
}));
|
|
494
|
+
return { playlist: playlist, tracks: playlist.tracks };
|
|
482
495
|
}
|
|
483
|
-
|
|
496
|
+
default:
|
|
497
|
+
return { playlist: null, tracks: [] };
|
|
498
|
+
}
|
|
484
499
|
}
|
|
485
500
|
/**
|
|
486
501
|
* Registers extractor
|
|
@@ -555,5 +570,12 @@ class Player extends tiny_typed_emitter_1.TypedEmitter {
|
|
|
555
570
|
*[Symbol.iterator]() {
|
|
556
571
|
yield* Array.from(this.queues.values());
|
|
557
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Creates `Playlist` instance
|
|
575
|
+
* @param data The data to initialize a playlist
|
|
576
|
+
*/
|
|
577
|
+
createPlaylist(data) {
|
|
578
|
+
return new Playlist_1.Playlist(this, data);
|
|
579
|
+
}
|
|
558
580
|
}
|
|
559
581
|
exports.Player = Player;
|