magmastream 2.9.0-dev.35 → 2.9.0-dev.37

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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Structure = exports.AutoPlayUtils = exports.TrackUtils = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ /* eslint-disable @typescript-eslint/no-require-imports */
5
6
  const axios_1 = tslib_1.__importDefault(require("axios"));
6
7
  const jsdom_1 = require("jsdom");
7
8
  const Enums_1 = require("./Enums");
@@ -167,6 +168,10 @@ class AutoPlayUtils {
167
168
  throw new Error("No available nodes.");
168
169
  }
169
170
  const apiKey = this.manager.options.lastFmApiKey;
171
+ // Check if Last.fm API is available
172
+ if (apiKey) {
173
+ return await this.getRecommendedTracksFromLastFm(track, apiKey);
174
+ }
170
175
  const enabledSources = node.info.sourceManagers;
171
176
  const autoPlaySearchPlatforms = this.manager.options.autoPlaySearchPlatforms;
172
177
  // Iterate over autoplay platforms in order of priority
@@ -179,10 +184,6 @@ class AutoPlayUtils {
179
184
  }
180
185
  }
181
186
  }
182
- // Check if Last.fm API is available
183
- if (apiKey) {
184
- return await this.getRecommendedTracksFromLastFm(track, apiKey);
185
- }
186
187
  return [];
187
188
  }
188
189
  /**
@@ -203,22 +204,7 @@ class AutoPlayUtils {
203
204
  return [];
204
205
  }
205
206
  const randomTrack = response.data.toptracks.track[Math.floor(Math.random() * response.data.toptracks.track.length)];
206
- const searchResult = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
207
- if (TrackUtils.isErrorOrEmptySearchResult(searchResult)) {
208
- return [];
209
- }
210
- let resolvedTracks;
211
- switch (searchResult.loadType) {
212
- case Enums_1.LoadTypes.Playlist:
213
- resolvedTracks = searchResult.playlist.tracks;
214
- break;
215
- case Enums_1.LoadTypes.Track:
216
- case Enums_1.LoadTypes.Search:
217
- resolvedTracks = searchResult.tracks;
218
- break;
219
- default:
220
- return [];
221
- }
207
+ const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
222
208
  if (!resolvedTracks.length)
223
209
  return [];
224
210
  return resolvedTracks;
@@ -251,22 +237,7 @@ class AutoPlayUtils {
251
237
  return [];
252
238
  }
253
239
  const randomTrack = retryResponse.data.toptracks.track[Math.floor(Math.random() * retryResponse.data.toptracks.track.length)];
254
- const searchResult = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
255
- if (TrackUtils.isErrorOrEmptySearchResult(searchResult)) {
256
- return [];
257
- }
258
- let resolvedTracks;
259
- switch (searchResult.loadType) {
260
- case Enums_1.LoadTypes.Playlist:
261
- resolvedTracks = searchResult.playlist.tracks;
262
- break;
263
- case Enums_1.LoadTypes.Track:
264
- case Enums_1.LoadTypes.Search:
265
- resolvedTracks = searchResult.tracks;
266
- break;
267
- default:
268
- return [];
269
- }
240
+ const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
270
241
  if (!resolvedTracks.length)
271
242
  return [];
272
243
  const filteredTracks = resolvedTracks.filter((t) => t.uri !== track.uri);
@@ -279,22 +250,7 @@ class AutoPlayUtils {
279
250
  if (!randomTrack) {
280
251
  return [];
281
252
  }
282
- const searchResult = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
283
- if (TrackUtils.isErrorOrEmptySearchResult(searchResult)) {
284
- return [];
285
- }
286
- let resolvedTracks;
287
- switch (searchResult.loadType) {
288
- case Enums_1.LoadTypes.Playlist:
289
- resolvedTracks = searchResult.playlist.tracks;
290
- break;
291
- case Enums_1.LoadTypes.Track:
292
- case Enums_1.LoadTypes.Search:
293
- resolvedTracks = searchResult.tracks;
294
- break;
295
- default:
296
- return [];
297
- }
253
+ const resolvedTracks = await this.resolveTracksFromQuery(`${randomTrack.artist.name} - ${randomTrack.name}`, this.manager.options.defaultSearchPlatform, track.requester);
298
254
  if (!resolvedTracks.length)
299
255
  return [];
300
256
  return resolvedTracks;
@@ -308,285 +264,219 @@ class AutoPlayUtils {
308
264
  static async getRecommendedTracksFromSource(track, platform) {
309
265
  const requester = track.requester;
310
266
  switch (platform) {
311
- case Enums_1.AutoPlayPlatform.Spotify:
312
- {
313
- if (!track.uri.includes("spotify")) {
314
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.Spotify }, requester);
315
- if (TrackUtils.isErrorOrEmptySearchResult(res))
316
- return [];
317
- let resolvedTrack;
318
- switch (res.loadType) {
319
- case Enums_1.LoadTypes.Playlist:
320
- resolvedTrack = res.playlist.tracks[0];
321
- break;
322
- case Enums_1.LoadTypes.Track:
323
- case Enums_1.LoadTypes.Search:
324
- resolvedTrack = res.tracks[0];
325
- break;
326
- default:
327
- return [];
328
- }
329
- if (!resolvedTrack)
330
- return [];
331
- track = resolvedTrack;
332
- }
333
- const extractSpotifyArtistID = (url) => {
334
- const regex = /https:\/\/open\.spotify\.com\/artist\/([a-zA-Z0-9]+)/;
335
- const match = url.match(regex);
336
- return match ? match[1] : null;
337
- };
338
- const identifier = `sprec:seed_artists=${extractSpotifyArtistID(track.pluginInfo.artistUrl)}&seed_tracks=${track.identifier}`;
339
- const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
340
- const tracks = this.buildTracksFromResponse(recommendedResult, requester);
341
- return tracks;
267
+ case Enums_1.AutoPlayPlatform.Spotify: {
268
+ if (!track.uri.includes("spotify")) {
269
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.Spotify, requester);
270
+ if (!resolvedTrack)
271
+ return [];
272
+ track = resolvedTrack;
342
273
  }
343
- break;
344
- case Enums_1.AutoPlayPlatform.Deezer:
345
- {
346
- if (!track.uri.includes("deezer")) {
347
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.Deezer }, requester);
348
- if (TrackUtils.isErrorOrEmptySearchResult(res))
349
- return [];
350
- let resolvedTrack;
351
- switch (res.loadType) {
352
- case Enums_1.LoadTypes.Playlist:
353
- resolvedTrack = res.playlist.tracks[0];
354
- break;
355
- case Enums_1.LoadTypes.Track:
356
- case Enums_1.LoadTypes.Search:
357
- resolvedTrack = res.tracks[0];
358
- break;
359
- default:
360
- return [];
361
- }
362
- if (!resolvedTrack)
363
- return [];
364
- track = resolvedTrack;
365
- }
366
- const identifier = `dzrec:${track.identifier}`;
367
- const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
368
- const tracks = this.buildTracksFromResponse(recommendedResult, requester);
369
- return tracks;
274
+ const extractSpotifyArtistID = (url) => {
275
+ const regex = /https:\/\/open\.spotify\.com\/artist\/([a-zA-Z0-9]+)/;
276
+ const match = url.match(regex);
277
+ return match ? match[1] : null;
278
+ };
279
+ const identifier = `sprec:seed_artists=${extractSpotifyArtistID(track.pluginInfo.artistUrl)}&seed_tracks=${track.identifier}`;
280
+ const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
281
+ const tracks = this.buildTracksFromResponse(recommendedResult, requester);
282
+ return tracks;
283
+ }
284
+ case Enums_1.AutoPlayPlatform.Deezer: {
285
+ if (!track.uri.includes("deezer")) {
286
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.Deezer, requester);
287
+ if (!resolvedTrack)
288
+ return [];
289
+ track = resolvedTrack;
370
290
  }
371
- break;
372
- case Enums_1.AutoPlayPlatform.SoundCloud:
373
- {
374
- if (!track.uri.includes("soundcloud")) {
375
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.SoundCloud }, requester);
376
- if (TrackUtils.isErrorOrEmptySearchResult(res))
377
- return [];
378
- let resolvedTrack;
379
- switch (res.loadType) {
380
- case Enums_1.LoadTypes.Playlist:
381
- resolvedTrack = res.playlist.tracks[0];
382
- break;
383
- case Enums_1.LoadTypes.Track:
384
- case Enums_1.LoadTypes.Search:
385
- resolvedTrack = res.tracks[0];
386
- break;
387
- default:
388
- return [];
389
- }
390
- if (!resolvedTrack)
391
- return [];
392
- track = resolvedTrack;
393
- }
394
- try {
395
- const recommendedRes = await axios_1.default.get(`${track.uri}/recommended`).catch((err) => {
396
- console.error(`[AutoPlay] Failed to fetch SoundCloud recommendations. Status: ${err.response?.status || "Unknown"}`, err.message);
397
- return null;
398
- });
399
- if (!recommendedRes) {
400
- return [];
401
- }
402
- const html = recommendedRes.data;
403
- const dom = new jsdom_1.JSDOM(html);
404
- const document = dom.window.document;
405
- const secondNoscript = document.querySelectorAll("noscript")[1];
406
- const sectionElement = secondNoscript.querySelector("section");
407
- const articleElements = sectionElement.querySelectorAll("article");
408
- if (!articleElements || articleElements.length === 0) {
409
- return [];
410
- }
411
- const urls = Array.from(articleElements)
412
- .map((articleElement) => {
413
- const h2Element = articleElement.querySelector('h2[itemprop="name"]');
414
- const aElement = h2Element?.querySelector('a[itemprop="url"]');
415
- return aElement ? `https://soundcloud.com${aElement.getAttribute("href")}` : null;
416
- })
417
- .filter(Boolean);
418
- if (!urls.length) {
419
- return [];
420
- }
421
- const randomUrl = urls[Math.floor(Math.random() * urls.length)];
422
- const res = await this.manager.search({ query: randomUrl, source: Enums_1.SearchPlatform.SoundCloud }, requester);
423
- let resolvedTrack;
424
- switch (res.loadType) {
425
- case Enums_1.LoadTypes.Playlist:
426
- resolvedTrack = res.playlist.tracks[0];
427
- break;
428
- case Enums_1.LoadTypes.Track:
429
- case Enums_1.LoadTypes.Search:
430
- resolvedTrack = res.tracks[0];
431
- break;
432
- default:
433
- return [];
434
- }
435
- if (!resolvedTrack)
436
- return [];
437
- return [resolvedTrack];
438
- }
439
- catch (error) {
440
- console.error("[AutoPlay] Error occurred while fetching soundcloud recommendations:", error);
291
+ const identifier = `dzrec:${track.identifier}`;
292
+ const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
293
+ const tracks = this.buildTracksFromResponse(recommendedResult, requester);
294
+ return tracks;
295
+ }
296
+ case Enums_1.AutoPlayPlatform.SoundCloud: {
297
+ if (!track.uri.includes("soundcloud")) {
298
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.SoundCloud, requester);
299
+ if (!resolvedTrack)
441
300
  return [];
442
- }
301
+ track = resolvedTrack;
443
302
  }
444
- break;
445
- case Enums_1.AutoPlayPlatform.YouTube:
446
- {
447
- const hasYouTubeURL = ["youtube.com", "youtu.be"].some((url) => track.uri.includes(url));
448
- let videoID = null;
449
- if (hasYouTubeURL) {
450
- videoID = track.uri.split("=").pop();
451
- }
452
- else {
453
- const searchResult = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.YouTube }, requester);
454
- if (TrackUtils.isErrorOrEmptySearchResult(searchResult)) {
455
- return [];
456
- }
457
- let resolvedTrack;
458
- switch (searchResult.loadType) {
459
- case Enums_1.LoadTypes.Playlist:
460
- resolvedTrack = searchResult.playlist.tracks[0];
461
- break;
462
- case Enums_1.LoadTypes.Track:
463
- case Enums_1.LoadTypes.Search:
464
- resolvedTrack = searchResult.tracks[0];
465
- break;
466
- default:
467
- return [];
468
- }
469
- if (!resolvedTrack)
470
- return [];
471
- videoID = resolvedTrack.uri.split("=").pop();
472
- }
473
- if (!videoID) {
303
+ try {
304
+ const recommendedRes = await axios_1.default.get(`${track.uri}/recommended`).catch((err) => {
305
+ console.error(`[AutoPlay] Failed to fetch SoundCloud recommendations. Status: ${err.response?.status || "Unknown"}`, err.message);
306
+ return null;
307
+ });
308
+ if (!recommendedRes) {
474
309
  return [];
475
310
  }
476
- let randomIndex;
477
- let searchURI;
478
- do {
479
- randomIndex = Math.floor(Math.random() * 23) + 2;
480
- searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
481
- } while (track.uri.includes(searchURI));
482
- const res = await this.manager.search({ query: searchURI, source: Enums_1.SearchPlatform.YouTube }, requester);
483
- if (TrackUtils.isErrorOrEmptySearchResult(res)) {
311
+ const html = recommendedRes.data;
312
+ const dom = new jsdom_1.JSDOM(html);
313
+ const window = dom.window;
314
+ // Narrow the element types using instanceof
315
+ const secondNoscript = window.querySelectorAll("noscript")[1];
316
+ if (!secondNoscript || !(secondNoscript instanceof window.Element))
484
317
  return [];
485
- }
486
- let resolvedTracks;
487
- switch (res.loadType) {
488
- case Enums_1.LoadTypes.Playlist:
489
- resolvedTracks = res.playlist.tracks;
490
- break;
491
- case Enums_1.LoadTypes.Track:
492
- case Enums_1.LoadTypes.Search:
493
- resolvedTracks = res.tracks;
494
- break;
495
- default:
496
- return [];
497
- }
498
- const filteredTracks = resolvedTracks.filter((t) => t.uri !== track.uri);
499
- return filteredTracks;
318
+ const sectionElement = secondNoscript.querySelector("section");
319
+ if (!sectionElement || !(sectionElement instanceof window.HTMLElement))
320
+ return [];
321
+ const articleElements = sectionElement.querySelectorAll("article");
322
+ if (!articleElements || articleElements.length === 0)
323
+ return [];
324
+ const urls = Array.from(articleElements)
325
+ .map((element) => {
326
+ const h2 = element.querySelector('h2[itemprop="name"]');
327
+ if (!h2)
328
+ return null;
329
+ const a = h2.querySelector('a[itemprop="url"]');
330
+ if (!a)
331
+ return null;
332
+ const href = a.getAttribute("href");
333
+ return href ? `https://soundcloud.com${href}` : null;
334
+ })
335
+ .filter(Boolean);
336
+ if (!urls.length)
337
+ return [];
338
+ const randomUrl = urls[Math.floor(Math.random() * urls.length)];
339
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(randomUrl, Enums_1.SearchPlatform.SoundCloud, requester);
340
+ return resolvedTrack ? [resolvedTrack] : [];
500
341
  }
501
- break;
502
- case Enums_1.AutoPlayPlatform.Tidal:
503
- {
504
- if (!track.uri.includes("tidal")) {
505
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.Tidal }, requester);
506
- if (TrackUtils.isErrorOrEmptySearchResult(res))
507
- return [];
508
- let resolvedTrack;
509
- switch (res.loadType) {
510
- case Enums_1.LoadTypes.Playlist:
511
- resolvedTrack = res.playlist.tracks[0];
512
- break;
513
- case Enums_1.LoadTypes.Track:
514
- case Enums_1.LoadTypes.Search:
515
- resolvedTrack = res.tracks[0];
516
- break;
517
- default:
518
- return [];
519
- }
520
- if (!resolvedTrack)
521
- return [];
522
- track = resolvedTrack;
523
- }
524
- const identifier = `tdrec:${track.identifier}`;
525
- const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
526
- const tracks = this.buildTracksFromResponse(recommendedResult, requester);
527
- return tracks;
342
+ catch (error) {
343
+ console.error("[AutoPlay] Error occurred while fetching soundcloud recommendations:", error);
344
+ return [];
528
345
  }
529
- break;
530
- case Enums_1.AutoPlayPlatform.VKMusic:
531
- {
532
- if (!track.uri.includes("vk.com") && !track.uri.includes("vk.ru")) {
533
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.VKMusic }, requester);
534
- if (TrackUtils.isErrorOrEmptySearchResult(res))
535
- return [];
536
- let resolvedTrack;
537
- switch (res.loadType) {
538
- case Enums_1.LoadTypes.Playlist:
539
- resolvedTrack = res.playlist.tracks[0];
540
- break;
541
- case Enums_1.LoadTypes.Track:
542
- case Enums_1.LoadTypes.Search:
543
- resolvedTrack = res.tracks[0];
544
- break;
545
- default:
546
- return [];
547
- }
548
- if (!resolvedTrack)
549
- return [];
550
- track = resolvedTrack;
551
- }
552
- const identifier = `vkrec:${track.identifier}`;
553
- const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
554
- const tracks = this.buildTracksFromResponse(recommendedResult, requester);
555
- return tracks;
346
+ }
347
+ case Enums_1.AutoPlayPlatform.YouTube: {
348
+ const hasYouTubeURL = ["youtube.com", "youtu.be"].some((url) => track.uri.includes(url));
349
+ let videoID = null;
350
+ if (hasYouTubeURL) {
351
+ videoID = track.uri.split("=").pop();
556
352
  }
557
- break;
558
- case Enums_1.AutoPlayPlatform.Qobuz:
559
- {
560
- if (!track.uri.includes("qobuz.com")) {
561
- const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Enums_1.SearchPlatform.Qobuz }, requester);
562
- if (TrackUtils.isErrorOrEmptySearchResult(res))
563
- return [];
564
- let resolvedTrack;
565
- switch (res.loadType) {
566
- case Enums_1.LoadTypes.Playlist:
567
- resolvedTrack = res.playlist.tracks[0];
568
- break;
569
- case Enums_1.LoadTypes.Track:
570
- case Enums_1.LoadTypes.Search:
571
- resolvedTrack = res.tracks[0];
572
- break;
573
- default:
574
- return [];
575
- }
576
- if (!resolvedTrack)
577
- return [];
578
- track = resolvedTrack;
579
- }
580
- const identifier = `qbrec:${track.identifier}`;
581
- const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
582
- const tracks = this.buildTracksFromResponse(recommendedResult, requester);
583
- return tracks;
353
+ else {
354
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.YouTube, requester);
355
+ if (!resolvedTrack)
356
+ return [];
357
+ videoID = resolvedTrack.uri.split("=").pop();
358
+ }
359
+ if (!videoID) {
360
+ return [];
361
+ }
362
+ let randomIndex;
363
+ let searchURI;
364
+ do {
365
+ randomIndex = Math.floor(Math.random() * 23) + 2;
366
+ searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
367
+ } while (track.uri.includes(searchURI));
368
+ const resolvedTracks = await this.resolveTracksFromQuery(searchURI, Enums_1.SearchPlatform.YouTube, requester);
369
+ const filteredTracks = resolvedTracks.filter((t) => t.uri !== track.uri);
370
+ return filteredTracks;
371
+ }
372
+ case Enums_1.AutoPlayPlatform.Tidal: {
373
+ if (!track.uri.includes("tidal")) {
374
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.Tidal, requester);
375
+ if (!resolvedTrack)
376
+ return [];
377
+ track = resolvedTrack;
378
+ }
379
+ const identifier = `tdrec:${track.identifier}`;
380
+ const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
381
+ const tracks = this.buildTracksFromResponse(recommendedResult, requester);
382
+ return tracks;
383
+ }
384
+ case Enums_1.AutoPlayPlatform.VKMusic: {
385
+ if (!track.uri.includes("vk.com") && !track.uri.includes("vk.ru")) {
386
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.VKMusic, requester);
387
+ if (!resolvedTrack)
388
+ return [];
389
+ track = resolvedTrack;
584
390
  }
585
- break;
391
+ const identifier = `vkrec:${track.identifier}`;
392
+ const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
393
+ const tracks = this.buildTracksFromResponse(recommendedResult, requester);
394
+ return tracks;
395
+ }
396
+ case Enums_1.AutoPlayPlatform.Qobuz: {
397
+ if (!track.uri.includes("qobuz.com")) {
398
+ const resolvedTrack = await this.resolveFirstTrackFromQuery(`${track.author} - ${track.title}`, Enums_1.SearchPlatform.Qobuz, requester);
399
+ if (!resolvedTrack)
400
+ return [];
401
+ track = resolvedTrack;
402
+ }
403
+ const identifier = `qbrec:${track.identifier}`;
404
+ const recommendedResult = (await this.manager.useableNode.rest.get(`/v4/loadtracks?identifier=${encodeURIComponent(identifier)}`));
405
+ const tracks = this.buildTracksFromResponse(recommendedResult, requester);
406
+ return tracks;
407
+ }
586
408
  default:
587
409
  return [];
588
410
  }
589
411
  }
412
+ /**
413
+ * Searches for a track using the manager and returns resolved tracks.
414
+ * @param query The search query (artist - title).
415
+ * @param requester The requester who initiated the search.
416
+ * @returns An array of resolved tracks, or an empty array if not found or error occurred.
417
+ */
418
+ static async resolveTracksFromQuery(query, source, requester) {
419
+ try {
420
+ const searchResult = await this.manager.search({ query, source }, requester);
421
+ if (TrackUtils.isErrorOrEmptySearchResult(searchResult)) {
422
+ return [];
423
+ }
424
+ switch (searchResult.loadType) {
425
+ case Enums_1.LoadTypes.Album:
426
+ case Enums_1.LoadTypes.Artist:
427
+ case Enums_1.LoadTypes.Station:
428
+ case Enums_1.LoadTypes.Podcast:
429
+ case Enums_1.LoadTypes.Show:
430
+ case Enums_1.LoadTypes.Playlist:
431
+ return searchResult.playlist.tracks;
432
+ case Enums_1.LoadTypes.Track:
433
+ case Enums_1.LoadTypes.Search:
434
+ case Enums_1.LoadTypes.Short:
435
+ return searchResult.tracks;
436
+ default:
437
+ return [];
438
+ }
439
+ }
440
+ catch (error) {
441
+ console.error("[TrackResolver] Failed to resolve query:", query, error);
442
+ return [];
443
+ }
444
+ }
445
+ /**
446
+ * Resolves the first available track from a search query using the specified source.
447
+ * Useful for normalizing tracks that lack platform-specific metadata or URIs.
448
+ *
449
+ * @param query - The search query string (usually "Artist - Title").
450
+ * @param source - The search platform to use (e.g., Spotify, Deezer, YouTube).
451
+ * @param requester - The requester object, used for context or attribution.
452
+ * @returns A single resolved {@link Track} object if found, or `null` if the search fails or returns no results.
453
+ */
454
+ static async resolveFirstTrackFromQuery(query, source, requester) {
455
+ try {
456
+ const searchResult = await this.manager.search({ query, source }, requester);
457
+ if (TrackUtils.isErrorOrEmptySearchResult(searchResult))
458
+ return null;
459
+ switch (searchResult.loadType) {
460
+ case Enums_1.LoadTypes.Album:
461
+ case Enums_1.LoadTypes.Artist:
462
+ case Enums_1.LoadTypes.Station:
463
+ case Enums_1.LoadTypes.Podcast:
464
+ case Enums_1.LoadTypes.Show:
465
+ case Enums_1.LoadTypes.Playlist:
466
+ return searchResult.playlist.tracks[0] || null;
467
+ case Enums_1.LoadTypes.Track:
468
+ case Enums_1.LoadTypes.Search:
469
+ case Enums_1.LoadTypes.Short:
470
+ return searchResult.tracks[0] || null;
471
+ default:
472
+ return null;
473
+ }
474
+ }
475
+ catch (err) {
476
+ console.error(`[AutoPlay] Failed to resolve track from query: "${query}" on source: ${source}`, err);
477
+ return null;
478
+ }
479
+ }
590
480
  // static async getSpotifyAccessToken() {
591
481
  // const timeoutMs = 15000;
592
482
  // let browser;
@@ -652,7 +542,7 @@ class AutoPlayUtils {
652
542
  return tracks;
653
543
  }
654
544
  default:
655
- throw new Error(`Unsupported loadType: ${recommendedResult.loadType}`);
545
+ throw new Error(`[TrackBuilder] Unsupported loadType: ${recommendedResult.loadType}`);
656
546
  }
657
547
  }
658
548
  }
@@ -685,7 +575,7 @@ class Structure {
685
575
  exports.Structure = Structure;
686
576
  const structures = {
687
577
  Player: require("./Player").Player,
688
- Queue: require("./Queue").Queue,
578
+ Queue: require("../statestorage/MemoryQueue").MemoryQueue,
689
579
  Node: require("./Node").Node,
690
580
  Filters: require("./Filters").Filters,
691
581
  Manager: require("./Manager").Manager,
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SeyfertManager = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const Manager_1 = require("../structures/Manager");
6
+ const common_1 = require("seyfert/lib/common");
7
+ tslib_1.__exportStar(require("../index"), exports);
8
+ /**
9
+ * Seyfert wrapper for Magmastream.
10
+ *
11
+ * @note This wrapper does require the manual implementation of the "raw" and "ready" events, to call the `updateVoiceState` and `init` methods respectively.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const client = new Client();
16
+ * const manager = new SeyfertManager(client, options);
17
+ *
18
+ * client.events.values.RAW = {
19
+ * data: { name: "raw" },
20
+ * run: async (data) => {
21
+ * await manager.updateVoiceState(data);
22
+ * }
23
+ * }
24
+ *
25
+ * client.events.values.READY = {
26
+ * data: { name: "ready" },
27
+ * run: async (user, client) => {
28
+ * await manager.init({ clientId: client.botId });
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ class SeyfertManager extends Manager_1.Manager {
34
+ client;
35
+ constructor(client, options) {
36
+ super(options);
37
+ this.client = client;
38
+ }
39
+ send(packet) {
40
+ this.client.gateway.send((0, common_1.calculateShardId)(packet.d.guild_id), packet);
41
+ }
42
+ }
43
+ exports.SeyfertManager = SeyfertManager;