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.
package/dist/index.d.ts CHANGED
@@ -275,6 +275,53 @@ declare enum AvailableFilters {
275
275
  Vaporwave = "vaporwave",
276
276
  Vibrato = "vibrato"
277
277
  }
278
+ /**
279
+ * MagmaStream Error Codes Enum
280
+ */
281
+ declare enum MagmaStreamErrorCode {
282
+ GENERAL_UNKNOWN = "MS_GENERAL_UNKNOWN",
283
+ GENERAL_TIMEOUT = "MS_GENERAL_TIMEOUT",
284
+ GENERAL_INVALID_MANAGER = "MS_GENERAL_INVALID_MANAGER",
285
+ MANAGER_INIT_FAILED = "MS_MANAGER_INIT_FAILED",
286
+ MANAGER_INVALID_CONFIG = "MS_MANAGER_INVALID_CONFIG",
287
+ MANAGER_SHUTDOWN_FAILED = "MS_MANAGER_SHUTDOWN_FAILED",
288
+ MANAGER_NO_NODES = "MS_MANAGER_NO_NODES",
289
+ MANAGER_NODE_NOT_FOUND = "MS_MANAGER_NODE_NOT_FOUND",
290
+ MANAGER_SEARCH_FAILED = "MS_MANAGER_SEARCH_FAILED",
291
+ MANAGER_CLEANUP_INACTIVE_PLAYERS_FAILED = "MS_MANAGER_CLEANUP_INACTIVE_PLAYERS_FAILED",
292
+ NODE_INVALID_CONFIG = "MS_NODE_INVALID_CONFIG",
293
+ NODE_CONNECT_FAILED = "MS_NODE_CONNECT_FAILED",
294
+ NODE_RECONNECT_FAILED = "MS_NODE_RECONNECT_FAILED",
295
+ NODE_DISCONNECTED = "MS_NODE_DISCONNECTED",
296
+ NODE_PROTOCOL_ERROR = "MS_NODE_PROTOCOL_ERROR",
297
+ NODE_SESSION_IDS_LOAD_FAILED = "MS_NODE_SESSION_IDS_LOAD_FAILED",
298
+ NODE_SESSION_IDS_UPDATE_FAILED = "MS_NODE_SESSION_IDS_UPDATE_FAILED",
299
+ NODE_PLUGIN_ERROR = "MS_NODE_PLUGIN_ERROR",
300
+ PLAYER_INVALID_CONFIG = "MS_PLAYER_INVALID_CONFIG",
301
+ PLAYER_STATE_INVALID = "MS_PLAYER_STATE_INVALID",
302
+ PLAYER_QUEUE_EMPTY = "MS_PLAYER_QUEUE_EMPTY",
303
+ PLAYER_PREVIOUS_EMPTY = "MS_PLAYER_PREVIOUS_EMPTY",
304
+ PLAYER_INVALID_NOW_PLAYING_MESSAGE = "MS_PLAYER_INVALID_NOW_PLAYING_MESSAGE",
305
+ PLAYER_INVALID_AUTOPLAY = "MS_PLAYER_INVALID_AUTOPLAY",
306
+ PLAYER_INVALID_VOLUME = "MS_PLAYER_INVALID_VOLUME",
307
+ PLAYER_INVALID_REPEAT = "MS_PLAYER_INVALID_REPEAT",
308
+ PLAYER_INVALID_PAUSE = "MS_PLAYER_INVALID_PAUSE",
309
+ PLAYER_INVALID_SEEK = "MS_PLAYER_INVALID_SEEK",
310
+ PLAYER_MOVE_FAILED = "MS_PLAYER_MOVE_FAILED",
311
+ PLAYER_VOICE_RECEIVER_ERROR = "MS_PLAYER_VOICE_RECEIVER_ERROR",
312
+ QUEUE_REDIS_ERROR = "MS_QUEUE_REDIS_ERROR",
313
+ QUEUE_JSON_ERROR = "MS_QUEUE_JSON_ERROR",
314
+ QUEUE_MEMORY_ERROR = "MS_QUEUE_MEMORY_ERROR",
315
+ FILTER_APPLY_FAILED = "MS_FILTER_APPLY_FAILED",
316
+ REST_REQUEST_FAILED = "MS_REST_REQUEST_FAILED",
317
+ REST_UNAUTHORIZED = "MS_REST_UNAUTHORIZED",
318
+ UTILS_TRACK_PARTIAL_INVALID = "MS_UTILS_TRACK_PARTIAL_INVALID",
319
+ UTILS_TRACK_BUILD_FAILED = "MS_UTILS_TRACK_BUILD_FAILED",
320
+ UTILS_AUTOPLAY_BUILD_FAILED = "MS_UTILS_AUTOPLAY_BUILD_FAILED",
321
+ PLUGIN_LOAD_FAILED = "MS_PLUGIN_LOAD_FAILED",
322
+ PLUGIN_RUNTIME_ERROR = "MS_PLUGIN_RUNTIME_ERROR"
323
+ }
324
+ declare const MagmaStreamErrorNumbers: Record<MagmaStreamErrorCode, number>;
278
325
 
279
326
  /**
280
327
  * The player's queue, the `current` property is the currently playing track, think of the rest as the up-coming tracks.
@@ -2262,7 +2309,6 @@ declare class Player {
2262
2309
  * Retrieves the current lyrics for the playing track.
2263
2310
  * @param skipTrackSource - Indicates whether to skip the track source when fetching lyrics.
2264
2311
  * @returns {Promise<Lyrics>} - The lyrics of the current track.
2265
- * @throws {RangeError} - If the 'lavalyrics-plugin' is not available on the Lavalink node.
2266
2312
  */
2267
2313
  getCurrentLyrics(skipTrackSource?: boolean): Promise<Lyrics>;
2268
2314
  /**
@@ -2336,10 +2382,10 @@ declare class Rest {
2336
2382
  */
2337
2383
  setSessionId(sessionId: string): string;
2338
2384
  /**
2339
- * Retrieves all the players that are currently running on the node.
2385
+ * Retrieves one the player that is currently running on the node.
2340
2386
  * @returns {Promise<unknown>} Returns the result of the GET request.
2341
2387
  */
2342
- getAllPlayers(): Promise<unknown>;
2388
+ getPlayer(guildId: string): Promise<LavaPlayer>;
2343
2389
  /**
2344
2390
  * Sends a PATCH request to update player related data.
2345
2391
  * @param {RestPlayOptions} options The options to update the player with.
@@ -3525,6 +3571,19 @@ declare abstract class JSONUtils {
3525
3571
  static serializeTrack(track: Track): string;
3526
3572
  }
3527
3573
 
3574
+ interface MagmaStreamErrorOptions<T = unknown> {
3575
+ code: MagmaStreamErrorCode;
3576
+ message?: string;
3577
+ cause?: Error;
3578
+ context?: T;
3579
+ }
3580
+ declare class MagmaStreamError<T = unknown> extends Error {
3581
+ readonly code: MagmaStreamErrorCode;
3582
+ readonly number: number;
3583
+ readonly context?: T;
3584
+ constructor({ code, message, cause, context }: MagmaStreamErrorOptions<T>);
3585
+ }
3586
+
3528
3587
  /**
3529
3588
  * Discord.js wrapper for Magmastream.
3530
3589
  */
@@ -3597,5 +3656,5 @@ declare class SeyfertManager extends Manager {
3597
3656
  resolveUser(user: PortableUser | string): Promise<User$3 | PortableUser>;
3598
3657
  }
3599
3658
 
3600
- export { AutoPlayPlatform, AutoPlayUtils, AvailableFilters, DetritusManager, DiscordJSManager, ErisManager, Filters, JSONUtils, JsonQueue, LoadTypes, Manager, ManagerEventTypes, MemoryQueue, Node, OceanicManager, Player, PlayerStateEventTypes, PlayerUtils, Plugin, RedisQueue, Rest, SearchPlatform, SeverityTypes, SeyfertManager, SponsorBlockSegment, StateStorageType, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
3659
+ export { AutoPlayPlatform, AutoPlayUtils, AvailableFilters, DetritusManager, DiscordJSManager, ErisManager, Filters, JSONUtils, JsonQueue, LoadTypes, MagmaStreamError, MagmaStreamErrorCode, MagmaStreamErrorNumbers, Manager, ManagerEventTypes, MemoryQueue, Node, OceanicManager, Player, PlayerStateEventTypes, PlayerUtils, Plugin, RedisQueue, Rest, SearchPlatform, SeverityTypes, SeyfertManager, SponsorBlockSegment, StateStorageType, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
3601
3660
  export type { AlbumSearchResult, ArtistSearchResult, CPUStats, DiscordPacket, DistortionOptions, EndSpeakingEventVoiceReceiver, EndSpeakingEventVoiceReceiverData, EqualizerBand, ErrorOrEmptySearchResult, Exception, Extendable, FrameStats, IQueue, JsonConfig, KaraokeOptions, LavaPlayer, LavalinkInfo, LavalinkResponse, LoadType, Lyrics, LyricsEvent, LyricsEventType, LyricsFoundEvent, LyricsLine, LyricsLineEvent, LyricsNotFoundEvent, ManagerEvents, ManagerInitOptions, ManagerOptions, MemoryStats, NodeLinkGetLyrics, NodeLinkGetLyricsEmpty, NodeLinkGetLyricsError, NodeLinkGetLyricsMultiple, NodeLinkGetLyricsSingle, NodeMessage, NodeOptions, NodeStats, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerStateUpdateEvent, PlayerUpdateVoiceState, PlaylistData, PlaylistInfoData, PlaylistRawData, PlaylistSearchResult, PodcastSearchResult, PortableUser, RedisConfig, RestPlayOptions, ReverbOptions, RotationOptions, SearchQuery, SearchResult, SearchSearchResult, Severity, ShortSearchResult, ShowSearchResult, Sizes, SponsorBlockChapterStarted, SponsorBlockChaptersLoaded, SponsorBlockSegmentEventType, SponsorBlockSegmentEvents, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, StartSpeakingEventVoiceReceiver, StartSpeakingEventVoiceReceiverData, StateStorageOptions, StationSearchResult, TimescaleOptions, Track, TrackData, TrackDataInfo, TrackEndEvent, TrackEndReason, TrackExceptionEvent, TrackPluginInfo, TrackSearchResult, TrackSourceName, TrackStartEvent, TrackStuckEvent, UseNodeOption, VibratoOptions, VoicePacket, VoiceReceiverEvent, VoiceServer, VoiceServerUpdate, VoiceState, WebSocketClosedEvent };
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ tslib_1.__exportStar(require("./structures/Plugin"), exports);
9
9
  tslib_1.__exportStar(require("./statestorage/MemoryQueue"), exports);
10
10
  tslib_1.__exportStar(require("./structures/Rest"), exports);
11
11
  tslib_1.__exportStar(require("./structures/Utils"), exports);
12
+ tslib_1.__exportStar(require("./structures/MagmastreamError"), exports);
12
13
  // wrappers
13
14
  tslib_1.__exportStar(require("./wrappers/discord.js"), exports);
14
15
  tslib_1.__exportStar(require("./wrappers/eris"), exports);
@@ -6,6 +6,7 @@ const Enums_1 = require("../structures/Enums");
6
6
  const path_1 = tslib_1.__importDefault(require("path"));
7
7
  const fs_1 = require("fs");
8
8
  const Utils_1 = require("../structures/Utils");
9
+ const MagmastreamError_1 = require("../structures/MagmastreamError");
9
10
  /**
10
11
  * The player's queue, the `current` property is the currently playing track, think of the rest as the up-coming tracks.
11
12
  */
@@ -32,82 +33,106 @@ class JsonQueue {
32
33
  * @param [offset=null] The position to add the track(s) at. If not provided, the track(s) will be added at the end of the queue.
33
34
  */
34
35
  async add(track, offset) {
35
- const isArray = Array.isArray(track);
36
- const inputTracks = isArray ? track : [track];
37
- const tracks = [...inputTracks];
38
- const queue = await this.getQueue();
39
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
40
- // Set first track as current if none is active
41
- if (!(await this.getCurrent())) {
42
- const current = tracks.shift();
43
- if (current) {
44
- await this.setCurrent(current);
36
+ try {
37
+ const isArray = Array.isArray(track);
38
+ const inputTracks = isArray ? track : [track];
39
+ const tracks = [...inputTracks];
40
+ const queue = await this.getQueue();
41
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
42
+ // Set first track as current if none is active
43
+ if (!(await this.getCurrent())) {
44
+ const current = tracks.shift();
45
+ if (current) {
46
+ await this.setCurrent(current);
47
+ }
45
48
  }
46
- }
47
- if (typeof offset === "number" && !isNaN(offset)) {
48
- queue.splice(offset, 0, ...tracks);
49
- }
50
- else {
51
- queue.push(...tracks);
52
- }
53
- await this.setQueue(queue);
54
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Added ${tracks.length} track(s) to queue`);
55
- if (this.manager.players.has(this.guildId) && this.manager.players.get(this.guildId).isAutoplay) {
56
- if (!isArray) {
57
- const AutoplayUser = (await this.manager.players.get(this.guildId).get("Internal_AutoplayUser"));
58
- if (AutoplayUser && AutoplayUser.id === track.requester.id) {
59
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
60
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
61
- details: {
62
- type: "queue",
63
- action: "autoPlayAdd",
64
- tracks: [track],
65
- },
66
- });
67
- return;
49
+ if (typeof offset === "number" && !isNaN(offset)) {
50
+ queue.splice(offset, 0, ...tracks);
51
+ }
52
+ else {
53
+ queue.push(...tracks);
54
+ }
55
+ await this.setQueue(queue);
56
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Added ${tracks.length} track(s) to queue`);
57
+ if (this.manager.players.has(this.guildId) && this.manager.players.get(this.guildId).isAutoplay) {
58
+ if (!isArray) {
59
+ const AutoplayUser = (await this.manager.players.get(this.guildId).get("Internal_AutoplayUser"));
60
+ if (AutoplayUser && AutoplayUser.id === track.requester.id) {
61
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
62
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
63
+ details: {
64
+ type: "queue",
65
+ action: "autoPlayAdd",
66
+ tracks: [track],
67
+ },
68
+ });
69
+ return;
70
+ }
68
71
  }
69
72
  }
73
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
74
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
75
+ details: {
76
+ type: "queue",
77
+ action: "add",
78
+ tracks,
79
+ },
80
+ });
81
+ }
82
+ catch (err) {
83
+ throw new MagmastreamError_1.MagmaStreamError({
84
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
85
+ message: `Failed to add tracks to JSON queue for guild ${this.guildId}: ${err.message}`,
86
+ });
70
87
  }
71
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
72
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
73
- details: {
74
- type: "queue",
75
- action: "add",
76
- tracks,
77
- },
78
- });
79
88
  }
80
89
  /**
81
90
  * @param track The track to add.
82
91
  */
83
92
  async addPrevious(track) {
84
- const max = this.manager.options.maxPreviousTracks;
85
- const tracks = Array.isArray(track) ? track : [track];
86
- if (!tracks.length)
87
- return;
88
- const current = await this.getPrevious();
89
- const newTracks = tracks.filter((t) => !current.some((p) => p.identifier === t.identifier));
90
- if (!newTracks.length)
91
- return;
92
- const updated = [...newTracks.reverse(), ...current];
93
- const trimmed = updated.slice(0, max);
94
- await this.writeJSON(this.previousPath, trimmed);
93
+ try {
94
+ const max = this.manager.options.maxPreviousTracks;
95
+ const tracks = Array.isArray(track) ? track : [track];
96
+ if (!tracks.length)
97
+ return;
98
+ const current = await this.getPrevious();
99
+ const newTracks = tracks.filter((t) => !current.some((p) => p.identifier === t.identifier));
100
+ if (!newTracks.length)
101
+ return;
102
+ const updated = [...current, ...newTracks];
103
+ const trimmed = updated.slice(-max);
104
+ await this.writeJSON(this.previousPath, trimmed);
105
+ }
106
+ catch (err) {
107
+ throw new MagmastreamError_1.MagmaStreamError({
108
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
109
+ message: `Failed to add tracks to JSON queue for guild ${this.guildId}: ${err.message}`,
110
+ });
111
+ }
95
112
  }
96
113
  /**
97
114
  * Clears the queue.
98
115
  */
99
116
  async clear() {
100
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
101
- await this.deleteFile(this.queuePath);
102
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
103
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
104
- details: {
105
- type: "queue",
106
- action: "clear",
107
- tracks: [],
108
- },
109
- });
110
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Cleared the queue for: ${this.guildId}`);
117
+ try {
118
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
119
+ await this.deleteFile(this.queuePath);
120
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
121
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
122
+ details: {
123
+ type: "queue",
124
+ action: "clear",
125
+ tracks: [],
126
+ },
127
+ });
128
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Cleared the queue for: ${this.guildId}`);
129
+ }
130
+ catch (err) {
131
+ throw new MagmastreamError_1.MagmaStreamError({
132
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
133
+ message: `Failed to clear JSON queue for guild ${this.guildId}: ${err.message}`,
134
+ });
135
+ }
111
136
  }
112
137
  /**
113
138
  * Clears the previous tracks.
@@ -119,28 +144,52 @@ class JsonQueue {
119
144
  * Removes the first track from the queue.
120
145
  */
121
146
  async dequeue() {
122
- const queue = await this.getQueue();
123
- const track = queue.shift();
124
- await this.setQueue(queue);
125
- return track;
147
+ try {
148
+ const queue = await this.getQueue();
149
+ const track = queue.shift();
150
+ await this.setQueue(queue);
151
+ return track;
152
+ }
153
+ catch (err) {
154
+ throw new MagmastreamError_1.MagmaStreamError({
155
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
156
+ message: `Failed to dequeue track for guild ${this.guildId}: ${err.message}`,
157
+ });
158
+ }
126
159
  }
127
160
  /**
128
161
  * @returns The total duration of the queue.
129
162
  */
130
163
  async duration() {
131
- const queue = await this.getQueue();
132
- const current = await this.getCurrent();
133
- const currentDuration = current?.duration || 0;
134
- const total = queue.reduce((acc, track) => acc + (track.duration || 0), currentDuration);
135
- return total;
164
+ try {
165
+ const queue = await this.getQueue();
166
+ const current = await this.getCurrent();
167
+ const currentDuration = current?.duration || 0;
168
+ const total = queue.reduce((acc, track) => acc + (track.duration || 0), currentDuration);
169
+ return total;
170
+ }
171
+ catch (err) {
172
+ throw new MagmastreamError_1.MagmaStreamError({
173
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
174
+ message: `Failed to get duration for guild ${this.guildId}: ${err.message}`,
175
+ });
176
+ }
136
177
  }
137
178
  /**
138
179
  * Adds a track to the front of the queue.
139
180
  */
140
181
  async enqueueFront(track) {
141
- const tracks = Array.isArray(track) ? track : [track];
142
- const queue = await this.getQueue();
143
- await this.setQueue([...tracks.reverse(), ...queue]);
182
+ try {
183
+ const tracks = Array.isArray(track) ? track : [track];
184
+ const queue = await this.getQueue();
185
+ await this.setQueue([...tracks.reverse(), ...queue]);
186
+ }
187
+ catch (err) {
188
+ throw new MagmastreamError_1.MagmaStreamError({
189
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
190
+ message: `Failed to enqueue front track for guild ${this.guildId}: ${err.message}`,
191
+ });
192
+ }
144
193
  }
145
194
  /**
146
195
  * Tests whether all elements in the queue pass the test implemented by the provided function.
@@ -211,76 +260,100 @@ class JsonQueue {
211
260
  * @returns The newest track.
212
261
  */
213
262
  async popPrevious() {
214
- const current = await this.getPrevious();
215
- if (!current.length)
216
- return null;
217
- const popped = current.shift();
218
- await this.writeJSON(this.previousPath, current);
219
- return popped;
263
+ try {
264
+ const current = await this.getPrevious();
265
+ if (!current.length)
266
+ return null;
267
+ const popped = current.pop();
268
+ await this.writeJSON(this.previousPath, current);
269
+ return popped;
270
+ }
271
+ catch (err) {
272
+ throw new MagmastreamError_1.MagmaStreamError({
273
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
274
+ message: `Failed to pop previous track for guild ${this.guildId}: ${err.message}`,
275
+ });
276
+ }
220
277
  }
221
278
  async remove(startOrPos = 0, end) {
222
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
223
- const queue = await this.getQueue();
224
- let removed = [];
225
- if (typeof end === "number") {
226
- if (startOrPos >= end || startOrPos >= queue.length)
227
- throw new RangeError("Invalid range.");
228
- removed = queue.splice(startOrPos, end - startOrPos);
279
+ try {
280
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
281
+ const queue = await this.getQueue();
282
+ let removed = [];
283
+ if (typeof end === "number") {
284
+ if (startOrPos >= end || startOrPos >= queue.length)
285
+ throw new RangeError("Invalid range.");
286
+ removed = queue.splice(startOrPos, end - startOrPos);
287
+ }
288
+ else {
289
+ removed = queue.splice(startOrPos, 1);
290
+ }
291
+ await this.setQueue(queue);
292
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Removed ${removed.length} track(s) from position ${startOrPos}${end ? ` to ${end}` : ""}`);
293
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
294
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
295
+ details: {
296
+ type: "queue",
297
+ action: "remove",
298
+ tracks: removed,
299
+ },
300
+ });
301
+ return removed;
229
302
  }
230
- else {
231
- removed = queue.splice(startOrPos, 1);
303
+ catch (err) {
304
+ throw new MagmastreamError_1.MagmaStreamError({
305
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
306
+ message: `Failed to remove track for guild ${this.guildId}: ${err.message}`,
307
+ });
232
308
  }
233
- await this.setQueue(queue);
234
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Removed ${removed.length} track(s) from position ${startOrPos}${end ? ` to ${end}` : ""}`);
235
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
236
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
237
- details: {
238
- type: "queue",
239
- action: "remove",
240
- tracks: removed,
241
- },
242
- });
243
- return removed;
244
309
  }
245
310
  /**
246
311
  * Shuffles the queue by round-robin.
247
312
  */
248
313
  async roundRobinShuffle() {
249
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
250
- const queue = await this.getQueue();
251
- const userMap = new Map();
252
- for (const track of queue) {
253
- const userId = track.requester.id;
254
- if (!userMap.has(userId))
255
- userMap.set(userId, []);
256
- userMap.get(userId).push(track);
257
- }
258
- // Shuffle each user's tracks
259
- for (const tracks of userMap.values()) {
260
- for (let i = tracks.length - 1; i > 0; i--) {
261
- const j = Math.floor(Math.random() * (i + 1));
262
- [tracks[i], tracks[j]] = [tracks[j], tracks[i]];
314
+ try {
315
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
316
+ const queue = await this.getQueue();
317
+ const userMap = new Map();
318
+ for (const track of queue) {
319
+ const userId = track.requester.id;
320
+ if (!userMap.has(userId))
321
+ userMap.set(userId, []);
322
+ userMap.get(userId).push(track);
263
323
  }
264
- }
265
- const users = [...userMap.keys()];
266
- const queues = users.map((id) => userMap.get(id));
267
- const shuffledQueue = [];
268
- while (queues.some((q) => q.length > 0)) {
269
- for (const q of queues) {
270
- const track = q.shift();
271
- if (track)
272
- shuffledQueue.push(track);
324
+ // Shuffle each user's tracks
325
+ for (const tracks of userMap.values()) {
326
+ for (let i = tracks.length - 1; i > 0; i--) {
327
+ const j = Math.floor(Math.random() * (i + 1));
328
+ [tracks[i], tracks[j]] = [tracks[j], tracks[i]];
329
+ }
330
+ }
331
+ const users = [...userMap.keys()];
332
+ const queues = users.map((id) => userMap.get(id));
333
+ const shuffledQueue = [];
334
+ while (queues.some((q) => q.length > 0)) {
335
+ for (const q of queues) {
336
+ const track = q.shift();
337
+ if (track)
338
+ shuffledQueue.push(track);
339
+ }
273
340
  }
341
+ await this.setQueue(shuffledQueue);
342
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
343
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
344
+ details: {
345
+ type: "queue",
346
+ action: "roundRobin",
347
+ },
348
+ });
349
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] roundRobinShuffled the queue for: ${this.guildId}`);
350
+ }
351
+ catch (err) {
352
+ throw new MagmastreamError_1.MagmaStreamError({
353
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
354
+ message: `Failed to round robin shuffle queue for guild ${this.guildId}: ${err.message}`,
355
+ });
274
356
  }
275
- await this.setQueue(shuffledQueue);
276
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
277
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
278
- details: {
279
- type: "queue",
280
- action: "roundRobin",
281
- },
282
- });
283
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] roundRobinShuffled the queue for: ${this.guildId}`);
284
357
  }
285
358
  /**
286
359
  * @param track The track to set.
@@ -306,21 +379,29 @@ class JsonQueue {
306
379
  * Shuffles the queue.
307
380
  */
308
381
  async shuffle() {
309
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
310
- const queue = await this.getQueue();
311
- for (let i = queue.length - 1; i > 0; i--) {
312
- const j = Math.floor(Math.random() * (i + 1));
313
- [queue[i], queue[j]] = [queue[j], queue[i]];
382
+ try {
383
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
384
+ const queue = await this.getQueue();
385
+ for (let i = queue.length - 1; i > 0; i--) {
386
+ const j = Math.floor(Math.random() * (i + 1));
387
+ [queue[i], queue[j]] = [queue[j], queue[i]];
388
+ }
389
+ await this.setQueue(queue);
390
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
391
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
392
+ details: {
393
+ type: "queue",
394
+ action: "shuffle",
395
+ },
396
+ });
397
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Shuffled the queue for: ${this.guildId}`);
398
+ }
399
+ catch (err) {
400
+ throw new MagmastreamError_1.MagmaStreamError({
401
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
402
+ message: `Failed to shuffle queue for guild ${this.guildId}: ${err.message}`,
403
+ });
314
404
  }
315
- await this.setQueue(queue);
316
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
317
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
318
- details: {
319
- type: "queue",
320
- action: "shuffle",
321
- },
322
- });
323
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Shuffled the queue for: ${this.guildId}`);
324
405
  }
325
406
  /**
326
407
  * @returns The size of the queue.
@@ -347,32 +428,40 @@ class JsonQueue {
347
428
  * Shuffles the queue by user.
348
429
  */
349
430
  async userBlockShuffle() {
350
- const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
351
- const queue = await this.getQueue();
352
- const userMap = new Map();
353
- for (const track of queue) {
354
- const userId = track.requester.id;
355
- if (!userMap.has(userId))
356
- userMap.set(userId, []);
357
- userMap.get(userId).push(track);
358
- }
359
- const shuffledQueue = [];
360
- while (shuffledQueue.length < queue.length) {
361
- for (const [, tracks] of userMap) {
362
- const track = tracks.shift();
363
- if (track)
364
- shuffledQueue.push(track);
431
+ try {
432
+ const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
433
+ const queue = await this.getQueue();
434
+ const userMap = new Map();
435
+ for (const track of queue) {
436
+ const userId = track.requester.id;
437
+ if (!userMap.has(userId))
438
+ userMap.set(userId, []);
439
+ userMap.get(userId).push(track);
365
440
  }
441
+ const shuffledQueue = [];
442
+ while (shuffledQueue.length < queue.length) {
443
+ for (const [, tracks] of userMap) {
444
+ const track = tracks.shift();
445
+ if (track)
446
+ shuffledQueue.push(track);
447
+ }
448
+ }
449
+ await this.setQueue(shuffledQueue);
450
+ this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
451
+ changeType: Enums_1.PlayerStateEventTypes.QueueChange,
452
+ details: {
453
+ type: "queue",
454
+ action: "userBlock",
455
+ },
456
+ });
457
+ this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] userBlockShuffled the queue for: ${this.guildId}`);
458
+ }
459
+ catch (err) {
460
+ throw new MagmastreamError_1.MagmaStreamError({
461
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
462
+ message: `Failed to user block shuffle queue for guild ${this.guildId}: ${err.message}`,
463
+ });
366
464
  }
367
- await this.setQueue(shuffledQueue);
368
- this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
369
- changeType: Enums_1.PlayerStateEventTypes.QueueChange,
370
- details: {
371
- type: "queue",
372
- action: "userBlock",
373
- },
374
- });
375
- this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] userBlockShuffled the queue for: ${this.guildId}`);
376
465
  }
377
466
  // #endregion Public
378
467
  // #region Private
@@ -391,6 +480,10 @@ class JsonQueue {
391
480
  }
392
481
  catch {
393
482
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[JSONQUEUE] Failed to delete file: ${filePath}`);
483
+ throw new MagmastreamError_1.MagmaStreamError({
484
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
485
+ message: `Failed to delete file: ${filePath}`,
486
+ });
394
487
  }
395
488
  }
396
489
  /**
@@ -427,7 +520,16 @@ class JsonQueue {
427
520
  const raw = await fs_1.promises.readFile(filePath, "utf-8");
428
521
  return JSON.parse(raw);
429
522
  }
430
- catch {
523
+ catch (err) {
524
+ const error = err instanceof MagmastreamError_1.MagmaStreamError
525
+ ? err
526
+ : new MagmastreamError_1.MagmaStreamError({
527
+ code: Enums_1.MagmaStreamErrorCode.QUEUE_JSON_ERROR,
528
+ message: "An unknown error occurred.",
529
+ cause: err,
530
+ context: { stage: "SIGINT" },
531
+ });
532
+ console.error(error);
431
533
  return null;
432
534
  }
433
535
  }