magmastream 2.9.3-dev.3 → 2.9.3-dev.31
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/config/blockedWords.d.ts +1 -0
- package/dist/index.d.ts +19 -3687
- package/dist/index.js +1 -1
- package/dist/statestorage/JsonQueue.d.ts +173 -0
- package/dist/statestorage/JsonQueue.js +32 -4
- package/dist/statestorage/MemoryQueue.d.ts +154 -0
- package/dist/statestorage/MemoryQueue.js +56 -36
- package/dist/statestorage/RedisQueue.d.ts +178 -0
- package/dist/statestorage/RedisQueue.js +29 -7
- package/dist/structures/Enums.d.ts +310 -0
- package/dist/structures/Enums.js +6 -0
- package/dist/structures/Filters.d.ts +352 -0
- package/dist/structures/Filters.js +5 -4
- package/dist/structures/MagmastreamError.d.ts +14 -0
- package/dist/structures/Manager.d.ts +259 -0
- package/dist/structures/Manager.js +296 -555
- package/dist/structures/Node.d.ts +390 -0
- package/dist/structures/Node.js +100 -145
- package/dist/structures/Player.d.ts +347 -0
- package/dist/structures/Player.js +55 -132
- package/dist/structures/Plugin.d.ts +23 -0
- package/dist/structures/Rest.d.ts +93 -0
- package/dist/structures/Rest.js +41 -21
- package/dist/structures/Types.d.ts +1315 -0
- package/dist/structures/Utils.d.ts +169 -0
- package/dist/structures/Utils.js +145 -71
- package/dist/utils/filtersEqualizers.d.ts +16 -0
- package/dist/utils/managerCheck.d.ts +7 -0
- package/dist/utils/nodeCheck.d.ts +7 -0
- package/dist/utils/playerCheck.d.ts +7 -0
- package/dist/wrappers/discord.js.d.ts +15 -0
- package/dist/wrappers/discord.js.js +19 -4
- package/dist/wrappers/discordeno.d.ts +19 -0
- package/dist/wrappers/discordeno.js +77 -0
- package/dist/wrappers/eris.d.ts +15 -0
- package/dist/wrappers/eris.js +20 -3
- package/dist/wrappers/oceanic.d.ts +15 -0
- package/dist/wrappers/oceanic.js +22 -4
- package/dist/wrappers/seyfert.d.ts +37 -0
- package/dist/wrappers/seyfert.js +25 -1
- package/package.json +106 -98
- package/dist/wrappers/detritus.js +0 -52
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import { Filters } from "./Filters";
|
|
2
|
+
import { Manager } from "./Manager";
|
|
3
|
+
import { Node } from "./Node";
|
|
4
|
+
import { AnyMessage, IQueue, Lyrics, PlayerOptions, PlayOptions, SearchQuery, SearchResult, Track, VoiceState } from "./Types";
|
|
5
|
+
import { SponsorBlockSegment, StateTypes } from "./Enums";
|
|
6
|
+
import { WebSocket } from "ws";
|
|
7
|
+
export declare class Player {
|
|
8
|
+
options: PlayerOptions;
|
|
9
|
+
/** The Queue for the Player. */
|
|
10
|
+
queue: IQueue;
|
|
11
|
+
/** The filters applied to the audio. */
|
|
12
|
+
filters: Filters;
|
|
13
|
+
/** Whether the queue repeats the track. */
|
|
14
|
+
trackRepeat: boolean;
|
|
15
|
+
/** Whether the queue repeats the queue. */
|
|
16
|
+
queueRepeat: boolean;
|
|
17
|
+
/**Whether the queue repeats and shuffles after each song. */
|
|
18
|
+
dynamicRepeat: boolean;
|
|
19
|
+
/** The time the player is in the track. */
|
|
20
|
+
position: number;
|
|
21
|
+
/** Whether the player is playing. */
|
|
22
|
+
playing: boolean;
|
|
23
|
+
/** Whether the player is paused. */
|
|
24
|
+
paused: boolean;
|
|
25
|
+
/** The volume for the player */
|
|
26
|
+
volume: number;
|
|
27
|
+
/** The Node for the Player. */
|
|
28
|
+
node: Node;
|
|
29
|
+
/** The guild ID for the player. */
|
|
30
|
+
guildId: string;
|
|
31
|
+
/** The voice channel for the player. */
|
|
32
|
+
voiceChannelId: string | null;
|
|
33
|
+
/** The text channel for the player. */
|
|
34
|
+
textChannelId: string | null;
|
|
35
|
+
/**The now playing message. */
|
|
36
|
+
nowPlayingMessage?: AnyMessage;
|
|
37
|
+
/** The current state of the player. */
|
|
38
|
+
state: StateTypes;
|
|
39
|
+
/** The equalizer bands array. */
|
|
40
|
+
bands: number[];
|
|
41
|
+
/** The voice state object from Discord. */
|
|
42
|
+
voiceState: VoiceState;
|
|
43
|
+
/** The Manager. */
|
|
44
|
+
manager: Manager;
|
|
45
|
+
/** The autoplay state of the player. */
|
|
46
|
+
isAutoplay: boolean;
|
|
47
|
+
/** The number of times to try autoplay before emitting queueEnd. */
|
|
48
|
+
autoplayTries: number;
|
|
49
|
+
/** The cluster ID for the player. */
|
|
50
|
+
clusterId: number;
|
|
51
|
+
private readonly data;
|
|
52
|
+
private dynamicLoopInterval;
|
|
53
|
+
dynamicRepeatIntervalMs: number | null;
|
|
54
|
+
private static _manager;
|
|
55
|
+
/** Should only be used when the node is a NodeLink */
|
|
56
|
+
protected voiceReceiverWsClient: WebSocket | null;
|
|
57
|
+
protected isConnectToVoiceReceiver: boolean;
|
|
58
|
+
protected voiceReceiverReconnectTimeout: NodeJS.Timeout | null;
|
|
59
|
+
protected voiceReceiverAttempt: number;
|
|
60
|
+
protected voiceReceiverReconnectTries: number;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new player, returns one if it already exists.
|
|
63
|
+
* @param options The player options.
|
|
64
|
+
* @see https://docs.magmastream.com/main/introduction/getting-started
|
|
65
|
+
*/
|
|
66
|
+
constructor(options: PlayerOptions);
|
|
67
|
+
/**
|
|
68
|
+
* Initializes the static properties of the Player class.
|
|
69
|
+
* @hidden
|
|
70
|
+
* @param manager The Manager to use.
|
|
71
|
+
*/
|
|
72
|
+
static init(manager: Manager): void;
|
|
73
|
+
/**
|
|
74
|
+
* Set custom data.
|
|
75
|
+
* @param key - The key to set the data for.
|
|
76
|
+
* @param value - The value to set the data to.
|
|
77
|
+
*/
|
|
78
|
+
set(key: string, value: unknown): void;
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves custom data associated with a given key.
|
|
81
|
+
* @template T - The expected type of the data.
|
|
82
|
+
* @param {string} key - The key to retrieve the data for.
|
|
83
|
+
* @returns {T} - The data associated with the key, cast to the specified type.
|
|
84
|
+
*/
|
|
85
|
+
get<T>(key: string): T;
|
|
86
|
+
/**
|
|
87
|
+
* Same as Manager#search() but a shortcut on the player itself.
|
|
88
|
+
* @param query
|
|
89
|
+
* @param requester
|
|
90
|
+
*/
|
|
91
|
+
search<T = unknown>(query: string | SearchQuery, requester?: T): Promise<SearchResult>;
|
|
92
|
+
/**
|
|
93
|
+
* Connects the player to the voice channel.
|
|
94
|
+
* @throws {RangeError} If no voice channel has been set.
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
connect(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Disconnects the player from the voice channel.
|
|
100
|
+
* @returns {this} The player instance.
|
|
101
|
+
*/
|
|
102
|
+
disconnect(): Promise<this>;
|
|
103
|
+
/**
|
|
104
|
+
* Destroys the player and clears the queue.
|
|
105
|
+
* @param {boolean} disconnect - Whether to disconnect the player from the voice channel.
|
|
106
|
+
* @returns {Promise<boolean>} - Whether the player was successfully destroyed.
|
|
107
|
+
* @emits {PlayerDestroy} - Emitted when the player is destroyed.
|
|
108
|
+
* @emits {PlayerStateUpdate} - Emitted when the player state is updated.
|
|
109
|
+
*/
|
|
110
|
+
destroy(disconnect?: boolean): Promise<boolean>;
|
|
111
|
+
/**
|
|
112
|
+
* Sets the player voice channel.
|
|
113
|
+
* @param {string} channel - The new voice channel ID.
|
|
114
|
+
* @returns {this} - The player instance.
|
|
115
|
+
* @throws {TypeError} If the channel parameter is not a string.
|
|
116
|
+
*/
|
|
117
|
+
setVoiceChannelId(channel: string): this;
|
|
118
|
+
/**
|
|
119
|
+
* Sets the player text channel.
|
|
120
|
+
*
|
|
121
|
+
* This method updates the text channel associated with the player. It also
|
|
122
|
+
* emits a player state update event indicating the change in the channel.
|
|
123
|
+
*
|
|
124
|
+
* @param {string} channel - The new text channel ID.
|
|
125
|
+
* @returns {this} - The player instance for method chaining.
|
|
126
|
+
* @throws {TypeError} If the channel parameter is not a string.
|
|
127
|
+
*/
|
|
128
|
+
setTextChannelId(channel: string): this;
|
|
129
|
+
/**
|
|
130
|
+
* Sets the now playing message.
|
|
131
|
+
*
|
|
132
|
+
* @param message - The message of the now playing message.
|
|
133
|
+
* @returns The now playing message.
|
|
134
|
+
*/
|
|
135
|
+
setNowPlayingMessage(message: AnyMessage): AnyMessage;
|
|
136
|
+
/**
|
|
137
|
+
* Plays the next track.
|
|
138
|
+
*
|
|
139
|
+
* If a track is provided, it will be played. Otherwise, the next track in the queue will be played.
|
|
140
|
+
* If the queue is not empty, but the current track has not finished yet, it will be replaced with the provided track.
|
|
141
|
+
*
|
|
142
|
+
* @param {object} [optionsOrTrack] - The track to play or the options to play with.
|
|
143
|
+
* @param {object} [playOptions] - The options to play with.
|
|
144
|
+
*
|
|
145
|
+
* @returns {Promise<void>}
|
|
146
|
+
*/
|
|
147
|
+
play(): Promise<Player>;
|
|
148
|
+
play(track: Track): Promise<Player>;
|
|
149
|
+
play(options: PlayOptions): Promise<Player>;
|
|
150
|
+
play(track: Track, options: PlayOptions): Promise<Player>;
|
|
151
|
+
/**
|
|
152
|
+
* Sets the autoplay-state of the player.
|
|
153
|
+
*
|
|
154
|
+
* Autoplay is a feature that makes the player play a recommended
|
|
155
|
+
* track when the current track ends.
|
|
156
|
+
*
|
|
157
|
+
* @param {boolean} autoplayState - Whether or not autoplay should be enabled.
|
|
158
|
+
* @param {object} AutoplayUser - The user-object that should be used as the bot-user.
|
|
159
|
+
* @param {number} [tries=3] - The number of times the player should try to find a
|
|
160
|
+
* recommended track if the first one doesn't work.
|
|
161
|
+
* @returns {this} - The player instance.
|
|
162
|
+
*/
|
|
163
|
+
setAutoplay<T = unknown>(autoplayState: boolean, AutoplayUser?: T, tries?: number): this;
|
|
164
|
+
/**
|
|
165
|
+
* Gets recommended tracks and returns an array of tracks.
|
|
166
|
+
* @param {Track} track - The track to find recommendations for.
|
|
167
|
+
* @returns {Promise<Track[]>} - Array of recommended tracks.
|
|
168
|
+
*/
|
|
169
|
+
getRecommendedTracks(track: Track): Promise<Track[]>;
|
|
170
|
+
/**
|
|
171
|
+
* Sets the volume of the player.
|
|
172
|
+
* @param {number} volume - The new volume. Must be between 0 and 500 when using filter mode (100 = 100%).
|
|
173
|
+
* @returns {Promise<Player>} - The updated player.
|
|
174
|
+
* @throws {TypeError} If the volume is not a number.
|
|
175
|
+
* @throws {RangeError} If the volume is not between 0 and 500 when using filter mode (100 = 100%).
|
|
176
|
+
* @emits {PlayerStateUpdate} - Emitted when the volume is changed.
|
|
177
|
+
* @example
|
|
178
|
+
* player.setVolume(50);
|
|
179
|
+
*/
|
|
180
|
+
setVolume(volume: number): Promise<this>;
|
|
181
|
+
/**
|
|
182
|
+
* Sets the sponsorblock for the player. This will set the sponsorblock segments for the player to the given segments.
|
|
183
|
+
* @param {SponsorBlockSegment[]} segments - The sponsorblock segments to set. Defaults to `[SponsorBlockSegment.Sponsor, SponsorBlockSegment.SelfPromo]` if not provided.
|
|
184
|
+
* @returns {Promise<void>} The promise is resolved when the operation is complete.
|
|
185
|
+
*/
|
|
186
|
+
setSponsorBlock(segments?: SponsorBlockSegment[]): Promise<void>;
|
|
187
|
+
/**
|
|
188
|
+
* Gets the sponsorblock for the player.
|
|
189
|
+
* @returns {Promise<SponsorBlockSegment[]>} The sponsorblock segments.
|
|
190
|
+
*/
|
|
191
|
+
getSponsorBlock(): Promise<SponsorBlockSegment[]>;
|
|
192
|
+
/**
|
|
193
|
+
* Deletes the sponsorblock for the player. This will remove all sponsorblock segments that have been set for the player.
|
|
194
|
+
* @returns {Promise<void>}
|
|
195
|
+
*/
|
|
196
|
+
deleteSponsorBlock(): Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Sets the track repeat mode.
|
|
199
|
+
* When track repeat is enabled, the current track will replay after it ends.
|
|
200
|
+
* Disables queueRepeat and dynamicRepeat modes if enabled.
|
|
201
|
+
*
|
|
202
|
+
* @param repeat - A boolean indicating whether to enable track repeat.
|
|
203
|
+
* @returns {this} - The player instance.
|
|
204
|
+
* @throws {TypeError} If the repeat parameter is not a boolean.
|
|
205
|
+
*/
|
|
206
|
+
setTrackRepeat(repeat: boolean): this;
|
|
207
|
+
/**
|
|
208
|
+
* Sets the queue repeat.
|
|
209
|
+
* @param repeat Whether to repeat the queue or not
|
|
210
|
+
* @returns {this} - The player instance.
|
|
211
|
+
* @throws {TypeError} If the repeat parameter is not a boolean
|
|
212
|
+
*/
|
|
213
|
+
setQueueRepeat(repeat: boolean): this;
|
|
214
|
+
/**
|
|
215
|
+
* Sets the queue to repeat and shuffles the queue after each song.
|
|
216
|
+
* @param repeat "true" or "false".
|
|
217
|
+
* @param ms After how many milliseconds to trigger dynamic repeat.
|
|
218
|
+
* @returns {this} - The player instance.
|
|
219
|
+
* @throws {TypeError} If the repeat parameter is not a boolean.
|
|
220
|
+
* @throws {RangeError} If the queue size is less than or equal to 1.
|
|
221
|
+
*/
|
|
222
|
+
setDynamicRepeat(repeat: boolean, ms: number): Promise<this>;
|
|
223
|
+
/**
|
|
224
|
+
* Restarts the currently playing track from the beginning.
|
|
225
|
+
* If there is no track playing, it will play the next track in the queue.
|
|
226
|
+
* @returns {Promise<Player>} The current instance of the Player class for method chaining.
|
|
227
|
+
*/
|
|
228
|
+
restart(): Promise<Player>;
|
|
229
|
+
/**
|
|
230
|
+
* Stops the player and optionally removes tracks from the queue.
|
|
231
|
+
* @param {number} [amount] The amount of tracks to remove from the queue. If not provided, removes the current track if it exists.
|
|
232
|
+
* @returns {Promise<this>} - The player instance.
|
|
233
|
+
* @throws {RangeError} If the amount is greater than the queue length.
|
|
234
|
+
*/
|
|
235
|
+
stop(amount?: number): Promise<this>;
|
|
236
|
+
/**
|
|
237
|
+
* Skips the current track.
|
|
238
|
+
* @returns {this} - The player instance.
|
|
239
|
+
* @throws {Error} If there are no tracks in the queue.
|
|
240
|
+
* @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
|
|
241
|
+
*/
|
|
242
|
+
pause(pause: boolean): Promise<this>;
|
|
243
|
+
/**
|
|
244
|
+
* Skips to the previous track in the queue.
|
|
245
|
+
* @returns {this} - The player instance.
|
|
246
|
+
* @throws {Error} If there are no previous tracks in the queue.
|
|
247
|
+
* @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
|
|
248
|
+
*/
|
|
249
|
+
previous(addBackToQueue?: boolean): Promise<this>;
|
|
250
|
+
/**
|
|
251
|
+
* Seeks to a given position in the currently playing track.
|
|
252
|
+
* @param position - The position in milliseconds to seek to.
|
|
253
|
+
* @returns {this} - The player instance.
|
|
254
|
+
* @throws {Error} If the position is invalid.
|
|
255
|
+
* @emits {PlayerStateUpdate} - With {@link PlayerStateEventTypes.TrackChange} as the change type.
|
|
256
|
+
*/
|
|
257
|
+
seek(position: number): Promise<this>;
|
|
258
|
+
/**
|
|
259
|
+
* Returns the current repeat state of the player.
|
|
260
|
+
* @param player The player to get the repeat state from.
|
|
261
|
+
* @returns The repeat state of the player, or null if it is not repeating.
|
|
262
|
+
*/
|
|
263
|
+
private getRepeatState;
|
|
264
|
+
/**
|
|
265
|
+
* Automatically moves the player to a usable node.
|
|
266
|
+
* @returns {Promise<Player | void>} - The player instance or void if not moved.
|
|
267
|
+
*/
|
|
268
|
+
autoMoveNode(): Promise<Player | void>;
|
|
269
|
+
/**
|
|
270
|
+
* Moves the player to another node.
|
|
271
|
+
* @param {string} identifier - The identifier of the node to move to.
|
|
272
|
+
* @returns {Promise<Player>} - The player instance after being moved.
|
|
273
|
+
*/
|
|
274
|
+
moveNode(identifier: string): Promise<Player>;
|
|
275
|
+
/**
|
|
276
|
+
* Retrieves the data associated with the player.
|
|
277
|
+
* @returns {Record<string, unknown>} - The data associated with the player.
|
|
278
|
+
*/
|
|
279
|
+
getData(): Record<string, unknown>;
|
|
280
|
+
/**
|
|
281
|
+
* Retrieves the dynamic loop interval of the player.
|
|
282
|
+
* @returns {NodeJS.Timeout | null} - The dynamic loop interval of the player.
|
|
283
|
+
*/
|
|
284
|
+
getDynamicLoopIntervalPublic(): NodeJS.Timeout | null;
|
|
285
|
+
/**
|
|
286
|
+
* Retrieves the data associated with the player.
|
|
287
|
+
* @returns {Record<string, unknown>} - The data associated with the player.
|
|
288
|
+
*/
|
|
289
|
+
getSerializableData(): Record<string, unknown>;
|
|
290
|
+
/**
|
|
291
|
+
* Retrieves the current lyrics for the playing track.
|
|
292
|
+
* @param skipTrackSource - Indicates whether to skip the track source when fetching lyrics.
|
|
293
|
+
* @returns {Promise<Lyrics>} - The lyrics of the current track.
|
|
294
|
+
*/
|
|
295
|
+
getCurrentLyrics(skipTrackSource?: boolean): Promise<Lyrics>;
|
|
296
|
+
/**
|
|
297
|
+
* Sets up the voice receiver for the player.
|
|
298
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is set up.
|
|
299
|
+
* @throws {Error} - If the node is not a NodeLink.
|
|
300
|
+
*/
|
|
301
|
+
setupVoiceReceiver(): Promise<void>;
|
|
302
|
+
/**
|
|
303
|
+
* Removes the voice receiver for the player.
|
|
304
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is removed.
|
|
305
|
+
* @throws {Error} - If the node is not a NodeLink.
|
|
306
|
+
*/
|
|
307
|
+
removeVoiceReceiver(): Promise<void>;
|
|
308
|
+
/**
|
|
309
|
+
* Closes the voice receiver for the player.
|
|
310
|
+
* @param {number} code - The code to close the voice receiver with.
|
|
311
|
+
* @param {string} reason - The reason to close the voice receiver with.
|
|
312
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is closed.
|
|
313
|
+
*/
|
|
314
|
+
private closeVoiceReceiver;
|
|
315
|
+
/**
|
|
316
|
+
* Reconnects the voice receiver for the player.
|
|
317
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is reconnected.
|
|
318
|
+
*/
|
|
319
|
+
private reconnectVoiceReceiver;
|
|
320
|
+
/**
|
|
321
|
+
* Disconnects the voice receiver for the player.
|
|
322
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is disconnected.
|
|
323
|
+
*/
|
|
324
|
+
private disconnectVoiceReceiver;
|
|
325
|
+
/**
|
|
326
|
+
* Opens the voice receiver for the player.
|
|
327
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is opened.
|
|
328
|
+
*/
|
|
329
|
+
private openVoiceReceiver;
|
|
330
|
+
/**
|
|
331
|
+
* Handles a voice receiver message.
|
|
332
|
+
* @param {string} payload - The payload to handle.
|
|
333
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver message is handled.
|
|
334
|
+
*/
|
|
335
|
+
private onVoiceReceiverMessage;
|
|
336
|
+
/**
|
|
337
|
+
* Handles a voice receiver error.
|
|
338
|
+
* @param {Error} error - The error to handle.
|
|
339
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver error is handled.
|
|
340
|
+
*/
|
|
341
|
+
private onVoiceReceiverError;
|
|
342
|
+
/**
|
|
343
|
+
* Updates the voice state for the player.
|
|
344
|
+
* @returns {Promise<void>} - A promise that resolves when the voice state is updated.
|
|
345
|
+
*/
|
|
346
|
+
updateVoice(): Promise<void>;
|
|
347
|
+
}
|
|
@@ -82,7 +82,7 @@ class Player {
|
|
|
82
82
|
message: "Manager instance is required.",
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
-
this.clusterId = this.manager.options.clusterId
|
|
85
|
+
this.clusterId = this.manager.options.clusterId ?? 0;
|
|
86
86
|
// Check the player options for errors.
|
|
87
87
|
(0, playerCheck_1.default)(options);
|
|
88
88
|
this.options = {
|
|
@@ -260,21 +260,30 @@ class Player {
|
|
|
260
260
|
*/
|
|
261
261
|
async destroy(disconnect = true) {
|
|
262
262
|
this.state = Enums_1.StateTypes.Destroying;
|
|
263
|
+
if (this.dynamicLoopInterval) {
|
|
264
|
+
clearInterval(this.dynamicLoopInterval);
|
|
265
|
+
this.dynamicLoopInterval = null;
|
|
266
|
+
}
|
|
267
|
+
if (this.voiceReceiverReconnectTimeout) {
|
|
268
|
+
clearTimeout(this.voiceReceiverReconnectTimeout);
|
|
269
|
+
this.voiceReceiverReconnectTimeout = null;
|
|
270
|
+
}
|
|
271
|
+
if (this.voiceReceiverWsClient) {
|
|
272
|
+
this.voiceReceiverWsClient.removeAllListeners();
|
|
273
|
+
this.voiceReceiverWsClient.close();
|
|
274
|
+
this.voiceReceiverWsClient = null;
|
|
275
|
+
}
|
|
263
276
|
if (disconnect) {
|
|
264
|
-
await this.disconnect().catch((
|
|
265
|
-
console.warn(`[Player#destroy] Failed to disconnect player ${this.guildId}:`, err);
|
|
266
|
-
});
|
|
277
|
+
await this.disconnect().catch(() => { });
|
|
267
278
|
}
|
|
268
|
-
await this.node.rest.destroyPlayer(this.guildId).catch((
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
await this.queue.clear();
|
|
272
|
-
await this.queue.clearPrevious();
|
|
273
|
-
await this.queue.setCurrent(null);
|
|
279
|
+
await this.node.rest.destroyPlayer(this.guildId).catch(() => { });
|
|
280
|
+
await this.queue.destroy();
|
|
281
|
+
this.nowPlayingMessage = undefined;
|
|
274
282
|
this.manager.emit(Enums_1.ManagerEventTypes.PlayerDestroy, this);
|
|
275
283
|
const deleted = this.manager.players.delete(this.guildId);
|
|
276
|
-
if (this.manager.options.stateStorage.
|
|
284
|
+
if (this.manager.options.stateStorage.deleteDestroyedPlayers) {
|
|
277
285
|
await this.manager.cleanupInactivePlayer(this.guildId);
|
|
286
|
+
}
|
|
278
287
|
return deleted;
|
|
279
288
|
}
|
|
280
289
|
/**
|
|
@@ -374,11 +383,8 @@ class Player {
|
|
|
374
383
|
console.error(error);
|
|
375
384
|
return this;
|
|
376
385
|
}
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
: ["startTime", "endTime", "noReplace"].every((v) => Object.keys(optionsOrTrack || {}).includes(v))
|
|
380
|
-
? optionsOrTrack
|
|
381
|
-
: {};
|
|
386
|
+
const isPlayOptions = (v) => typeof v === "object" && v !== null && ("startTime" in v || "endTime" in v || "noReplace" in v);
|
|
387
|
+
const finalOptions = playOptions ? playOptions : isPlayOptions(optionsOrTrack) ? optionsOrTrack : {};
|
|
382
388
|
await this.node.rest.updatePlayer({
|
|
383
389
|
guildId: this.guildId,
|
|
384
390
|
data: {
|
|
@@ -387,7 +393,7 @@ class Player {
|
|
|
387
393
|
},
|
|
388
394
|
});
|
|
389
395
|
this.playing = true;
|
|
390
|
-
this.position = 0;
|
|
396
|
+
this.position = finalOptions.startTime || 0;
|
|
391
397
|
return this;
|
|
392
398
|
}
|
|
393
399
|
/**
|
|
@@ -806,11 +812,8 @@ class Player {
|
|
|
806
812
|
if (currentPlayingTrack) {
|
|
807
813
|
await this.queue.add(currentPlayingTrack, 0);
|
|
808
814
|
}
|
|
809
|
-
await this.play(lastTrack);
|
|
810
|
-
}
|
|
811
|
-
else {
|
|
812
|
-
await this.play(lastTrack);
|
|
813
815
|
}
|
|
816
|
+
await this.play(lastTrack);
|
|
814
817
|
this.manager.emit(Enums_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this, {
|
|
815
818
|
changeType: Enums_1.PlayerStateEventTypes.TrackChange,
|
|
816
819
|
details: {
|
|
@@ -922,7 +925,8 @@ class Player {
|
|
|
922
925
|
const sessionId = this.voiceState?.sessionId;
|
|
923
926
|
const token = this.voiceState?.event?.token;
|
|
924
927
|
const endpoint = this.voiceState?.event?.endpoint;
|
|
925
|
-
|
|
928
|
+
const channelId = this.voiceState?.channelId;
|
|
929
|
+
if (!sessionId || !token || !endpoint || !channelId) {
|
|
926
930
|
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.`);
|
|
927
931
|
throw new MagmastreamError_1.MagmaStreamError({
|
|
928
932
|
code: Enums_1.MagmaStreamErrorCode.PLAYER_STATE_INVALID,
|
|
@@ -936,7 +940,7 @@ class Player {
|
|
|
936
940
|
this.manager.players.set(this.guildId, this);
|
|
937
941
|
await this.node.rest.updatePlayer({
|
|
938
942
|
guildId: this.guildId,
|
|
939
|
-
data: { paused: this.paused, volume: this.volume, position: playerPosition, encodedTrack: currentTrack?.track, voice: { token, endpoint, sessionId } },
|
|
943
|
+
data: { paused: this.paused, volume: this.volume, position: playerPosition, encodedTrack: currentTrack?.track, voice: { token, endpoint, sessionId, channelId } },
|
|
940
944
|
});
|
|
941
945
|
await this.filters.updateFilters();
|
|
942
946
|
}
|
|
@@ -953,115 +957,6 @@ class Player {
|
|
|
953
957
|
console.error(error);
|
|
954
958
|
}
|
|
955
959
|
}
|
|
956
|
-
/**
|
|
957
|
-
* Transfers the player to a new server. If the player already exists on the new server
|
|
958
|
-
* and force is false, this method will return the existing player. Otherwise, a new player
|
|
959
|
-
* will be created and the current player will be destroyed.
|
|
960
|
-
* @param {PlayerOptions} newOptions - The new options for the player.
|
|
961
|
-
* @param {boolean} force - Whether to force the creation of a new player.
|
|
962
|
-
* @returns {Promise<Player>} - The new player instance.
|
|
963
|
-
*/
|
|
964
|
-
async switchGuild(newOptions, force = false) {
|
|
965
|
-
if (!newOptions.guildId) {
|
|
966
|
-
throw new MagmastreamError_1.MagmaStreamError({
|
|
967
|
-
code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
|
|
968
|
-
message: "guildId is required for switchGuild",
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
if (!newOptions.voiceChannelId) {
|
|
972
|
-
throw new MagmastreamError_1.MagmaStreamError({
|
|
973
|
-
code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
|
|
974
|
-
message: "voiceChannelId is required for switchGuild",
|
|
975
|
-
});
|
|
976
|
-
}
|
|
977
|
-
if (!newOptions.textChannelId) {
|
|
978
|
-
throw new MagmastreamError_1.MagmaStreamError({
|
|
979
|
-
code: Enums_1.MagmaStreamErrorCode.PLAYER_INVALID_CONFIG,
|
|
980
|
-
message: "textChannelId is required for switchGuild",
|
|
981
|
-
});
|
|
982
|
-
}
|
|
983
|
-
// Check if a player already exists for the new guild
|
|
984
|
-
let newPlayer = this.manager.getPlayer(newOptions.guildId);
|
|
985
|
-
// If the player already exists and force is false, return the existing player
|
|
986
|
-
if (newPlayer && !force)
|
|
987
|
-
return newPlayer;
|
|
988
|
-
const oldPlayerProperties = {
|
|
989
|
-
paused: this.paused,
|
|
990
|
-
selfMute: this.options.selfMute,
|
|
991
|
-
selfDeafen: this.options.selfDeafen,
|
|
992
|
-
volume: this.volume,
|
|
993
|
-
position: this.position,
|
|
994
|
-
queue: {
|
|
995
|
-
current: await this.queue.getCurrent(),
|
|
996
|
-
tracks: [...(await this.queue.getTracks())],
|
|
997
|
-
previous: [...(await this.queue.getPrevious())],
|
|
998
|
-
},
|
|
999
|
-
trackRepeat: this.trackRepeat,
|
|
1000
|
-
queueRepeat: this.queueRepeat,
|
|
1001
|
-
dynamicRepeat: this.dynamicRepeat,
|
|
1002
|
-
dynamicRepeatIntervalMs: this.dynamicRepeatIntervalMs,
|
|
1003
|
-
ClientUser: this.get("Internal_AutoplayUser"),
|
|
1004
|
-
filters: this.filters,
|
|
1005
|
-
nowPlayingMessage: this.nowPlayingMessage,
|
|
1006
|
-
isAutoplay: this.isAutoplay,
|
|
1007
|
-
applyVolumeAsFilter: this.options.applyVolumeAsFilter,
|
|
1008
|
-
pauseOnDisconnect: this.options.pauseOnDisconnect,
|
|
1009
|
-
};
|
|
1010
|
-
// If force is true, destroy the existing player for the new guild
|
|
1011
|
-
if (force && newPlayer) {
|
|
1012
|
-
await newPlayer.destroy();
|
|
1013
|
-
}
|
|
1014
|
-
newOptions.nodeIdentifier = newOptions.nodeIdentifier ?? this.options.nodeIdentifier;
|
|
1015
|
-
newOptions.selfDeafen = newOptions.selfDeafen ?? oldPlayerProperties.selfDeafen;
|
|
1016
|
-
newOptions.selfMute = newOptions.selfMute ?? oldPlayerProperties.selfMute;
|
|
1017
|
-
newOptions.volume = newOptions.volume ?? oldPlayerProperties.volume;
|
|
1018
|
-
newOptions.applyVolumeAsFilter = newOptions.applyVolumeAsFilter ?? oldPlayerProperties.applyVolumeAsFilter;
|
|
1019
|
-
newOptions.pauseOnDisconnect = newOptions.pauseOnDisconnect ?? oldPlayerProperties.pauseOnDisconnect;
|
|
1020
|
-
// Deep clone the current player
|
|
1021
|
-
const clonedPlayer = this.manager.create(newOptions);
|
|
1022
|
-
// Connect the cloned player to the new voice channel
|
|
1023
|
-
clonedPlayer.connect();
|
|
1024
|
-
// Update the player's state on the Lavalink node
|
|
1025
|
-
await clonedPlayer.node.rest.updatePlayer({
|
|
1026
|
-
guildId: clonedPlayer.guildId,
|
|
1027
|
-
data: {
|
|
1028
|
-
paused: oldPlayerProperties.paused,
|
|
1029
|
-
volume: oldPlayerProperties.volume,
|
|
1030
|
-
position: oldPlayerProperties.position,
|
|
1031
|
-
encodedTrack: oldPlayerProperties.queue.current?.track,
|
|
1032
|
-
},
|
|
1033
|
-
});
|
|
1034
|
-
await clonedPlayer.queue.setCurrent(oldPlayerProperties.queue.current);
|
|
1035
|
-
await clonedPlayer.queue.addPrevious(oldPlayerProperties.queue.previous);
|
|
1036
|
-
await clonedPlayer.queue.add(oldPlayerProperties.queue.tracks);
|
|
1037
|
-
clonedPlayer.filters = oldPlayerProperties.filters;
|
|
1038
|
-
clonedPlayer.isAutoplay = oldPlayerProperties.isAutoplay;
|
|
1039
|
-
clonedPlayer.nowPlayingMessage = oldPlayerProperties.nowPlayingMessage;
|
|
1040
|
-
clonedPlayer.trackRepeat = oldPlayerProperties.trackRepeat;
|
|
1041
|
-
clonedPlayer.queueRepeat = oldPlayerProperties.queueRepeat;
|
|
1042
|
-
clonedPlayer.dynamicRepeat = oldPlayerProperties.dynamicRepeat;
|
|
1043
|
-
clonedPlayer.dynamicRepeatIntervalMs = oldPlayerProperties.dynamicRepeatIntervalMs;
|
|
1044
|
-
clonedPlayer.set("Internal_AutoplayUser", oldPlayerProperties.ClientUser);
|
|
1045
|
-
clonedPlayer.paused = oldPlayerProperties.paused;
|
|
1046
|
-
// Update filters for the cloned player
|
|
1047
|
-
await clonedPlayer.filters.updateFilters();
|
|
1048
|
-
// Debug information
|
|
1049
|
-
const debugInfo = {
|
|
1050
|
-
success: true,
|
|
1051
|
-
message: `Transferred ${await clonedPlayer.queue.size()} tracks successfully to <#${newOptions.voiceChannelId}> bound to <#${newOptions.textChannelId}>.`,
|
|
1052
|
-
player: {
|
|
1053
|
-
guildId: clonedPlayer.guildId,
|
|
1054
|
-
voiceChannelId: clonedPlayer.voiceChannelId,
|
|
1055
|
-
textChannelId: clonedPlayer.textChannelId,
|
|
1056
|
-
volume: clonedPlayer.volume,
|
|
1057
|
-
playing: clonedPlayer.playing,
|
|
1058
|
-
queueSize: clonedPlayer.queue.size,
|
|
1059
|
-
},
|
|
1060
|
-
};
|
|
1061
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[PLAYER] Transferred player to a new server: ${Utils_1.JSONUtils.safe(debugInfo, 2)}.`);
|
|
1062
|
-
// Return the cloned player
|
|
1063
|
-
return clonedPlayer;
|
|
1064
|
-
}
|
|
1065
960
|
/**
|
|
1066
961
|
* Retrieves the data associated with the player.
|
|
1067
962
|
* @returns {Record<string, unknown>} - The data associated with the player.
|
|
@@ -1076,6 +971,13 @@ class Player {
|
|
|
1076
971
|
getDynamicLoopIntervalPublic() {
|
|
1077
972
|
return this.dynamicLoopInterval;
|
|
1078
973
|
}
|
|
974
|
+
/**
|
|
975
|
+
* Retrieves the data associated with the player.
|
|
976
|
+
* @returns {Record<string, unknown>} - The data associated with the player.
|
|
977
|
+
*/
|
|
978
|
+
getSerializableData() {
|
|
979
|
+
return { ...this.data };
|
|
980
|
+
}
|
|
1079
981
|
/**
|
|
1080
982
|
* Retrieves the current lyrics for the playing track.
|
|
1081
983
|
* @param skipTrackSource - Indicates whether to skip the track source when fetching lyrics.
|
|
@@ -1239,5 +1141,26 @@ class Player {
|
|
|
1239
1141
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `VoiceReceiver error for player ${this.guildId}: ${error.message}`);
|
|
1240
1142
|
this.manager.emit(Enums_1.ManagerEventTypes.VoiceReceiverError, this, error);
|
|
1241
1143
|
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Updates the voice state for the player.
|
|
1146
|
+
* @returns {Promise<void>} - A promise that resolves when the voice state is updated.
|
|
1147
|
+
*/
|
|
1148
|
+
async updateVoice() {
|
|
1149
|
+
const vs = this.voiceState;
|
|
1150
|
+
const ev = vs?.event;
|
|
1151
|
+
if (!vs?.channelId || !vs?.sessionId || !ev?.token || !ev?.endpoint)
|
|
1152
|
+
return;
|
|
1153
|
+
await this.node.rest.updatePlayer({
|
|
1154
|
+
guildId: this.options.guildId,
|
|
1155
|
+
data: {
|
|
1156
|
+
voice: {
|
|
1157
|
+
token: ev.token,
|
|
1158
|
+
endpoint: ev.endpoint,
|
|
1159
|
+
sessionId: vs.sessionId,
|
|
1160
|
+
channelId: vs.channelId,
|
|
1161
|
+
},
|
|
1162
|
+
},
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1242
1165
|
}
|
|
1243
1166
|
exports.Player = Player;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Manager } from "./Manager";
|
|
2
|
+
/**
|
|
3
|
+
* Base abstract class for all plugins.
|
|
4
|
+
* Users must extend this and implement load and unload methods.
|
|
5
|
+
*/
|
|
6
|
+
export declare abstract class Plugin {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
/**
|
|
9
|
+
* @param name The name of the plugin
|
|
10
|
+
*/
|
|
11
|
+
constructor(name: string);
|
|
12
|
+
/**
|
|
13
|
+
* Load the plugin.
|
|
14
|
+
* @param manager The MagmaStream Manager instance
|
|
15
|
+
*/
|
|
16
|
+
abstract load(manager: Manager): void;
|
|
17
|
+
/**
|
|
18
|
+
* Unload the plugin.
|
|
19
|
+
* Called on shutdown to gracefully cleanup resources or detach listeners.
|
|
20
|
+
* @param manager The MagmaStream Manager instance
|
|
21
|
+
*/
|
|
22
|
+
abstract unload(manager: Manager): void;
|
|
23
|
+
}
|