magmastream 2.9.2-dev.1 → 2.9.2-dev.3

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.
@@ -9,6 +9,7 @@ const ws_1 = tslib_1.__importDefault(require("ws"));
9
9
  const fs_1 = tslib_1.__importDefault(require("fs"));
10
10
  const path_1 = tslib_1.__importDefault(require("path"));
11
11
  const Enums_1 = require("./Enums");
12
+ const MagmastreamError_1 = require("./MagmastreamError");
12
13
  const validSponsorBlocks = Object.values(Enums_1.SponsorBlockSegment).map((v) => v.toLowerCase());
13
14
  class Node {
14
15
  manager;
@@ -40,8 +41,12 @@ class Node {
40
41
  constructor(manager, options) {
41
42
  this.manager = manager;
42
43
  this.options = options;
43
- if (!this.manager)
44
- throw new RangeError("Manager instance is required.");
44
+ if (!this.manager) {
45
+ throw new MagmastreamError_1.MagmaStreamError({
46
+ code: Enums_1.MagmaStreamErrorCode.GENERAL_INVALID_MANAGER,
47
+ message: "Manager instance is required.",
48
+ });
49
+ }
45
50
  if (this.manager.nodes.has(options.identifier || options.host)) {
46
51
  return this.manager.nodes.get(options.identifier || options.host);
47
52
  }
@@ -162,7 +167,11 @@ class Node {
162
167
  try {
163
168
  const sessionIds = JSON.parse(currentRaw);
164
169
  if (typeof sessionIds !== "object" || Array.isArray(sessionIds)) {
165
- throw new Error("[NODE] loadSessionIds invalid data type from Redis.");
170
+ throw new MagmastreamError_1.MagmaStreamError({
171
+ code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_LOAD_FAILED,
172
+ message: "Invalid sessionIds data type from Redis.",
173
+ context: { sessionIds },
174
+ });
166
175
  }
167
176
  this.sessionIdsMap = new Map(Object.entries(sessionIds));
168
177
  const compositeKey = `${this.options.identifier}::${this.manager.options.clusterId}`;
@@ -199,9 +208,9 @@ class Node {
199
208
  switch (this.manager.options.stateStorage.type) {
200
209
  case Enums_1.StateStorageType.Memory:
201
210
  case Enums_1.StateStorageType.JSON: {
202
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Updating sessionIds to file: ${this.sessionIdsFilePath}`);
203
211
  const compositeKey = `${this.options.identifier}::${this.manager.options.clusterId}`;
204
212
  const filePath = this.sessionIdsFilePath;
213
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Updating sessionIds to file: ${filePath}`);
205
214
  let updated = false;
206
215
  let retries = 3;
207
216
  while (!updated && retries > 0) {
@@ -227,8 +236,12 @@ class Node {
227
236
  catch (err) {
228
237
  retries--;
229
238
  if (retries === 0) {
230
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Failed to update sessionIds after retries: ${err.message}`);
231
- throw err;
239
+ throw new MagmastreamError_1.MagmaStreamError({
240
+ code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
241
+ message: `Failed to update sessionIds after retries.`,
242
+ cause: err instanceof Error ? err : undefined,
243
+ context: { filePath, compositeKey, storage: "file" },
244
+ });
232
245
  }
233
246
  await new Promise((r) => setTimeout(r, 50));
234
247
  }
@@ -239,27 +252,37 @@ class Node {
239
252
  const key = `${this.redisPrefix}node:sessionIds`;
240
253
  const compositeKey = `${this.options.identifier}::${this.manager.options.clusterId}`;
241
254
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Updating sessionIds in Redis key: ${key}`);
242
- const currentRaw = await this.manager.redis.get(key);
243
- let sessionIds;
244
- if (currentRaw) {
245
- try {
255
+ let sessionIds = {};
256
+ try {
257
+ const currentRaw = await this.manager.redis.get(key);
258
+ if (currentRaw) {
246
259
  sessionIds = JSON.parse(currentRaw);
247
260
  if (typeof sessionIds !== "object" || Array.isArray(sessionIds)) {
248
261
  throw new Error("Invalid data type in Redis");
249
262
  }
250
263
  }
251
- catch (err) {
252
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Corrupted Redis sessionIds, reinitializing: ${err.message}`);
264
+ else {
265
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Redis key not found — creating new sessionIds key.`);
253
266
  sessionIds = {};
254
267
  }
255
268
  }
256
- else {
257
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Redis key not found — creating new sessionIds key.`);
269
+ catch (err) {
270
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Corrupted Redis sessionIds, reinitializing: ${err.message}`);
258
271
  sessionIds = {};
259
272
  }
260
- sessionIds[compositeKey] = this.sessionId;
261
- this.sessionIdsMap = new Map(Object.entries(sessionIds));
262
- await this.manager.redis.set(key, Utils_1.JSONUtils.safe(sessionIds));
273
+ try {
274
+ sessionIds[compositeKey] = this.sessionId;
275
+ this.sessionIdsMap = new Map(Object.entries(sessionIds));
276
+ await this.manager.redis.set(key, Utils_1.JSONUtils.safe(sessionIds));
277
+ }
278
+ catch (err) {
279
+ throw new MagmastreamError_1.MagmaStreamError({
280
+ code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
281
+ message: `Failed to update sessionIds in Redis.`,
282
+ cause: err instanceof Error ? err : undefined,
283
+ context: { key, compositeKey, storage: "redis" },
284
+ });
285
+ }
263
286
  break;
264
287
  }
265
288
  }
@@ -371,7 +394,11 @@ class Node {
371
394
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Reconnecting node: ${Utils_1.JSONUtils.safe(debugInfo, 2)}`);
372
395
  this.reconnectTimeout = setTimeout(async () => {
373
396
  if (this.reconnectAttempts >= this.options.maxRetryAttempts) {
374
- const error = new Error(`Unable to connect after ${this.options.maxRetryAttempts} attempts.`);
397
+ const error = new MagmastreamError_1.MagmaStreamError({
398
+ code: Enums_1.MagmaStreamErrorCode.NODE_RECONNECT_FAILED,
399
+ message: `Unable to reconnect after ${this.options.maxRetryAttempts} attempts.`,
400
+ context: { ...debugInfo },
401
+ });
375
402
  this.manager.emit(Enums_1.ManagerEventTypes.NodeError, this, error);
376
403
  return await this.destroy();
377
404
  }
@@ -634,7 +661,8 @@ class Node {
634
661
  const skipFlag = player.get("skipFlag");
635
662
  const previous = await player.queue.getPrevious();
636
663
  const current = await player.queue.getCurrent();
637
- if (!skipFlag && (previous.length === 0 || (previous[0] && previous[0].track !== current?.track))) {
664
+ // Only add current to previous if it's not already the newest
665
+ if (!skipFlag && (previous.length === 0 || (previous.at(-1)?.track !== current?.track))) {
638
666
  await player.queue.addPrevious(current);
639
667
  }
640
668
  player.set("skipFlag", false);
@@ -696,10 +724,10 @@ class Node {
696
724
  if (!player.isAutoplay || attempt > player.autoplayTries || !(await player.queue.getPrevious()).length)
697
725
  return false;
698
726
  const PreviousQueue = await player.queue.getPrevious();
699
- const lastTrack = PreviousQueue?.at(-1);
700
- lastTrack.requester = player.get("Internal_AutoplayUser");
727
+ const lastTrack = PreviousQueue.at(-1); // newest is at tail
701
728
  if (!lastTrack)
702
729
  return false;
730
+ lastTrack.requester = player.get("Internal_AutoplayUser");
703
731
  const tracks = await Utils_1.AutoPlayUtils.getRecommendedTracks(lastTrack);
704
732
  const normalize = (str) => str
705
733
  .toLowerCase()
@@ -708,6 +736,7 @@ class Node {
708
736
  const filteredTracks = tracks.filter((track) => track.identifier !== lastTrack.identifier && track.uri !== lastTrack.uri && normalize(track.title) !== normalize(lastTrack.title));
709
737
  if (filteredTracks.length) {
710
738
  const randomTrack = filteredTracks[Math.floor(Math.random() * filteredTracks.length)];
739
+ console.log(randomTrack);
711
740
  await player.queue.add(randomTrack);
712
741
  await player.play();
713
742
  return true;
@@ -838,24 +867,35 @@ class Node {
838
867
  * @returns {Promise<Lyrics | NodeLinkGetLyrics>} A promise that resolves with the lyrics data.
839
868
  */
840
869
  async getLyrics(track, skipTrackSource = false, language) {
841
- if (!this.connected)
842
- throw new RangeError(`The node is not connected to the lavalink server: ${this.options.identifier}`);
870
+ if (!this.connected) {
871
+ throw new MagmastreamError_1.MagmaStreamError({
872
+ code: Enums_1.MagmaStreamErrorCode.NODE_DISCONNECTED,
873
+ message: `The node is not connected to the lavalink server.`,
874
+ context: { identifier: this.options.identifier },
875
+ });
876
+ }
843
877
  if (this.isNodeLink) {
844
878
  return (await this.rest.get(`/v4/loadlyrics?encodedTrack=${encodeURIComponent(track.track)}${language ? `&language=${language}` : ""}`));
845
879
  }
846
- if (!this.info.plugins.some((plugin) => plugin.name === "lavalyrics-plugin")) {
847
- throw new RangeError(`The plugin "lavalyrics-plugin" must be present in the lavalink node: ${this.options.identifier}`);
880
+ const requiredPlugins = ["lavalyrics-plugin"];
881
+ for (const plugin of requiredPlugins) {
882
+ if (!this.info.plugins.some((p) => p.name === plugin)) {
883
+ throw new MagmastreamError_1.MagmaStreamError({
884
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
885
+ message: `The plugin "${plugin}" must be present in the lavalink node.`,
886
+ context: { identifier: this.options.identifier },
887
+ });
888
+ }
848
889
  }
849
- if (!this.info.plugins.some((plugin) => plugin.name === "lavasrc-plugin" || plugin.name === "java-lyrics-plugin")) {
850
- throw new RangeError(`One of the following plugins must also be present in the lavalink node: "lavasrc-plugin" or "java-lyrics-plugin" (Node: ${this.options.identifier})`);
890
+ if (!this.info.plugins.some((p) => p.name === "lavasrc-plugin" || p.name === "java-lyrics-plugin")) {
891
+ throw new MagmastreamError_1.MagmaStreamError({
892
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
893
+ message: `One of the following plugins must also be present in the lavalink node: "lavasrc-plugin" or "java-lyrics-plugin".`,
894
+ context: { identifier: this.options.identifier },
895
+ });
851
896
  }
852
- return ((await this.rest.get(`/v4/lyrics?track=${encodeURIComponent(track.track)}&skipTrackSource=${skipTrackSource}`)) || {
853
- source: null,
854
- provider: null,
855
- text: null,
856
- lines: [],
857
- plugin: [],
858
- });
897
+ const lyrics = (await this.rest.get(`/v4/lyrics?track=${encodeURIComponent(track.track)}&skipTrackSource=${skipTrackSource}`));
898
+ return lyrics || { source: null, provider: null, text: null, lines: [], plugin: [] };
859
899
  }
860
900
  /**
861
901
  * Subscribes to lyrics for a player.
@@ -865,17 +905,50 @@ class Node {
865
905
  * @throws {RangeError} If the node is not connected to the lavalink server or if the java-lyrics-plugin is not available.
866
906
  */
867
907
  async lyricsSubscribe(guildId, skipTrackSource = false) {
868
- if (!this.connected)
869
- throw new RangeError(`The node is not connected to the lavalink server: ${this.options.identifier}`);
870
- if (this.isNodeLink)
871
- throw new RangeError(`The node is a node link: ${this.options.identifier}`);
872
- if (!this.info.plugins.some((plugin) => plugin.name === "lavalyrics-plugin")) {
873
- throw new RangeError(`The plugin "lavalyrics-plugin" must be present in the lavalink node: ${this.options.identifier}`);
908
+ if (!this.connected) {
909
+ throw new MagmastreamError_1.MagmaStreamError({
910
+ code: Enums_1.MagmaStreamErrorCode.NODE_DISCONNECTED,
911
+ message: `The node is not connected to the lavalink server.`,
912
+ context: { identifier: this.options.identifier },
913
+ });
914
+ }
915
+ if (this.isNodeLink) {
916
+ throw new MagmastreamError_1.MagmaStreamError({
917
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
918
+ message: `The node is a NodeLink, cannot subscribe to lyrics.`,
919
+ context: { identifier: this.options.identifier },
920
+ });
921
+ }
922
+ const requiredPlugins = ["lavalyrics-plugin"];
923
+ for (const plugin of requiredPlugins) {
924
+ if (!this.info.plugins.some((p) => p.name === plugin)) {
925
+ throw new MagmastreamError_1.MagmaStreamError({
926
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
927
+ message: `The plugin "${plugin}" must be present in the lavalink node.`,
928
+ context: { identifier: this.options.identifier },
929
+ });
930
+ }
931
+ }
932
+ if (!this.info.plugins.some((p) => p.name === "lavasrc-plugin" || p.name === "java-lyrics-plugin")) {
933
+ throw new MagmastreamError_1.MagmaStreamError({
934
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
935
+ message: `One of the following plugins must also be present in the lavalink node: "lavasrc-plugin" or "java-lyrics-plugin".`,
936
+ context: { identifier: this.options.identifier },
937
+ });
874
938
  }
875
- if (!this.info.plugins.some((plugin) => plugin.name === "lavasrc-plugin" || plugin.name === "java-lyrics-plugin")) {
876
- throw new RangeError(`One of the following plugins must also be present in the lavalink node: "lavasrc-plugin" or "java-lyrics-plugin" (Node: ${this.options.identifier})`);
939
+ try {
940
+ return await this.rest.post(`/v4/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe?skipTrackSource=${skipTrackSource}`, {});
941
+ }
942
+ catch (err) {
943
+ throw err instanceof MagmastreamError_1.MagmaStreamError
944
+ ? err
945
+ : new MagmastreamError_1.MagmaStreamError({
946
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
947
+ message: "Failed to subscribe to lyrics session.",
948
+ cause: err instanceof Error ? err : undefined,
949
+ context: { identifier: this.options.identifier, guildId, skipTrackSource },
950
+ });
877
951
  }
878
- return await this.rest.post(`/v4/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe?skipTrackSource=${skipTrackSource}`, {});
879
952
  }
880
953
  /**
881
954
  * Unsubscribes from lyrics for a player.
@@ -884,14 +957,40 @@ class Node {
884
957
  * @throws {RangeError} If the node is not connected to the lavalink server or if the java-lyrics-plugin is not available.
885
958
  */
886
959
  async lyricsUnsubscribe(guildId) {
887
- if (!this.connected)
888
- throw new RangeError(`The node is not connected to the lavalink server: ${this.options.identifier}`);
889
- if (this.isNodeLink)
890
- throw new RangeError(`The node is a node link: ${this.options.identifier}`);
960
+ if (!this.connected) {
961
+ throw new MagmastreamError_1.MagmaStreamError({
962
+ code: Enums_1.MagmaStreamErrorCode.NODE_DISCONNECTED,
963
+ message: `The node is not connected to the lavalink server.`,
964
+ context: { identifier: this.options.identifier },
965
+ });
966
+ }
967
+ if (this.isNodeLink) {
968
+ throw new MagmastreamError_1.MagmaStreamError({
969
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
970
+ message: `The node is a NodeLink, cannot unsubscribe from lyrics.`,
971
+ context: { identifier: this.options.identifier },
972
+ });
973
+ }
891
974
  if (!this.info.plugins.some((plugin) => plugin.name === "java-lyrics-plugin")) {
892
- throw new RangeError(`there is no java-lyrics-plugin available in the lavalink node: ${this.options.identifier}`);
975
+ throw new MagmastreamError_1.MagmaStreamError({
976
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
977
+ message: `The plugin "java-lyrics-plugin" must be present in the lavalink node to unsubscribe.`,
978
+ context: { identifier: this.options.identifier },
979
+ });
980
+ }
981
+ try {
982
+ return await this.rest.delete(`/v4/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe`);
983
+ }
984
+ catch (err) {
985
+ throw err instanceof MagmastreamError_1.MagmaStreamError
986
+ ? err
987
+ : new MagmastreamError_1.MagmaStreamError({
988
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
989
+ message: "Failed to unsubscribe from lyrics session.",
990
+ cause: err instanceof Error ? err : undefined,
991
+ context: { identifier: this.options.identifier, guildId },
992
+ });
893
993
  }
894
- return await this.rest.delete(`/v4/sessions/${this.sessionId}/players/${guildId}/lyrics/subscribe`);
895
994
  }
896
995
  /**
897
996
  * Handles the event when a track becomes stuck during playback.
@@ -1015,9 +1114,26 @@ class Node {
1015
1114
  * @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
1016
1115
  */
1017
1116
  async getSponsorBlock(player) {
1018
- if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin"))
1019
- throw new RangeError(`there is no sponsorblock-plugin available in the lavalink node: ${this.options.identifier}`);
1020
- return (await this.rest.get(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`));
1117
+ if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin")) {
1118
+ throw new MagmastreamError_1.MagmaStreamError({
1119
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
1120
+ message: `The plugin "sponsorblock-plugin" must be present in the lavalink node to fetch SponsorBlock data.`,
1121
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1122
+ });
1123
+ }
1124
+ try {
1125
+ return (await this.rest.get(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`));
1126
+ }
1127
+ catch (err) {
1128
+ throw err instanceof MagmastreamError_1.MagmaStreamError
1129
+ ? err
1130
+ : new MagmastreamError_1.MagmaStreamError({
1131
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1132
+ message: "Failed to fetch SponsorBlock segments.",
1133
+ cause: err instanceof Error ? err : undefined,
1134
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1135
+ });
1136
+ }
1021
1137
  }
1022
1138
  /**
1023
1139
  * Sets the sponsorblock segments for a player.
@@ -1034,14 +1150,40 @@ class Node {
1034
1150
  * ```
1035
1151
  */
1036
1152
  async setSponsorBlock(player, segments = [Enums_1.SponsorBlockSegment.Sponsor, Enums_1.SponsorBlockSegment.SelfPromo]) {
1037
- if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin"))
1038
- throw new RangeError(`there is no sponsorblock-plugin available in the lavalink node: ${this.options.identifier}`);
1039
- if (!segments.length)
1040
- throw new RangeError("No Segments provided. Did you mean to use 'deleteSponsorBlock'?");
1041
- if (segments.some((v) => !validSponsorBlocks.includes(v.toLowerCase())))
1042
- throw new SyntaxError(`You provided a sponsorblock which isn't valid, valid ones are: ${validSponsorBlocks.map((v) => `'${v}'`).join(", ")}`);
1043
- await this.rest.put(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, Utils_1.JSONUtils.safe(segments.map((v) => v.toLowerCase()), 2));
1044
- return;
1153
+ if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin")) {
1154
+ throw new MagmastreamError_1.MagmaStreamError({
1155
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
1156
+ message: `The plugin "sponsorblock-plugin" must be present in the lavalink node to set SponsorBlock segments.`,
1157
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1158
+ });
1159
+ }
1160
+ if (!segments.length) {
1161
+ throw new MagmastreamError_1.MagmaStreamError({
1162
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1163
+ message: "No segments provided. Did you mean to use 'deleteSponsorBlock'?",
1164
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1165
+ });
1166
+ }
1167
+ if (segments.some((v) => !validSponsorBlocks.includes(v.toLowerCase()))) {
1168
+ throw new MagmastreamError_1.MagmaStreamError({
1169
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1170
+ message: `Invalid SponsorBlock segments provided. Valid ones are: ${validSponsorBlocks.map((v) => `'${v}'`).join(", ")}`,
1171
+ context: { identifier: this.options.identifier, guildId: player.guildId, invalidSegments: segments },
1172
+ });
1173
+ }
1174
+ try {
1175
+ await this.rest.put(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`, Utils_1.JSONUtils.safe(segments.map((v) => v.toLowerCase()), 2));
1176
+ }
1177
+ catch (err) {
1178
+ throw err instanceof MagmastreamError_1.MagmaStreamError
1179
+ ? err
1180
+ : new MagmastreamError_1.MagmaStreamError({
1181
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1182
+ message: "Failed to set SponsorBlock segments.",
1183
+ cause: err instanceof Error ? err : undefined,
1184
+ context: { identifier: this.options.identifier, guildId: player.guildId, segments },
1185
+ });
1186
+ }
1045
1187
  }
1046
1188
  /**
1047
1189
  * Deletes the sponsorblock segments for a player.
@@ -1050,10 +1192,26 @@ class Node {
1050
1192
  * @throws {RangeError} If the sponsorblock-plugin is not available in the Lavalink node.
1051
1193
  */
1052
1194
  async deleteSponsorBlock(player) {
1053
- if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin"))
1054
- throw new RangeError(`there is no sponsorblock-plugin available in the lavalink node: ${this.options.identifier}`);
1055
- await this.rest.delete(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`);
1056
- return;
1195
+ if (!this.info.plugins.some((plugin) => plugin.name === "sponsorblock-plugin")) {
1196
+ throw new MagmastreamError_1.MagmaStreamError({
1197
+ code: Enums_1.MagmaStreamErrorCode.NODE_PLUGIN_ERROR,
1198
+ message: `The plugin "sponsorblock-plugin" must be present in the lavalink node to delete SponsorBlock segments.`,
1199
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1200
+ });
1201
+ }
1202
+ try {
1203
+ await this.rest.delete(`/v4/sessions/${this.sessionId}/players/${player.guildId}/sponsorblock/categories`);
1204
+ }
1205
+ catch (err) {
1206
+ throw err instanceof MagmastreamError_1.MagmaStreamError
1207
+ ? err
1208
+ : new MagmastreamError_1.MagmaStreamError({
1209
+ code: Enums_1.MagmaStreamErrorCode.NODE_PROTOCOL_ERROR,
1210
+ message: "Failed to delete SponsorBlock segments.",
1211
+ cause: err instanceof Error ? err : undefined,
1212
+ context: { identifier: this.options.identifier, guildId: player.guildId },
1213
+ });
1214
+ }
1057
1215
  }
1058
1216
  /**
1059
1217
  * Creates a README.md or README.txt file in the magmastream directory