magmastream 2.9.2-dev.1 → 2.9.2-dev.10

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.
@@ -11,6 +11,7 @@ const RedisQueue_1 = require("../statestorage/RedisQueue");
11
11
  const Enums_1 = require("./Enums");
12
12
  const ws_1 = require("ws");
13
13
  const JsonQueue_1 = require("../statestorage/JsonQueue");
14
+ const MagmastreamError_1 = require("./MagmastreamError");
14
15
  class Player {
15
16
  options;
16
17
  /** The Queue for the Player. */
@@ -75,8 +76,12 @@ class Player {
75
76
  // If the Manager is not initiated, throw an error.
76
77
  if (!this.manager)
77
78
  this.manager = Utils_1.Structure.get("Player")._manager;
78
- if (!this.manager)
79
- throw new RangeError("Manager has not been initiated.");
79
+ if (!this.manager) {
80
+ throw new MagmastreamError_1.MagmaStreamError({
81
+ code: Enums_1.MagmaStreamErrorCode.GENERAL_INVALID_MANAGER,
82
+ message: "Manager instance is required.",
83
+ });
84
+ }
80
85
  this.clusterId = this.manager.options.clusterId || 0;
81
86
  // Check the player options for errors.
82
87
  (0, playerCheck_1.default)(options);
@@ -102,8 +107,13 @@ class Player {
102
107
  const node = this.manager.nodes.get(options.nodeIdentifier);
103
108
  this.node = node || this.manager.useableNode;
104
109
  // If no node is available, throw an error.
105
- if (!this.node)
106
- throw new RangeError("No available nodes.");
110
+ if (!this.node) {
111
+ throw new MagmastreamError_1.MagmaStreamError({
112
+ code: Enums_1.MagmaStreamErrorCode.MANAGER_NO_NODES,
113
+ message: "No available nodes for the player found.",
114
+ context: { guildId: this.guildId },
115
+ });
116
+ }
107
117
  // Initialize the queue with the guild ID and manager.
108
118
  switch (this.manager.options.stateStorage.type) {
109
119
  case Enums_1.StateStorageType.Redis:
@@ -169,7 +179,11 @@ class Player {
169
179
  connect() {
170
180
  // Check if the voice channel has been set.
171
181
  if (!this.voiceChannelId) {
172
- throw new RangeError("No voice channel has been set. You must use the `setVoiceChannelId()` method to set the voice channel before connecting.");
182
+ throw new MagmastreamError_1.MagmaStreamError({
183
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
184
+ message: "No voice channel has been set. You must set the voice channel before connecting.",
185
+ context: { voiceChannelId: this.voiceChannelId },
186
+ });
173
187
  }
174
188
  // Set the player state to connecting.
175
189
  this.state = Enums_1.StateTypes.Connecting;
@@ -268,8 +282,12 @@ class Player {
268
282
  */
269
283
  setVoiceChannelId(channel) {
270
284
  // Validate the channel parameter
271
- if (typeof channel !== "string")
272
- throw new TypeError("Channel must be a non-empty string.");
285
+ if (typeof channel !== "string") {
286
+ throw new MagmastreamError_1.MagmaStreamError({
287
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
288
+ message: "Channel must be a non-empty string.",
289
+ });
290
+ }
273
291
  // Clone the current player state for comparison
274
292
  const oldPlayer = this ? { ...this } : null;
275
293
  // Update the player voice channel
@@ -300,8 +318,12 @@ class Player {
300
318
  */
301
319
  setTextChannelId(channel) {
302
320
  // Validate the channel parameter
303
- if (typeof channel !== "string")
304
- throw new TypeError("Channel must be a non-empty string.");
321
+ if (typeof channel !== "string") {
322
+ throw new MagmastreamError_1.MagmaStreamError({
323
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
324
+ message: "Channel must be a non-empty string.",
325
+ });
326
+ }
305
327
  // Clone the current player state for comparison
306
328
  const oldPlayer = this ? { ...this } : null;
307
329
  // Update the text channel property
@@ -328,8 +350,12 @@ class Player {
328
350
  */
329
351
  setNowPlayingMessage(message) {
330
352
  if (!message) {
331
- throw new TypeError("You must provide the message of the now playing message.");
353
+ throw new MagmastreamError_1.MagmaStreamError({
354
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_NOW_PLAYING_MESSAGE,
355
+ message: "You must provide the message of the now playing message.",
356
+ });
332
357
  }
358
+ this.set("nowPlayingMessage", message);
333
359
  this.nowPlayingMessage = message;
334
360
  return this.nowPlayingMessage;
335
361
  }
@@ -337,8 +363,14 @@ class Player {
337
363
  if (typeof optionsOrTrack !== "undefined" && Utils_1.TrackUtils.validate(optionsOrTrack)) {
338
364
  await this.queue.setCurrent(optionsOrTrack);
339
365
  }
340
- if (!(await this.queue.getCurrent()))
341
- throw new RangeError("No current track.");
366
+ if (!(await this.queue.getCurrent())) {
367
+ const error = new MagmastreamError_1.MagmaStreamError({
368
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_QUEUE_EMPTY,
369
+ message: "The queue is empty.",
370
+ });
371
+ console.error(error);
372
+ return this;
373
+ }
342
374
  const finalOptions = playOptions
343
375
  ? playOptions
344
376
  : ["startTime", "endTime", "noReplace"].every((v) => Object.keys(optionsOrTrack || {}).includes(v))
@@ -369,11 +401,21 @@ class Player {
369
401
  */
370
402
  setAutoplay(autoplayState, AutoplayUser, tries) {
371
403
  if (typeof autoplayState !== "boolean") {
372
- throw new Error("autoplayState must be a boolean.");
404
+ const error = new MagmastreamError_1.MagmaStreamError({
405
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_AUTOPLAY,
406
+ message: "autoplayState must be a boolean.",
407
+ });
408
+ console.error(error);
409
+ return this;
373
410
  }
374
411
  if (autoplayState) {
375
412
  if (!AutoplayUser) {
376
- throw new Error("AutoplayUser must be provided when enabling autoplay.");
413
+ const error = new MagmastreamError_1.MagmaStreamError({
414
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_AUTOPLAY,
415
+ message: "AutoplayUser must be provided when enabling autoplay.",
416
+ });
417
+ console.error(error);
418
+ return this;
377
419
  }
378
420
  this.autoplayTries = tries && typeof tries === "number" && tries > 0 ? tries : 3; // Default to 3 if invalid
379
421
  this.isAutoplay = true;
@@ -416,16 +458,26 @@ class Player {
416
458
  * player.setVolume(50);
417
459
  */
418
460
  async setVolume(volume) {
419
- if (isNaN(volume))
420
- throw new TypeError("Volume must be a number.");
461
+ if (isNaN(volume)) {
462
+ throw new MagmastreamError_1.MagmaStreamError({
463
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_VOLUME,
464
+ message: "Volume must be a number.",
465
+ });
466
+ }
421
467
  if (this.options.applyVolumeAsFilter) {
422
468
  if (volume < 0 || volume > 500) {
423
- throw new RangeError("Volume must be between 0 and 500 when using filter mode (100 = 100%).");
469
+ throw new MagmastreamError_1.MagmaStreamError({
470
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_VOLUME,
471
+ message: "Volume must be between 0 and 500 when using filter mode (100 = 100%).",
472
+ });
424
473
  }
425
474
  }
426
475
  else {
427
476
  if (volume < 0 || volume > 1000) {
428
- throw new RangeError("Volume must be between 0 and 1000.");
477
+ throw new MagmastreamError_1.MagmaStreamError({
478
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_VOLUME,
479
+ message: "Volume must be between 0 and 1000.",
480
+ });
429
481
  }
430
482
  }
431
483
  const oldVolume = this.volume;
@@ -481,8 +533,12 @@ class Player {
481
533
  */
482
534
  setTrackRepeat(repeat) {
483
535
  // Ensure the repeat parameter is a boolean
484
- if (typeof repeat !== "boolean")
485
- throw new TypeError('Repeat can only be "true" or "false".');
536
+ if (typeof repeat !== "boolean") {
537
+ throw new MagmastreamError_1.MagmaStreamError({
538
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_REPEAT,
539
+ message: "Repeat must be a boolean.",
540
+ });
541
+ }
486
542
  // Clone the current player state for event emission
487
543
  const oldPlayer = this ? { ...this } : null;
488
544
  if (repeat) {
@@ -517,8 +573,12 @@ class Player {
517
573
  */
518
574
  setQueueRepeat(repeat) {
519
575
  // Ensure the repeat parameter is a boolean
520
- if (typeof repeat !== "boolean")
521
- throw new TypeError('Repeat can only be "true" or "false".');
576
+ if (typeof repeat !== "boolean") {
577
+ throw new MagmastreamError_1.MagmaStreamError({
578
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_REPEAT,
579
+ message: "Repeat must be a boolean.",
580
+ });
581
+ }
522
582
  // Get the current player state
523
583
  const oldPlayer = this ? { ...this } : null;
524
584
  // Update the player state
@@ -555,11 +615,17 @@ class Player {
555
615
  async setDynamicRepeat(repeat, ms) {
556
616
  // Validate the repeat parameter
557
617
  if (typeof repeat !== "boolean") {
558
- throw new TypeError('Repeat can only be "true" or "false".');
618
+ throw new MagmastreamError_1.MagmaStreamError({
619
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_REPEAT,
620
+ message: "Repeat must be a boolean.",
621
+ });
559
622
  }
560
623
  // Ensure the queue has more than one track for dynamic repeat
561
624
  if ((await this.queue.size()) <= 1) {
562
- throw new RangeError("The queue size must be greater than 1.");
625
+ throw new MagmastreamError_1.MagmaStreamError({
626
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_REPEAT,
627
+ message: "The queue size must be greater than 1.",
628
+ });
563
629
  }
564
630
  // Clone the current player state for comparison
565
631
  const oldPlayer = this ? { ...this } : null;
@@ -633,12 +699,25 @@ class Player {
633
699
  async stop(amount) {
634
700
  const oldPlayer = { ...this };
635
701
  let removedTracks = [];
702
+ const current = await this.queue.getCurrent(); // may be null
636
703
  if (typeof amount === "number" && amount > 1) {
637
- if (amount > (await this.queue.size()))
638
- throw new RangeError("Cannot skip more than the queue length.");
704
+ const queueSize = await this.queue.size();
705
+ if (amount > queueSize) {
706
+ throw new MagmastreamError_1.MagmaStreamError({
707
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_QUEUE_EMPTY,
708
+ message: "The amount of tracks to remove is greater than the queue size.",
709
+ });
710
+ }
639
711
  removedTracks = await this.queue.getSlice(0, amount - 1);
640
712
  await this.queue.modifyAt(0, amount - 1);
713
+ const toAdd = [];
714
+ if (current)
715
+ toAdd.push(current);
716
+ toAdd.push(...removedTracks);
717
+ await this.queue.addPrevious(toAdd);
641
718
  }
719
+ // This will trigger trackEnd for the current track; since we already added current,
720
+ // addPrevious will ignore duplicates.
642
721
  this.node.rest.updatePlayer({
643
722
  guildId: this.guildId,
644
723
  data: {
@@ -663,8 +742,12 @@ class Player {
663
742
  */
664
743
  async pause(pause) {
665
744
  // Validate the pause parameter to ensure it's a boolean.
666
- if (typeof pause !== "boolean")
667
- throw new RangeError('Pause can only be "true" or "false".');
745
+ if (typeof pause !== "boolean") {
746
+ throw new MagmastreamError_1.MagmaStreamError({
747
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_PAUSE,
748
+ message: "Pause must be a boolean.",
749
+ });
750
+ }
668
751
  // If the pause state is already as desired or there are no tracks, return early.
669
752
  if (this.paused === pause || !this.queue.totalSize)
670
753
  return this;
@@ -698,19 +781,33 @@ class Player {
698
781
  * @throws {Error} If there are no previous tracks in the queue.
699
782
  * @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
700
783
  */
701
- async previous() {
702
- // Get and remove the most recent previous track
784
+ async previous(addBackToQueue = true) {
785
+ // Pop the most recent previous track (from tail)
703
786
  const lastTrack = await this.queue.popPrevious();
704
787
  if (!lastTrack) {
705
788
  await this.queue.clearPrevious();
706
- throw new Error("No previous track available.");
789
+ const error = new MagmastreamError_1.MagmaStreamError({
790
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_PREVIOUS_EMPTY,
791
+ message: "Previous queue is empty.",
792
+ });
793
+ console.error(error);
794
+ return this;
707
795
  }
708
796
  // Capture the current state of the player before making changes.
709
797
  const oldPlayer = { ...this };
710
- // Set skip flag so trackEnd doesn't add current to previous
798
+ // Prevent re-adding the current track
711
799
  this.set("skipFlag", true);
712
- await this.play(lastTrack);
713
- // Emit state update
800
+ // Add the current track to the queue if addBackToQueue is true
801
+ if (addBackToQueue) {
802
+ const currentPlayingTrack = await this.queue.getCurrent();
803
+ if (currentPlayingTrack) {
804
+ await this.queue.add(currentPlayingTrack, 0);
805
+ }
806
+ await this.play(lastTrack);
807
+ }
808
+ else {
809
+ await this.play(lastTrack);
810
+ }
714
811
  this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this, {
715
812
  changeType: Enums_1.PlayerStateEventTypes.TrackChange,
716
813
  details: {
@@ -734,7 +831,10 @@ class Player {
734
831
  position = Number(position);
735
832
  // Check if the position is valid.
736
833
  if (isNaN(position)) {
737
- throw new RangeError("Position must be a number.");
834
+ throw new MagmastreamError_1.MagmaStreamError({
835
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_SEEK,
836
+ message: "Position must be a number.",
837
+ });
738
838
  }
739
839
  // Get the old player state.
740
840
  const oldPlayer = this ? { ...this } : null;
@@ -798,8 +898,14 @@ class Player {
798
898
  */
799
899
  async moveNode(identifier) {
800
900
  const node = this.manager.nodes.get(identifier);
801
- if (!node)
802
- throw new Error(`Node with identifier ${identifier} not found`);
901
+ if (!node) {
902
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Tried to move to non-existent node: ${identifier}`);
903
+ throw new MagmastreamError_1.MagmaStreamError({
904
+ code: Enums_1.MagmaStreamErrorCode.MANAGER_NODE_NOT_FOUND,
905
+ message: "Node not found.",
906
+ context: { identifier },
907
+ });
908
+ }
803
909
  if (this.state !== Enums_1.StateTypes.Connected) {
804
910
  return this;
805
911
  }
@@ -814,7 +920,12 @@ class Player {
814
920
  const token = this.voiceState?.event?.token;
815
921
  const endpoint = this.voiceState?.event?.endpoint;
816
922
  if (!sessionId || !token || !endpoint) {
817
- throw new Error(`Voice state is not properly initialized for player ${this.guildId}. The bot might not be connected to a voice channel.`);
923
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Voice state is not properly initialized for player ${this.guildId}. The bot might not be connected to a voice channel.`);
924
+ throw new MagmastreamError_1.MagmaStreamError({
925
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_STATE_INVALID,
926
+ message: `Voice state is not properly initialized. The bot might not be connected to a voice channel.`,
927
+ context: { guildId: this.guildId },
928
+ });
818
929
  }
819
930
  await this.node.rest.destroyPlayer(this.guildId).catch(() => { });
820
931
  this.manager.players.delete(this.guildId);
@@ -826,8 +937,17 @@ class Player {
826
937
  });
827
938
  await this.filters.updateFilters();
828
939
  }
829
- catch (error) {
830
- throw new Error(`Failed to move player to node ${identifier}: ${error}`);
940
+ catch (err) {
941
+ const error = err instanceof MagmastreamError_1.MagmaStreamError
942
+ ? err
943
+ : new MagmastreamError_1.MagmaStreamError({
944
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_MOVE_FAILED,
945
+ message: "Error moving player to node.",
946
+ cause: err,
947
+ context: { guildId: this.guildId },
948
+ });
949
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, error);
950
+ console.error(error);
831
951
  }
832
952
  }
833
953
  /**
@@ -839,12 +959,24 @@ class Player {
839
959
  * @returns {Promise<Player>} - The new player instance.
840
960
  */
841
961
  async switchGuild(newOptions, force = false) {
842
- if (!newOptions.guildId)
843
- throw new Error("guildId is required");
844
- if (!newOptions.voiceChannelId)
845
- throw new Error("Voice channel ID is required");
846
- if (!newOptions.textChannelId)
847
- throw new Error("Text channel ID is required");
962
+ if (!newOptions.guildId) {
963
+ throw new MagmastreamError_1.MagmaStreamError({
964
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
965
+ message: "guildId is required for switchGuild",
966
+ });
967
+ }
968
+ if (!newOptions.voiceChannelId) {
969
+ throw new MagmastreamError_1.MagmaStreamError({
970
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
971
+ message: "voiceChannelId is required for switchGuild",
972
+ });
973
+ }
974
+ if (!newOptions.textChannelId) {
975
+ throw new MagmastreamError_1.MagmaStreamError({
976
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
977
+ message: "textChannelId is required for switchGuild",
978
+ });
979
+ }
848
980
  // Check if a player already exists for the new guild
849
981
  let newPlayer = this.manager.getPlayer(newOptions.guildId);
850
982
  // If the player already exists and force is false, return the existing player
@@ -943,14 +1075,8 @@ class Player {
943
1075
  * Retrieves the current lyrics for the playing track.
944
1076
  * @param skipTrackSource - Indicates whether to skip the track source when fetching lyrics.
945
1077
  * @returns {Promise<Lyrics>} - The lyrics of the current track.
946
- * @throws {RangeError} - If the 'lavalyrics-plugin' is not available on the Lavalink node.
947
1078
  */
948
1079
  async getCurrentLyrics(skipTrackSource = false) {
949
- // Check if the 'lavalyrics-plugin' is available on the node
950
- const hasLyricsPlugin = this.node.info.plugins.some((plugin) => plugin.name === "lavalyrics-plugin");
951
- if (!hasLyricsPlugin) {
952
- throw new RangeError(`There is no lavalyrics-plugin available in the Lavalink node: ${this.node.options.identifier}`);
953
- }
954
1080
  // Fetch the lyrics for the current track from the Lavalink node
955
1081
  let result = (await this.node.getLyrics(await this.queue.getCurrent(), skipTrackSource));
956
1082
  // If no lyrics are found, return a default empty lyrics object
@@ -971,8 +1097,13 @@ class Player {
971
1097
  * @throws {Error} - If the node is not a NodeLink.
972
1098
  */
973
1099
  async setupVoiceReceiver() {
974
- if (!this.node.isNodeLink)
975
- throw new Error("This function is only available for NodeLinks");
1100
+ if (!this.node.isNodeLink) {
1101
+ throw new MagmastreamError_1.MagmaStreamError({
1102
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1103
+ message: `The node is not a NodeLink, cannot setup voice receiver.`,
1104
+ context: { identifier: this.node.options.identifier },
1105
+ });
1106
+ }
976
1107
  if (this.voiceReceiverWsClient)
977
1108
  await this.removeVoiceReceiver();
978
1109
  const headers = {
@@ -994,8 +1125,13 @@ class Player {
994
1125
  * @throws {Error} - If the node is not a NodeLink.
995
1126
  */
996
1127
  async removeVoiceReceiver() {
997
- if (!this.node.isNodeLink)
998
- throw new Error("This function is only available for NodeLinks");
1128
+ if (!this.node.isNodeLink) {
1129
+ throw new MagmastreamError_1.MagmaStreamError({
1130
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1131
+ message: `The node is not a NodeLink, cannot remove voice receiver.`,
1132
+ context: { identifier: this.node.options.identifier },
1133
+ });
1134
+ }
999
1135
  if (this.voiceReceiverWsClient) {
1000
1136
  this.voiceReceiverWsClient.close(1000, "destroy");
1001
1137
  this.voiceReceiverWsClient.removeAllListeners();
@@ -1021,8 +1157,13 @@ class Player {
1021
1157
  */
1022
1158
  async reconnectVoiceReceiver() {
1023
1159
  this.voiceReceiverReconnectTimeout = setTimeout(async () => {
1024
- if (this.voiceReceiverAttempt > this.voiceReceiverReconnectTries)
1025
- throw new Error("Failed to reconnect to voice receiver");
1160
+ if (this.voiceReceiverAttempt > this.voiceReceiverReconnectTries) {
1161
+ throw new MagmastreamError_1.MagmaStreamError({
1162
+ code: Enums_1.MagmaStreamErrorCode.PLAYER_VOICE_RECEIVER_ERROR,
1163
+ message: `Failed to reconnect to voice receiver for player ${this.guildId}`,
1164
+ context: { identifier: this.node.options.identifier },
1165
+ });
1166
+ }
1026
1167
  this.voiceReceiverWsClient?.removeAllListeners();
1027
1168
  this.voiceReceiverWsClient = null;
1028
1169
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[PLAYER] Reconnecting to voice receiver for player ${this.guildId}`);
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const axios_1 = tslib_1.__importDefault(require("axios"));
6
6
  const Enums_1 = require("./Enums");
7
7
  const Utils_1 = require("./Utils");
8
+ const MagmastreamError_1 = require("./MagmastreamError");
8
9
  /** Handles the requests sent to the Lavalink REST API. */
9
10
  class Rest {
10
11
  /** The Node that this Rest instance is connected to. */
@@ -38,12 +39,12 @@ class Rest {
38
39
  return this.sessionId;
39
40
  }
40
41
  /**
41
- * Retrieves all the players that are currently running on the node.
42
+ * Retrieves one the player that is currently running on the node.
42
43
  * @returns {Promise<unknown>} Returns the result of the GET request.
43
44
  */
44
- async getAllPlayers() {
45
+ async getPlayer(guildId) {
45
46
  // Send a GET request to the Lavalink Node to retrieve all the players.
46
- const result = await this.get(`/v4/sessions/${this.sessionId}/players`);
47
+ const result = (await this.get(`/v4/sessions/${this.sessionId}/players/${guildId}`));
47
48
  // Log the result of the request.
48
49
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] Getting all players on node: ${this.node.options.identifier} : ${Utils_1.JSONUtils.safe(result, 2)}`);
49
50
  // Return the result of the request.
@@ -93,7 +94,7 @@ class Rest {
93
94
  * @returns {Promise<unknown>} The response data of the request.
94
95
  */
95
96
  async request(method, endpoint, body) {
96
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] ${method} api call for endpoint: ${endpoint} with data: ${Utils_1.JSONUtils.safe(body, 2)}`);
97
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[REST] ${method} request to ${endpoint} with body: ${Utils_1.JSONUtils.safe(body, 2)}`);
97
98
  const config = {
98
99
  method,
99
100
  url: this.url + endpoint,
@@ -108,19 +109,29 @@ class Rest {
108
109
  const response = await (0, axios_1.default)(config);
109
110
  return response.data;
110
111
  }
111
- catch (error) {
112
+ catch (err) {
113
+ const error = err;
112
114
  if (!error.response) {
113
- console.error(`[REST] No response from node: ${error.message}`);
114
- return null;
115
+ throw new MagmastreamError_1.MagmaStreamError({
116
+ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
117
+ message: `No response from node ${this.node.options.identifier}: ${error.message}`,
118
+ });
115
119
  }
116
- if (error.response.data?.message === "Guild not found") {
120
+ const data = error.response.data;
121
+ if (data?.message === "Guild not found") {
117
122
  return [];
118
123
  }
119
- else if (error.response.status === 404) {
120
- await this.node.destroy();
121
- await this.node.manager.createNode(this.node.options).connect();
124
+ if (error.response.status === 401) {
125
+ throw new MagmastreamError_1.MagmaStreamError({
126
+ code: Enums_1.MagmaStreamErrorCode.REST_UNAUTHORIZED,
127
+ message: `Unauthorized access to node ${this.node.options.identifier}`,
128
+ });
122
129
  }
123
- return null;
130
+ const dataMessage = typeof data === "string" ? data : data?.message ? data.message : Utils_1.JSONUtils.safe(data, 2);
131
+ throw new MagmastreamError_1.MagmaStreamError({
132
+ code: Enums_1.MagmaStreamErrorCode.REST_REQUEST_FAILED,
133
+ message: `Request to node ${this.node.options.identifier} failed with status ${error.response.status}: ${dataMessage}`,
134
+ });
124
135
  }
125
136
  }
126
137
  /**