magmastream 2.9.0-dev.3 → 2.9.0-dev.4

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/index.d.ts CHANGED
@@ -678,11 +678,26 @@ declare abstract class AutoPlayUtils {
678
678
  * @hidden
679
679
  */
680
680
  static init(manager: Manager): void;
681
- static getRecommendedTracks(player: Player, track: Track, attempt?: number): Promise<Track[]>;
681
+ /**
682
+ * Gets recommended tracks for the given track.
683
+ * @param track The track to get recommended tracks for.
684
+ * @returns An array of recommended tracks.
685
+ */
686
+ static getRecommendedTracks(track: Track): Promise<Track[]>;
687
+ /**
688
+ * Gets recommended tracks from Last.fm for the given track.
689
+ * @param track The track to get recommended tracks for.
690
+ * @param apiKey The API key for Last.fm.
691
+ * @returns An array of recommended tracks.
692
+ */
682
693
  static getRecommendedTracksFromLastFm(track: Track, apiKey: string): Promise<Track[]>;
683
- static getRecommendedTracksFromSource(track: Track, mappedPlatform: string): Promise<Track[]>;
684
- static getRecommendedTracksFromYouTube(track: Track): Promise<Track[]>;
685
- static selectPlatform(enabledSources: string[]): SearchPlatform | null;
694
+ /**
695
+ * Gets recommended tracks from the given source.
696
+ * @param track The track to get recommended tracks for.
697
+ * @param platform The source to get recommended tracks from.
698
+ * @returns An array of recommended tracks.
699
+ */
700
+ static getRecommendedTracksFromSource(track: Track, platform: string): Promise<Track[]>;
686
701
  }
687
702
  /** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
688
703
  declare abstract class Structure {
@@ -901,7 +916,7 @@ declare class Manager extends EventEmitter {
901
916
  * @param options.enabledPlugins - An array of enabledPlugins to load.
902
917
  * @param options.nodes - An array of node options to create nodes from.
903
918
  * @param options.playNextOnEnd - Whether to automatically play the first track in the queue when the player is created.
904
- * @param options.autoPlaySearchPlatform - The search platform autoplay will use. Fallback to Youtube if not found.
919
+ * @param options.autoPlaySearchPlatforms - The search platform autoplay will use. Fallback to Youtube if not found.
905
920
  * @param options.enablePriorityMode - Whether to use the priority when selecting a node to play on.
906
921
  * @param options.clientName - The name of the client to send to Lavalink.
907
922
  * @param options.defaultSearchPlatform - The default search platform to use when searching for tracks.
@@ -1118,9 +1133,10 @@ interface ManagerOptions {
1118
1133
  enablePriorityMode?: boolean;
1119
1134
  /** Automatically play the next track when the current one ends. */
1120
1135
  playNextOnEnd?: boolean;
1121
- /** The search platform autoplay should use
1122
- * Use enum `SearchPlatform`. */
1123
- autoPlaySearchPlatform?: SearchPlatform;
1136
+ /** An array of search platforms to use for autoplay. First to last matters
1137
+ * Use enum `AutoPlayPlatform`.
1138
+ */
1139
+ autoPlaySearchPlatforms?: AutoPlayPlatform[];
1124
1140
  /** The client ID to use. */
1125
1141
  clientId?: string;
1126
1142
  /** Value to use for the `Client-Name` header. */
@@ -1202,6 +1218,12 @@ declare enum SearchPlatform {
1202
1218
  YouTube = "ytsearch",
1203
1219
  YouTubeMusic = "ytmsearch"
1204
1220
  }
1221
+ declare enum AutoPlayPlatform {
1222
+ Spotify = "spotify",
1223
+ Deezer = "deezer",
1224
+ SoundCloud = "soundcloud",
1225
+ YouTube = "youtube"
1226
+ }
1205
1227
  declare enum PlayerStateEventTypes {
1206
1228
  AutoPlayChange = "playerAutoplay",
1207
1229
  ConnectionChange = "playerConnection",
@@ -1402,7 +1424,7 @@ declare class Player {
1402
1424
  /** The autoplay state of the player. */
1403
1425
  isAutoplay: boolean;
1404
1426
  /** The number of times to try autoplay before emitting queueEnd. */
1405
- autoplayTries: number | null;
1427
+ autoplayTries: number;
1406
1428
  private static _manager;
1407
1429
  private readonly data;
1408
1430
  private dynamicLoopInterval;
@@ -2136,5 +2158,5 @@ declare class Plugin {
2136
2158
  load(manager: Manager): void;
2137
2159
  }
2138
2160
 
2139
- export { AutoPlayUtils, AvailableFilters, Filters, LoadTypes, Manager, ManagerEventTypes, Node, Player, PlayerStateEventTypes, Plugin, Queue, Rest, SearchPlatform, SeverityTypes, SponsorBlockSegment, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
2161
+ export { AutoPlayPlatform, AutoPlayUtils, AvailableFilters, Filters, LoadTypes, Manager, ManagerEventTypes, Node, Player, PlayerStateEventTypes, Plugin, Queue, Rest, SearchPlatform, SeverityTypes, SponsorBlockSegment, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
2140
2162
  export type { CPUStats, EqualizerBand, Exception, Extendable, FrameStats, LavalinkInfo, LavalinkResponse, LoadType, Lyrics, LyricsLine, ManagerEvents, ManagerOptions, MemoryStats, NodeMessage, NodeOptions, NodeStats, Payload, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerUpdate, PlaylistData, PlaylistInfoData, PlaylistRawData, SearchQuery, SearchResult, Severity, Sizes, SponsorBlockChapterStarted, SponsorBlockChaptersLoaded, SponsorBlockSegmentEventType, SponsorBlockSegmentEvents, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, State, Track, TrackData, TrackDataInfo, TrackEndEvent, TrackEndReason, TrackExceptionEvent, TrackPluginInfo, TrackSourceName, TrackStartEvent, TrackStuckEvent, UseNodeOption, VoicePacket, VoiceServer, VoiceState, WebSocketClosedEvent };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ManagerEventTypes = exports.PlayerStateEventTypes = exports.SearchPlatform = exports.UseNodeOptions = exports.TrackPartial = exports.Manager = void 0;
3
+ exports.ManagerEventTypes = exports.PlayerStateEventTypes = exports.AutoPlayPlatform = exports.SearchPlatform = exports.UseNodeOptions = exports.TrackPartial = exports.Manager = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const Utils_1 = require("./Utils");
6
6
  const collection_1 = require("@discordjs/collection");
@@ -27,7 +27,7 @@ class Manager extends events_1.EventEmitter {
27
27
  * @param options.enabledPlugins - An array of enabledPlugins to load.
28
28
  * @param options.nodes - An array of node options to create nodes from.
29
29
  * @param options.playNextOnEnd - Whether to automatically play the first track in the queue when the player is created.
30
- * @param options.autoPlaySearchPlatform - The search platform autoplay will use. Fallback to Youtube if not found.
30
+ * @param options.autoPlaySearchPlatforms - The search platform autoplay will use. Fallback to Youtube if not found.
31
31
  * @param options.enablePriorityMode - Whether to use the priority when selecting a node to play on.
32
32
  * @param options.clientName - The name of the client to send to Lavalink.
33
33
  * @param options.defaultSearchPlatform - The default search platform to use when searching for tracks.
@@ -61,7 +61,6 @@ class Manager extends events_1.EventEmitter {
61
61
  enablePriorityMode: false,
62
62
  clientName: "Magmastream",
63
63
  defaultSearchPlatform: SearchPlatform.YouTube,
64
- // autoPlaySearchPlatform: SearchPlatform.YouTube,
65
64
  useNode: UseNodeOptions.LeastPlayers,
66
65
  maxPreviousTracks: options.maxPreviousTracks ?? 20,
67
66
  ...options,
@@ -924,6 +923,13 @@ var SearchPlatform;
924
923
  SearchPlatform["YouTube"] = "ytsearch";
925
924
  SearchPlatform["YouTubeMusic"] = "ytmsearch";
926
925
  })(SearchPlatform || (exports.SearchPlatform = SearchPlatform = {}));
926
+ var AutoPlayPlatform;
927
+ (function (AutoPlayPlatform) {
928
+ AutoPlayPlatform["Spotify"] = "spotify";
929
+ AutoPlayPlatform["Deezer"] = "deezer";
930
+ AutoPlayPlatform["SoundCloud"] = "soundcloud";
931
+ AutoPlayPlatform["YouTube"] = "youtube";
932
+ })(AutoPlayPlatform || (exports.AutoPlayPlatform = AutoPlayPlatform = {}));
927
933
  var PlayerStateEventTypes;
928
934
  (function (PlayerStateEventTypes) {
929
935
  PlayerStateEventTypes["AutoPlayChange"] = "playerAutoplay";
@@ -602,13 +602,13 @@ class Node {
602
602
  */
603
603
  async handleAutoplay(player, attempt = 0) {
604
604
  // If autoplay is not enabled or all attempts have failed, early exit
605
- if (!player.isAutoplay || attempt === player.autoplayTries || !player.queue.previous.length)
605
+ if (!player.isAutoplay || attempt > player.autoplayTries || !player.queue.previous.length)
606
606
  return false;
607
607
  const lastTrack = player.queue.previous[player.queue.previous.length - 1];
608
608
  lastTrack.requester = player.get("Internal_BotUser");
609
609
  if (!lastTrack)
610
610
  return false;
611
- const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(player, lastTrack, attempt);
611
+ const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(lastTrack);
612
612
  if (tracks.length) {
613
613
  player.queue.add(tracks[0]);
614
614
  await player.play();
@@ -716,13 +716,13 @@ class Node {
716
716
  this.manager.emit(Manager_1.ManagerEventTypes.QueueEnd, player, track, payload);
717
717
  return;
718
718
  }
719
- let attempts = 1;
719
+ let attempt = 1;
720
720
  let success = false;
721
- while (attempts <= player.autoplayTries) {
722
- success = await this.handleAutoplay(player, attempts);
721
+ while (attempt <= player.autoplayTries) {
722
+ success = await this.handleAutoplay(player, attempt);
723
723
  if (success)
724
724
  return;
725
- attempts++;
725
+ attempt++;
726
726
  }
727
727
  // If all attempts fail, reset the player state and emit queueEnd
728
728
  player.playing = false;
@@ -50,7 +50,7 @@ class Player {
50
50
  /** The autoplay state of the player. */
51
51
  isAutoplay = false;
52
52
  /** The number of times to try autoplay before emitting queueEnd. */
53
- autoplayTries = null;
53
+ autoplayTries = 3;
54
54
  static _manager;
55
55
  data = {};
56
56
  dynamicLoopInterval = null;
@@ -375,7 +375,7 @@ class Player {
375
375
  * @returns {Promise<Track[]>} - Array of recommended tracks.
376
376
  */
377
377
  async getRecommendedTracks(track) {
378
- const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(this, track);
378
+ const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(track);
379
379
  return tracks;
380
380
  }
381
381
  /**
@@ -143,58 +143,42 @@ class AutoPlayUtils {
143
143
  throw new Error("AutoPlayUtils.init() requires a valid Manager instance.");
144
144
  this.manager = manager;
145
145
  }
146
- static async getRecommendedTracks(player, track, attempt = 0) {
146
+ /**
147
+ * Gets recommended tracks for the given track.
148
+ * @param track The track to get recommended tracks for.
149
+ * @returns An array of recommended tracks.
150
+ */
151
+ static async getRecommendedTracks(track) {
147
152
  const node = this.manager.useableNode;
148
153
  if (!node) {
149
154
  throw new Error("No available nodes.");
150
155
  }
151
- if (!player.isAutoplay) {
152
- return [];
153
- }
154
- if (attempt >= player.autoplayTries) {
155
- return [];
156
- }
157
- if (!player.queue.previous.length) {
158
- return [];
159
- }
160
156
  const apiKey = this.manager.options.lastFmApiKey;
161
157
  const enabledSources = node.info.sourceManagers;
162
- const { autoPlaySearchPlatform } = this.manager.options;
163
- const supportedPlatforms = ["spotify", "deezer", "soundcloud", "youtube"];
164
- const platformMapping = {
165
- [Manager_1.SearchPlatform.AppleMusic]: "applemusic",
166
- [Manager_1.SearchPlatform.Bandcamp]: "bandcamp",
167
- [Manager_1.SearchPlatform.Deezer]: "deezer",
168
- [Manager_1.SearchPlatform.Jiosaavn]: "jiosaavn",
169
- [Manager_1.SearchPlatform.SoundCloud]: "soundcloud",
170
- [Manager_1.SearchPlatform.Spotify]: "spotify",
171
- [Manager_1.SearchPlatform.Tidal]: "tidal",
172
- [Manager_1.SearchPlatform.VKMusic]: "vkmusic",
173
- [Manager_1.SearchPlatform.YouTube]: "youtube",
174
- [Manager_1.SearchPlatform.YouTubeMusic]: "youtube",
175
- };
176
- const mappedPlatform = platformMapping[autoPlaySearchPlatform];
177
- // Last attempt fallback to YouTube
178
- if (attempt === player.autoplayTries - 1 && player.autoplayTries > 1 && enabledSources.includes("youtube")) {
179
- return await this.getRecommendedTracksFromYouTube(track);
180
- }
181
- // Check if the preferred autoplay platform is supported and enabled
182
- if (mappedPlatform && supportedPlatforms.includes(mappedPlatform) && enabledSources.includes(mappedPlatform)) {
183
- return await this.getRecommendedTracksFromSource(track, mappedPlatform);
158
+ const autoPlaySearchPlatforms = this.manager.options.autoPlaySearchPlatforms;
159
+ // Iterate over autoplay platforms in order of priority
160
+ for (const platform of autoPlaySearchPlatforms) {
161
+ if (enabledSources.includes(platform)) {
162
+ const recommendedTracks = await this.getRecommendedTracksFromSource(track, platform);
163
+ // If tracks are found, return them immediately
164
+ if (recommendedTracks.length > 0) {
165
+ return recommendedTracks;
166
+ }
167
+ }
184
168
  }
185
169
  // Check if Last.fm API is available
186
170
  if (apiKey) {
187
171
  return await this.getRecommendedTracksFromLastFm(track, apiKey);
188
172
  }
189
- // Fallback to YouTube if all else fails
190
- if (enabledSources.includes("youtube")) {
191
- return await this.getRecommendedTracksFromYouTube(track);
192
- }
193
173
  return [];
194
174
  }
175
+ /**
176
+ * Gets recommended tracks from Last.fm for the given track.
177
+ * @param track The track to get recommended tracks for.
178
+ * @param apiKey The API key for Last.fm.
179
+ * @returns An array of recommended tracks.
180
+ */
195
181
  static async getRecommendedTracksFromLastFm(track, apiKey) {
196
- const enabledSources = this.manager.useableNode.info.sourceManagers;
197
- const selectedSource = this.selectPlatform(enabledSources);
198
182
  let { author: artist } = track;
199
183
  const { title } = track;
200
184
  if (!artist || !title) {
@@ -206,7 +190,7 @@ class AutoPlayUtils {
206
190
  return [];
207
191
  }
208
192
  const randomTrack = response.data.toptracks.track[Math.floor(Math.random() * response.data.toptracks.track.length)];
209
- const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, track.requester);
193
+ const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
210
194
  if (res.loadType === LoadTypes.Empty || res.loadType === LoadTypes.Error) {
211
195
  return [];
212
196
  }
@@ -233,7 +217,7 @@ class AutoPlayUtils {
233
217
  response = await axios_1.default.get(url);
234
218
  }
235
219
  catch (error) {
236
- console.log(error);
220
+ console.error("[AutoPlay] Error fetching similar tracks from Last.fm:", error);
237
221
  return [];
238
222
  }
239
223
  if (response.data.error || !response.data.similartracks?.track?.length) {
@@ -244,7 +228,7 @@ class AutoPlayUtils {
244
228
  return [];
245
229
  }
246
230
  const randomTrack = retryResponse.data.toptracks.track[Math.floor(Math.random() * retryResponse.data.toptracks.track.length)];
247
- const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, track.requester);
231
+ const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
248
232
  if (res.loadType === LoadTypes.Empty || res.loadType === LoadTypes.Error) {
249
233
  return [];
250
234
  }
@@ -258,7 +242,7 @@ class AutoPlayUtils {
258
242
  if (!randomTrack) {
259
243
  return [];
260
244
  }
261
- const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: selectedSource }, track.requester);
245
+ const res = await this.manager.search({ query: `${randomTrack.artist.name} - ${randomTrack.name}`, source: this.manager.options.defaultSearchPlatform }, track.requester);
262
246
  if (res.loadType === LoadTypes.Empty || res.loadType === LoadTypes.Error) {
263
247
  return [];
264
248
  }
@@ -269,8 +253,14 @@ class AutoPlayUtils {
269
253
  }
270
254
  return res.tracks;
271
255
  }
272
- static async getRecommendedTracksFromSource(track, mappedPlatform) {
273
- switch (mappedPlatform) {
256
+ /**
257
+ * Gets recommended tracks from the given source.
258
+ * @param track The track to get recommended tracks for.
259
+ * @param platform The source to get recommended tracks from.
260
+ * @returns An array of recommended tracks.
261
+ */
262
+ static async getRecommendedTracksFromSource(track, platform) {
263
+ switch (platform) {
274
264
  case "spotify":
275
265
  try {
276
266
  if (!track.uri.includes("spotify")) {
@@ -315,7 +305,7 @@ class AutoPlayUtils {
315
305
  body = response.data;
316
306
  }
317
307
  catch (error) {
318
- console.error("[AutoPlay] Failed to get access token:", error.response?.status, error.response?.data || error.message);
308
+ console.error("[AutoPlay] Failed to get spotify access token:", error.response?.status, error.response?.data || error.message);
319
309
  return [];
320
310
  }
321
311
  let json;
@@ -330,7 +320,7 @@ class AutoPlayUtils {
330
320
  json = response.data;
331
321
  }
332
322
  catch (error) {
333
- console.error("[AutoPlay] Failed to fetch recommendations:", error.response?.status, error.response?.data || error.message);
323
+ console.error("[AutoPlay] Failed to fetch spotify recommendations:", error.response?.status, error.response?.data || error.message);
334
324
  return [];
335
325
  }
336
326
  if (!json.tracks || !json.tracks.length) {
@@ -350,9 +340,10 @@ class AutoPlayUtils {
350
340
  return res.tracks;
351
341
  }
352
342
  catch (error) {
353
- console.error("[AutoPlay] Unexpected error:", error.message || error);
343
+ console.error("[AutoPlay] Unexpected spotify error:", error.message || error);
354
344
  return [];
355
345
  }
346
+ break;
356
347
  case "deezer":
357
348
  if (!track.uri.includes("deezer")) {
358
349
  const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Manager_1.SearchPlatform.Deezer }, track.requester);
@@ -406,6 +397,7 @@ class AutoPlayUtils {
406
397
  return [];
407
398
  }
408
399
  return result.tracks;
400
+ break;
409
401
  case "soundcloud":
410
402
  if (!track.uri.includes("soundcloud")) {
411
403
  const res = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Manager_1.SearchPlatform.SoundCloud }, track.requester);
@@ -461,79 +453,39 @@ class AutoPlayUtils {
461
453
  return res.tracks;
462
454
  }
463
455
  catch (error) {
464
- console.error("[AutoPlay] Error occurred while fetching recommendations:", error);
456
+ console.error("[AutoPlay] Error occurred while fetching soundcloud recommendations:", error);
465
457
  return [];
466
458
  }
459
+ break;
467
460
  case "youtube":
468
- return this.getRecommendedTracksFromYouTube(track);
461
+ const hasYouTubeURL = ["youtube.com", "youtu.be"].some((url) => track.uri.includes(url));
462
+ let videoID = null;
463
+ if (hasYouTubeURL) {
464
+ videoID = track.uri.split("=").pop();
465
+ }
466
+ else {
467
+ const searchResult = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Manager_1.SearchPlatform.YouTube }, track.requester);
468
+ videoID = searchResult.tracks[0]?.uri.split("=").pop();
469
+ }
470
+ if (!videoID) {
471
+ return [];
472
+ }
473
+ let randomIndex;
474
+ let searchURI;
475
+ do {
476
+ randomIndex = Math.floor(Math.random() * 23) + 2;
477
+ searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
478
+ } while (track.uri.includes(searchURI));
479
+ const res = await this.manager.search({ query: searchURI, source: Manager_1.SearchPlatform.YouTube }, track.requester);
480
+ if (res.loadType === LoadTypes.Empty || res.loadType === LoadTypes.Error) {
481
+ return [];
482
+ }
483
+ const filteredTracks = res.tracks.filter((t) => t.uri !== track.uri);
484
+ return filteredTracks;
469
485
  default:
470
486
  return [];
471
487
  }
472
488
  }
473
- static async getRecommendedTracksFromYouTube(track) {
474
- const hasYouTubeURL = ["youtube.com", "youtu.be"].some((url) => track.uri.includes(url));
475
- let videoID = null;
476
- if (hasYouTubeURL) {
477
- videoID = track.uri.split("=").pop();
478
- }
479
- else {
480
- const searchResult = await this.manager.search({ query: `${track.author} - ${track.title}`, source: Manager_1.SearchPlatform.YouTube }, track.requester);
481
- videoID = searchResult.tracks[0]?.uri.split("=").pop();
482
- }
483
- if (!videoID) {
484
- return [];
485
- }
486
- let randomIndex;
487
- let searchURI;
488
- do {
489
- randomIndex = Math.floor(Math.random() * 23) + 2;
490
- searchURI = `https://www.youtube.com/watch?v=${videoID}&list=RD${videoID}&index=${randomIndex}`;
491
- } while (track.uri.includes(searchURI));
492
- const res = await this.manager.search({ query: searchURI, source: Manager_1.SearchPlatform.YouTube }, track.requester);
493
- if (res.loadType === LoadTypes.Empty || res.loadType === LoadTypes.Error) {
494
- return [];
495
- }
496
- const filteredTracks = res.tracks.filter((t) => t.uri !== track.uri);
497
- return filteredTracks;
498
- }
499
- static selectPlatform(enabledSources) {
500
- const { autoPlaySearchPlatform } = this.manager.options;
501
- const platformMapping = {
502
- [Manager_1.SearchPlatform.AppleMusic]: "applemusic",
503
- [Manager_1.SearchPlatform.Bandcamp]: "bandcamp",
504
- [Manager_1.SearchPlatform.Deezer]: "deezer",
505
- [Manager_1.SearchPlatform.Jiosaavn]: "jiosaavn",
506
- [Manager_1.SearchPlatform.SoundCloud]: "soundcloud",
507
- [Manager_1.SearchPlatform.Spotify]: "spotify",
508
- [Manager_1.SearchPlatform.Tidal]: "tidal",
509
- [Manager_1.SearchPlatform.VKMusic]: "vkmusic",
510
- [Manager_1.SearchPlatform.YouTube]: "youtube",
511
- [Manager_1.SearchPlatform.YouTubeMusic]: "youtube",
512
- };
513
- // Try the autoPlaySearchPlatform first
514
- if (enabledSources.includes(platformMapping[autoPlaySearchPlatform])) {
515
- return autoPlaySearchPlatform;
516
- }
517
- // Fallback to other platforms in a predefined order
518
- const fallbackPlatforms = [
519
- Manager_1.SearchPlatform.Spotify,
520
- Manager_1.SearchPlatform.Deezer,
521
- Manager_1.SearchPlatform.SoundCloud,
522
- Manager_1.SearchPlatform.AppleMusic,
523
- Manager_1.SearchPlatform.Bandcamp,
524
- Manager_1.SearchPlatform.Jiosaavn,
525
- Manager_1.SearchPlatform.Tidal,
526
- Manager_1.SearchPlatform.VKMusic,
527
- Manager_1.SearchPlatform.YouTubeMusic,
528
- Manager_1.SearchPlatform.YouTube,
529
- ];
530
- for (const platform of fallbackPlatforms) {
531
- if (enabledSources.includes(platformMapping[platform])) {
532
- return platform;
533
- }
534
- }
535
- return null;
536
- }
537
489
  }
538
490
  exports.AutoPlayUtils = AutoPlayUtils;
539
491
  /** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
@@ -10,35 +10,38 @@ const Manager_1 = require("../structures/Manager");
10
10
  function managerCheck(options) {
11
11
  if (!options)
12
12
  throw new TypeError("ManagerOptions must not be empty.");
13
- const { playNextOnEnd, clientName, defaultSearchPlatform, autoPlaySearchPlatform, nodes, enabledPlugins, send, trackPartial, enablePriorityMode, useNode, normalizeYouTubeTitles, lastFmApiKey, maxPreviousTracks, } = options;
13
+ const { playNextOnEnd, clientName, defaultSearchPlatform, autoPlaySearchPlatforms, nodes, enabledPlugins, send, trackPartial, enablePriorityMode, useNode, normalizeYouTubeTitles, lastFmApiKey, maxPreviousTracks, } = options;
14
14
  // Validate playNextOnEnd option
15
15
  if (typeof playNextOnEnd !== "boolean") {
16
16
  throw new TypeError('Manager option "playNextOnEnd" must be a boolean.');
17
17
  }
18
18
  // Validate clientName option
19
- if (typeof clientName !== "undefined") {
19
+ if (typeof clientName !== undefined) {
20
20
  if (typeof clientName !== "string" || clientName.trim().length === 0) {
21
21
  throw new TypeError('Manager option "clientName" must be a non-empty string.');
22
22
  }
23
23
  }
24
24
  // Validate defaultSearchPlatform option
25
- if (typeof defaultSearchPlatform !== "undefined") {
25
+ if (typeof defaultSearchPlatform !== undefined) {
26
26
  if (!Object.values(Manager_1.SearchPlatform).includes(defaultSearchPlatform)) {
27
27
  throw new TypeError(`Manager option "defaultSearchPlatform" must be one of: ${Object.values(Manager_1.SearchPlatform).join(", ")}.`);
28
28
  }
29
29
  }
30
- // Validate autoPlaySearchPlatform
31
- if (typeof autoPlaySearchPlatform !== "undefined") {
32
- if (!Object.values(Manager_1.SearchPlatform).includes(autoPlaySearchPlatform)) {
33
- throw new TypeError(`Manager option "autoPlaySearchPlatform" must be one of: ${Object.values(Manager_1.SearchPlatform).join(", ")}.`);
30
+ // Validate autoPlaySearchPlatforms
31
+ if (autoPlaySearchPlatforms !== undefined) {
32
+ if (!Array.isArray(autoPlaySearchPlatforms)) {
33
+ throw new TypeError('Manager option "autoPlaySearchPlatforms" must be an array.');
34
+ }
35
+ if (!autoPlaySearchPlatforms.every((platform) => Object.values(Manager_1.AutoPlayPlatform).includes(platform))) {
36
+ throw new TypeError(`Manager option "autoPlaySearchPlatforms" must be an array of valid AutoPlayPlatform values.`);
34
37
  }
35
38
  }
36
39
  // Validate nodes option
37
- if (typeof nodes === "undefined" || !Array.isArray(nodes)) {
40
+ if (typeof nodes === undefined || !Array.isArray(nodes)) {
38
41
  throw new TypeError('Manager option "nodes" must be an array.');
39
42
  }
40
43
  // Validate enabledPlugins option
41
- if (typeof enabledPlugins !== "undefined" && !Array.isArray(enabledPlugins)) {
44
+ if (typeof enabledPlugins !== undefined && !Array.isArray(enabledPlugins)) {
42
45
  throw new TypeError('Manager option "enabledPlugins" must be a Plugin array.');
43
46
  }
44
47
  // Validate send option
@@ -46,7 +49,7 @@ function managerCheck(options) {
46
49
  throw new TypeError('Manager option "send" must be present and a function.');
47
50
  }
48
51
  // Validate trackPartial option
49
- if (typeof trackPartial !== "undefined") {
52
+ if (typeof trackPartial !== undefined) {
50
53
  if (!Array.isArray(trackPartial)) {
51
54
  throw new TypeError('Manager option "trackPartial" must be an array.');
52
55
  }
@@ -55,7 +58,7 @@ function managerCheck(options) {
55
58
  }
56
59
  }
57
60
  // Validate enablePriorityMode option
58
- if (typeof enablePriorityMode !== "undefined" && typeof enablePriorityMode !== "boolean") {
61
+ if (typeof enablePriorityMode !== undefined && typeof enablePriorityMode !== "boolean") {
59
62
  throw new TypeError('Manager option "enablePriorityMode" must be a boolean.');
60
63
  }
61
64
  // Validate node priority if enablePriorityMode is enabled
@@ -67,7 +70,7 @@ function managerCheck(options) {
67
70
  }
68
71
  }
69
72
  // Validate useNode option
70
- if (typeof useNode !== "undefined") {
73
+ if (typeof useNode !== undefined) {
71
74
  if (typeof useNode !== "string") {
72
75
  throw new TypeError('Manager option "useNode" must be a string "leastLoad" or "leastPlayers".');
73
76
  }
@@ -76,15 +79,15 @@ function managerCheck(options) {
76
79
  }
77
80
  }
78
81
  // Validate normalizeYouTubeTitles option
79
- if (typeof normalizeYouTubeTitles !== "undefined" && typeof normalizeYouTubeTitles !== "boolean") {
82
+ if (typeof normalizeYouTubeTitles !== undefined && typeof normalizeYouTubeTitles !== "boolean") {
80
83
  throw new TypeError('Manager option "normalizeYouTubeTitles" must be a boolean.');
81
84
  }
82
85
  // Validate lastFmApiKey option
83
- if (typeof lastFmApiKey !== "undefined" && (typeof lastFmApiKey !== "string" || lastFmApiKey.trim().length === 0)) {
86
+ if (typeof lastFmApiKey !== undefined && (typeof lastFmApiKey !== "string" || lastFmApiKey.trim().length === 0)) {
84
87
  throw new TypeError('Manager option "lastFmApiKey" must be a non-empty string.');
85
88
  }
86
89
  // Validate maxPreviousTracks option
87
- if (typeof maxPreviousTracks !== "undefined") {
90
+ if (typeof maxPreviousTracks !== undefined) {
88
91
  if (typeof maxPreviousTracks !== "number" || isNaN(maxPreviousTracks)) {
89
92
  throw new TypeError('Manager option "maxPreviousTracks" must be a number.');
90
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magmastream",
3
- "version": "2.9.0-dev.3",
3
+ "version": "2.9.0-dev.4",
4
4
  "description": "A user-friendly Lavalink client designed for NodeJS.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",