magmastream 2.9.0-dev.31 → 2.9.0-dev.33
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 +230 -40
- package/dist/structures/Enums.js +5 -0
- package/dist/structures/Manager.js +78 -2
- package/dist/structures/Node.js +17 -4
- package/dist/structures/Player.js +132 -5
- package/dist/structures/Rest.js +3 -0
- package/dist/structures/Utils.js +295 -359
- package/package.json +1 -1
- package/dist/storage/CollectionPlayerStore.js +0 -77
- package/dist/storage/RedisPlayerStore.js +0 -156
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Collection } from '@discordjs/collection';
|
|
2
2
|
import { GatewayVoiceStateUpdate } from 'discord-api-types/v10';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
|
-
import WebSocket from 'ws';
|
|
4
|
+
import WebSocket, { WebSocket as WebSocket$1 } from 'ws';
|
|
5
5
|
import { User, ClientUser, Message, Client } from 'discord.js';
|
|
6
6
|
import { Redis } from 'ioredis';
|
|
7
7
|
import { Client as Client$1 } from 'eris';
|
|
@@ -28,6 +28,8 @@ declare class Rest {
|
|
|
28
28
|
private readonly url;
|
|
29
29
|
/** The Manager instance. */
|
|
30
30
|
manager: Manager;
|
|
31
|
+
/** Whether the node is a NodeLink. */
|
|
32
|
+
isNodeLink: boolean;
|
|
31
33
|
constructor(node: Node$1, manager: Manager);
|
|
32
34
|
/**
|
|
33
35
|
* Sets the session ID.
|
|
@@ -285,7 +287,12 @@ declare enum ManagerEventTypes {
|
|
|
285
287
|
TrackEnd = "trackEnd",
|
|
286
288
|
TrackError = "trackError",
|
|
287
289
|
TrackStart = "trackStart",
|
|
288
|
-
TrackStuck = "trackStuck"
|
|
290
|
+
TrackStuck = "trackStuck",
|
|
291
|
+
VoiceReceiverDisconnect = "voiceReceiverDisconnect",
|
|
292
|
+
VoiceReceiverConnect = "voiceReceiverConnect",
|
|
293
|
+
VoiceReceiverError = "voiceReceiverError",
|
|
294
|
+
VoiceReceiverStartSpeaking = "voiceReceiverStartSpeaking",
|
|
295
|
+
VoiceReceiverEndSpeaking = "voiceReceiverEndSpeaking"
|
|
289
296
|
}
|
|
290
297
|
/**
|
|
291
298
|
* Track End Reason Enum
|
|
@@ -729,15 +736,40 @@ interface LavaPlayer {
|
|
|
729
736
|
filters: Record<string, unknown>;
|
|
730
737
|
}
|
|
731
738
|
/**
|
|
732
|
-
* Search Result
|
|
739
|
+
* Error or Empty Search Result
|
|
733
740
|
*/
|
|
734
|
-
interface
|
|
741
|
+
interface ErrorOrEmptySearchResult {
|
|
735
742
|
/** The load type of the result. */
|
|
736
|
-
loadType: LoadTypes;
|
|
737
|
-
|
|
743
|
+
loadType: LoadTypes.Empty | LoadTypes.Error;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Track Search Result
|
|
747
|
+
*/
|
|
748
|
+
interface TrackSearchResult {
|
|
749
|
+
/** The load type is always 'track' */
|
|
750
|
+
loadType: LoadTypes.Track;
|
|
751
|
+
/** The track obtained */
|
|
752
|
+
tracks: [Track];
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Search Result
|
|
756
|
+
*/
|
|
757
|
+
interface SearchSearchResult {
|
|
758
|
+
/** The load type is always 'search' */
|
|
759
|
+
loadType: LoadTypes.Search;
|
|
760
|
+
/** The tracks of the search result */
|
|
761
|
+
tracks: Track[];
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Playlist Search Result
|
|
765
|
+
*/
|
|
766
|
+
interface PlaylistSearchResult {
|
|
767
|
+
/** The playlist load type */
|
|
768
|
+
loadType: LoadTypes.Playlist;
|
|
769
|
+
/** The tracks of the playlist */
|
|
738
770
|
tracks: Track[];
|
|
739
|
-
/** The playlist info
|
|
740
|
-
playlist
|
|
771
|
+
/** The playlist info */
|
|
772
|
+
playlist: PlaylistData;
|
|
741
773
|
}
|
|
742
774
|
/**
|
|
743
775
|
* Playlist Data
|
|
@@ -801,6 +833,11 @@ interface ManagerEvents {
|
|
|
801
833
|
[ManagerEventTypes.TrackError]: [player: Player, track: Track, payload: TrackExceptionEvent];
|
|
802
834
|
[ManagerEventTypes.TrackStart]: [player: Player, track: Track, payload: TrackStartEvent];
|
|
803
835
|
[ManagerEventTypes.TrackStuck]: [player: Player, track: Track, payload: TrackStuckEvent];
|
|
836
|
+
[ManagerEventTypes.VoiceReceiverDisconnect]: [player: Player];
|
|
837
|
+
[ManagerEventTypes.VoiceReceiverConnect]: [player: Player];
|
|
838
|
+
[ManagerEventTypes.VoiceReceiverError]: [player: Player, error: Error];
|
|
839
|
+
[ManagerEventTypes.VoiceReceiverStartSpeaking]: [player: Player, data: unknown];
|
|
840
|
+
[ManagerEventTypes.VoiceReceiverEndSpeaking]: [player: Player, data: unknown];
|
|
804
841
|
}
|
|
805
842
|
/**
|
|
806
843
|
* Voice Packet
|
|
@@ -997,6 +1034,8 @@ interface NodeOptions {
|
|
|
997
1034
|
apiRequestTimeoutMs?: number;
|
|
998
1035
|
/** Priority of the node. */
|
|
999
1036
|
nodePriority?: number;
|
|
1037
|
+
/** Whether the node is a NodeLink. */
|
|
1038
|
+
isNodeLink?: boolean;
|
|
1000
1039
|
}
|
|
1001
1040
|
/**
|
|
1002
1041
|
* NodeOptions interface
|
|
@@ -1139,6 +1178,100 @@ interface Lyrics {
|
|
|
1139
1178
|
lines: LyricsLine[];
|
|
1140
1179
|
plugin: object[];
|
|
1141
1180
|
}
|
|
1181
|
+
/**
|
|
1182
|
+
* NodeLink Get Lyrics Multiple interface
|
|
1183
|
+
*/
|
|
1184
|
+
interface NodeLinkGetLyricsMultiple {
|
|
1185
|
+
loadType: "lyricsMultiple";
|
|
1186
|
+
data: NodeLinkGetLyricsData[];
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* NodeLink Get Lyrics Empty interface
|
|
1190
|
+
*/
|
|
1191
|
+
interface NodeLinkGetLyricsEmpty {
|
|
1192
|
+
loadType: "empty";
|
|
1193
|
+
data: Record<never, never>;
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* NodeLink Get Lyrics Data interface
|
|
1197
|
+
*/
|
|
1198
|
+
interface NodeLinkGetLyricsData {
|
|
1199
|
+
name: string;
|
|
1200
|
+
synced: boolean;
|
|
1201
|
+
data: {
|
|
1202
|
+
startTime?: number;
|
|
1203
|
+
endTime?: number;
|
|
1204
|
+
text: string;
|
|
1205
|
+
}[];
|
|
1206
|
+
rtl: boolean;
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* NodeLink Get Lyrics Single interface
|
|
1210
|
+
*/
|
|
1211
|
+
interface NodeLinkGetLyricsSingle {
|
|
1212
|
+
loadType: "lyricsSingle";
|
|
1213
|
+
data: NodeLinkGetLyricsData;
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* NodeLink Get Lyrics Error interface
|
|
1217
|
+
*/
|
|
1218
|
+
interface NodeLinkGetLyricsError {
|
|
1219
|
+
loadType: "error";
|
|
1220
|
+
data: {
|
|
1221
|
+
message: string;
|
|
1222
|
+
severity: Severity;
|
|
1223
|
+
cause: string;
|
|
1224
|
+
trace?: string;
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
interface StartSpeakingEventVoiceReceiverData {
|
|
1228
|
+
/**
|
|
1229
|
+
* The user ID of the user who started speaking.
|
|
1230
|
+
*/
|
|
1231
|
+
userId: string;
|
|
1232
|
+
/**
|
|
1233
|
+
* The guild ID of the guild where the user started speaking.
|
|
1234
|
+
*/
|
|
1235
|
+
guildId: string;
|
|
1236
|
+
}
|
|
1237
|
+
interface EndSpeakingEventVoiceReceiverData {
|
|
1238
|
+
/**
|
|
1239
|
+
* The user ID of the user who stopped speaking.
|
|
1240
|
+
*/
|
|
1241
|
+
userId: string;
|
|
1242
|
+
/**
|
|
1243
|
+
* The guild ID of the guild where the user stopped speaking.
|
|
1244
|
+
*/
|
|
1245
|
+
guildId: string;
|
|
1246
|
+
/**
|
|
1247
|
+
* The audio data received from the user in base64.
|
|
1248
|
+
*/
|
|
1249
|
+
data: string;
|
|
1250
|
+
/**
|
|
1251
|
+
* The type of the audio data. Can be either opus or pcm. Older versions may include ogg/opus.
|
|
1252
|
+
*/
|
|
1253
|
+
type: "opus" | "pcm";
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Base Voice Receiver Event interface
|
|
1257
|
+
*/
|
|
1258
|
+
interface BaseVoiceReceiverEvent {
|
|
1259
|
+
op: "speak";
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Start Speaking Event Voice Receiver interface
|
|
1263
|
+
*/
|
|
1264
|
+
interface StartSpeakingEventVoiceReceiver extends BaseVoiceReceiverEvent {
|
|
1265
|
+
type: "startSpeakingEvent";
|
|
1266
|
+
data: StartSpeakingEventVoiceReceiverData;
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* End Speaking Event Voice Receiver interface
|
|
1270
|
+
*/
|
|
1271
|
+
interface EndSpeakingEventVoiceReceiver extends BaseVoiceReceiverEvent {
|
|
1272
|
+
type: "endSpeakingEvent";
|
|
1273
|
+
data: EndSpeakingEventVoiceReceiverData;
|
|
1274
|
+
}
|
|
1142
1275
|
/**
|
|
1143
1276
|
* PlayerOptions interface
|
|
1144
1277
|
*/
|
|
@@ -1179,25 +1312,6 @@ interface EqualizerBand {
|
|
|
1179
1312
|
/** The gain amount being -0.25 to 1.00, 0.25 being double. */
|
|
1180
1313
|
gain: number;
|
|
1181
1314
|
}
|
|
1182
|
-
/**
|
|
1183
|
-
* PlayerStore interface
|
|
1184
|
-
*/
|
|
1185
|
-
interface PlayerStore {
|
|
1186
|
-
get(guildId: string): Promise<Player | undefined>;
|
|
1187
|
-
set(guildId: string, player: Player): Promise<void>;
|
|
1188
|
-
delete(guildId: string): Promise<void>;
|
|
1189
|
-
keys(): Promise<string[]>;
|
|
1190
|
-
has(guildId: string): Promise<boolean>;
|
|
1191
|
-
filter(predicate: (player: Player, guildId: string) => boolean | Promise<boolean>): Promise<Map<string, Player>>;
|
|
1192
|
-
find(predicate: (player: Player, guildId: string) => boolean | Promise<boolean>): Promise<Player | undefined>;
|
|
1193
|
-
map<T>(callback: (player: Player, guildId: string) => T | Promise<T>): Promise<T[]>;
|
|
1194
|
-
forEach(callback: (player: Player, guildId: string) => void | Promise<void>): Promise<void>;
|
|
1195
|
-
some(predicate: (player: Player, guildId: string) => boolean | Promise<boolean>): Promise<boolean>;
|
|
1196
|
-
every(predicate: (player: Player, guildId: string) => boolean | Promise<boolean>): Promise<boolean>;
|
|
1197
|
-
size(): Promise<number>;
|
|
1198
|
-
clear(): Promise<void>;
|
|
1199
|
-
entries(): AsyncIterableIterator<[string, Player]>;
|
|
1200
|
-
}
|
|
1201
1315
|
/**
|
|
1202
1316
|
* Queue interface
|
|
1203
1317
|
*/
|
|
@@ -1270,6 +1384,18 @@ type PlayerEvents = TrackStartEvent | TrackEndEvent | TrackStuckEvent | TrackExc
|
|
|
1270
1384
|
* Load Type Enum type
|
|
1271
1385
|
*/
|
|
1272
1386
|
type LoadType = keyof typeof LoadTypes;
|
|
1387
|
+
/**
|
|
1388
|
+
* NodeLink Get Lyrics Enum type
|
|
1389
|
+
*/
|
|
1390
|
+
type NodeLinkGetLyrics = NodeLinkGetLyricsSingle | NodeLinkGetLyricsMultiple | NodeLinkGetLyricsEmpty | NodeLinkGetLyricsError;
|
|
1391
|
+
/**
|
|
1392
|
+
* Voice Receiver Event Enum type
|
|
1393
|
+
*/
|
|
1394
|
+
type VoiceReceiverEvent = StartSpeakingEventVoiceReceiver | EndSpeakingEventVoiceReceiver;
|
|
1395
|
+
/**
|
|
1396
|
+
* Search Result Enum type
|
|
1397
|
+
*/
|
|
1398
|
+
type SearchResult = TrackSearchResult | SearchSearchResult | PlaylistSearchResult | ErrorOrEmptySearchResult;
|
|
1273
1399
|
|
|
1274
1400
|
declare class Node$1 {
|
|
1275
1401
|
manager: Manager;
|
|
@@ -1285,11 +1411,14 @@ declare class Node$1 {
|
|
|
1285
1411
|
readonly rest: Rest;
|
|
1286
1412
|
/** Actual Lavalink information of the node. */
|
|
1287
1413
|
info: LavalinkInfo | null;
|
|
1414
|
+
/** Whether the node is a NodeLink. */
|
|
1415
|
+
isNodeLink: boolean;
|
|
1288
1416
|
private reconnectTimeout?;
|
|
1289
1417
|
private reconnectAttempts;
|
|
1290
1418
|
/**
|
|
1291
1419
|
* Creates an instance of Node.
|
|
1292
|
-
* @param
|
|
1420
|
+
* @param manager - The manager for the node.
|
|
1421
|
+
* @param options - The options for the node.
|
|
1293
1422
|
*/
|
|
1294
1423
|
constructor(manager: Manager, options: NodeOptions);
|
|
1295
1424
|
/** Returns if connected to the Node. */
|
|
@@ -1361,6 +1490,12 @@ declare class Node$1 {
|
|
|
1361
1490
|
* @emits {nodeDestroy} - Emits a nodeDestroy event if the maximum number of retry attempts is reached.
|
|
1362
1491
|
*/
|
|
1363
1492
|
private reconnect;
|
|
1493
|
+
/**
|
|
1494
|
+
* Upgrades the node to a NodeLink.
|
|
1495
|
+
*
|
|
1496
|
+
* @param request - The incoming message.
|
|
1497
|
+
*/
|
|
1498
|
+
private upgrade;
|
|
1364
1499
|
/**
|
|
1365
1500
|
* Handles the "open" event emitted by the WebSocket connection.
|
|
1366
1501
|
*
|
|
@@ -1492,9 +1627,9 @@ declare class Node$1 {
|
|
|
1492
1627
|
*
|
|
1493
1628
|
* @param {Track} track - The track to fetch the lyrics for.
|
|
1494
1629
|
* @param {boolean} [skipTrackSource=false] - Whether to skip using the track's source URL.
|
|
1495
|
-
* @returns {Promise<Lyrics>} A promise that resolves with the lyrics data.
|
|
1630
|
+
* @returns {Promise<Lyrics | NodeLinkGetLyrics>} A promise that resolves with the lyrics data.
|
|
1496
1631
|
*/
|
|
1497
|
-
getLyrics(track: Track, skipTrackSource?: boolean): Promise<Lyrics>;
|
|
1632
|
+
getLyrics(track: Track, skipTrackSource?: boolean): Promise<Lyrics | NodeLinkGetLyrics>;
|
|
1498
1633
|
/**
|
|
1499
1634
|
* Handles the event when a track becomes stuck during playback.
|
|
1500
1635
|
* Stops the current track and emits a `trackStuck` event.
|
|
@@ -1808,6 +1943,11 @@ declare class Manager extends EventEmitter {
|
|
|
1808
1943
|
* This is done to prevent stale state files from accumulating on the file system.
|
|
1809
1944
|
*/
|
|
1810
1945
|
private cleanupInactivePlayers;
|
|
1946
|
+
/**
|
|
1947
|
+
* Clears all player states from the file system.
|
|
1948
|
+
* This is done to prevent stale state files from accumulating on the file system.
|
|
1949
|
+
*/
|
|
1950
|
+
private clearAllPlayerStates;
|
|
1811
1951
|
/**
|
|
1812
1952
|
* Returns the nodes that has the least load.
|
|
1813
1953
|
* The load is calculated by dividing the lavalink load by the number of cores.
|
|
@@ -1884,6 +2024,12 @@ declare class Player {
|
|
|
1884
2024
|
private dynamicLoopInterval;
|
|
1885
2025
|
dynamicRepeatIntervalMs: number | null;
|
|
1886
2026
|
private static _manager;
|
|
2027
|
+
/** Should only be used when the node is a NodeLink */
|
|
2028
|
+
protected voiceReceiverWsClient: WebSocket$1 | null;
|
|
2029
|
+
protected isConnectToVoiceReceiver: boolean;
|
|
2030
|
+
protected voiceReceiverReconnectTimeout: NodeJS.Timeout | null;
|
|
2031
|
+
protected voiceReceiverAttempt: number;
|
|
2032
|
+
protected voiceReceiverReconnectTries: number;
|
|
1887
2033
|
/**
|
|
1888
2034
|
* Creates a new player, returns one if it already exists.
|
|
1889
2035
|
* @param options The player options.
|
|
@@ -2116,11 +2262,51 @@ declare class Player {
|
|
|
2116
2262
|
*/
|
|
2117
2263
|
getCurrentLyrics(skipTrackSource?: boolean): Promise<Lyrics>;
|
|
2118
2264
|
/**
|
|
2119
|
-
*
|
|
2120
|
-
* @
|
|
2121
|
-
* @
|
|
2265
|
+
* Sets up the voice receiver for the player.
|
|
2266
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is set up.
|
|
2267
|
+
* @throws {Error} - If the node is not a NodeLink.
|
|
2122
2268
|
*/
|
|
2123
|
-
|
|
2269
|
+
setupVoiceReceiver(): Promise<void>;
|
|
2270
|
+
/**
|
|
2271
|
+
* Removes the voice receiver for the player.
|
|
2272
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is removed.
|
|
2273
|
+
* @throws {Error} - If the node is not a NodeLink.
|
|
2274
|
+
*/
|
|
2275
|
+
removeVoiceReceiver(): Promise<void>;
|
|
2276
|
+
/**
|
|
2277
|
+
* Closes the voice receiver for the player.
|
|
2278
|
+
* @param {number} code - The code to close the voice receiver with.
|
|
2279
|
+
* @param {string} reason - The reason to close the voice receiver with.
|
|
2280
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is closed.
|
|
2281
|
+
*/
|
|
2282
|
+
private closeVoiceReceiver;
|
|
2283
|
+
/**
|
|
2284
|
+
* Reconnects the voice receiver for the player.
|
|
2285
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is reconnected.
|
|
2286
|
+
*/
|
|
2287
|
+
private reconnectVoiceReceiver;
|
|
2288
|
+
/**
|
|
2289
|
+
* Disconnects the voice receiver for the player.
|
|
2290
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is disconnected.
|
|
2291
|
+
*/
|
|
2292
|
+
private disconnectVoiceReceiver;
|
|
2293
|
+
/**
|
|
2294
|
+
* Opens the voice receiver for the player.
|
|
2295
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver is opened.
|
|
2296
|
+
*/
|
|
2297
|
+
private openVoiceReceiver;
|
|
2298
|
+
/**
|
|
2299
|
+
* Handles a voice receiver message.
|
|
2300
|
+
* @param {string} payload - The payload to handle.
|
|
2301
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver message is handled.
|
|
2302
|
+
*/
|
|
2303
|
+
private onVoiceReceiverMessage;
|
|
2304
|
+
/**
|
|
2305
|
+
* Handles a voice receiver error.
|
|
2306
|
+
* @param {Error} error - The error to handle.
|
|
2307
|
+
* @returns {Promise<void>} - A promise that resolves when the voice receiver error is handled.
|
|
2308
|
+
*/
|
|
2309
|
+
private onVoiceReceiverError;
|
|
2124
2310
|
}
|
|
2125
2311
|
|
|
2126
2312
|
declare class Filters {
|
|
@@ -2575,6 +2761,12 @@ declare abstract class TrackUtils {
|
|
|
2575
2761
|
* @returns The built Track.
|
|
2576
2762
|
*/
|
|
2577
2763
|
static build<T = User | ClientUser>(data: TrackData, requester?: T): Track;
|
|
2764
|
+
/**
|
|
2765
|
+
* Validates a search result.
|
|
2766
|
+
* @param result The search result to validate.
|
|
2767
|
+
* @returns Whether the search result is valid.
|
|
2768
|
+
*/
|
|
2769
|
+
static isErrorOrEmptySearchResult(result: SearchResult): result is ErrorOrEmptySearchResult;
|
|
2578
2770
|
}
|
|
2579
2771
|
declare abstract class AutoPlayUtils {
|
|
2580
2772
|
private static manager;
|
|
@@ -2583,7 +2775,7 @@ declare abstract class AutoPlayUtils {
|
|
|
2583
2775
|
* @param manager The manager instance to use.
|
|
2584
2776
|
* @hidden
|
|
2585
2777
|
*/
|
|
2586
|
-
static init(manager: Manager): void
|
|
2778
|
+
static init(manager: Manager): Promise<void>;
|
|
2587
2779
|
/**
|
|
2588
2780
|
* Gets recommended tracks for the given track.
|
|
2589
2781
|
* @param track The track to get recommended tracks for.
|
|
@@ -2603,10 +2795,8 @@ declare abstract class AutoPlayUtils {
|
|
|
2603
2795
|
* @param platform The source to get recommended tracks from.
|
|
2604
2796
|
* @returns An array of recommended tracks.
|
|
2605
2797
|
*/
|
|
2606
|
-
static getRecommendedTracksFromSource(track: Track, platform:
|
|
2607
|
-
static
|
|
2608
|
-
static transformSecret(buffer: Buffer): Buffer<ArrayBuffer>;
|
|
2609
|
-
static generateTotp(secretBuffer: Buffer): string;
|
|
2798
|
+
static getRecommendedTracksFromSource(track: Track, platform: AutoPlayPlatform): Promise<Track[]>;
|
|
2799
|
+
static buildTracksFromResponse<T>(recommendedResult: LavalinkResponse, requester?: T): Track[];
|
|
2610
2800
|
}
|
|
2611
2801
|
/** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
|
|
2612
2802
|
declare abstract class Structure {
|
|
@@ -2660,4 +2850,4 @@ declare class OceanicManager extends Manager {
|
|
|
2660
2850
|
}
|
|
2661
2851
|
|
|
2662
2852
|
export { AutoPlayPlatform, AutoPlayUtils, AvailableFilters, DetritusManager, DiscordJSManager, ErisManager, Filters, LoadTypes, Manager, ManagerEventTypes, Node$1 as Node, OceanicManager, Player, PlayerStateEventTypes, Plugin$1 as Plugin, Queue, Rest, SearchPlatform, SeverityTypes, SponsorBlockSegment, StateStorageType, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
|
|
2663
|
-
export type { CPUStats, DiscordPacket, EqualizerBand, Exception, Extendable, FrameStats, IQueue, LavaPlayer, LavalinkInfo, LavalinkResponse, LoadType, Lyrics, LyricsLine, ManagerEvents, ManagerInitOptions, ManagerOptions, MemoryStats, NodeMessage, NodeOptions, NodeStats, Payload, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerStateUpdateEvent,
|
|
2853
|
+
export type { CPUStats, DiscordPacket, EndSpeakingEventVoiceReceiver, EndSpeakingEventVoiceReceiverData, EqualizerBand, ErrorOrEmptySearchResult, Exception, Extendable, FrameStats, IQueue, LavaPlayer, LavalinkInfo, LavalinkResponse, LoadType, Lyrics, LyricsLine, ManagerEvents, ManagerInitOptions, ManagerOptions, MemoryStats, NodeLinkGetLyrics, NodeLinkGetLyricsEmpty, NodeLinkGetLyricsError, NodeLinkGetLyricsMultiple, NodeLinkGetLyricsSingle, NodeMessage, NodeOptions, NodeStats, Payload, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerStateUpdateEvent, PlayerUpdate, PlayerUpdateVoiceState, PlaylistData, PlaylistInfoData, PlaylistRawData, PlaylistSearchResult, RedisConfig, SearchQuery, SearchResult, SearchSearchResult, Severity, Sizes, SponsorBlockChapterStarted, SponsorBlockChaptersLoaded, SponsorBlockSegmentEventType, SponsorBlockSegmentEvents, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, StartSpeakingEventVoiceReceiver, StartSpeakingEventVoiceReceiverData, StateStorageOptions, Track, TrackData, TrackDataInfo, TrackEndEvent, TrackEndReason, TrackExceptionEvent, TrackPluginInfo, TrackSearchResult, TrackSourceName, TrackStartEvent, TrackStuckEvent, UseNodeOption, VoicePacket, VoiceReceiverEvent, VoiceServer, VoiceServerUpdate, VoiceState, WebSocketClosedEvent };
|
package/dist/structures/Enums.js
CHANGED
|
@@ -163,6 +163,11 @@ var ManagerEventTypes;
|
|
|
163
163
|
ManagerEventTypes["TrackError"] = "trackError";
|
|
164
164
|
ManagerEventTypes["TrackStart"] = "trackStart";
|
|
165
165
|
ManagerEventTypes["TrackStuck"] = "trackStuck";
|
|
166
|
+
ManagerEventTypes["VoiceReceiverDisconnect"] = "voiceReceiverDisconnect";
|
|
167
|
+
ManagerEventTypes["VoiceReceiverConnect"] = "voiceReceiverConnect";
|
|
168
|
+
ManagerEventTypes["VoiceReceiverError"] = "voiceReceiverError";
|
|
169
|
+
ManagerEventTypes["VoiceReceiverStartSpeaking"] = "voiceReceiverStartSpeaking";
|
|
170
|
+
ManagerEventTypes["VoiceReceiverEndSpeaking"] = "voiceReceiverEndSpeaking";
|
|
166
171
|
})(ManagerEventTypes || (exports.ManagerEventTypes = ManagerEventTypes = {}));
|
|
167
172
|
/**
|
|
168
173
|
* Track End Reason Enum
|
|
@@ -47,7 +47,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
47
47
|
// Initialize structures
|
|
48
48
|
Utils_1.Structure.get("Player").init(this);
|
|
49
49
|
Utils_1.TrackUtils.init(this);
|
|
50
|
-
Utils_1.AutoPlayUtils.init(this);
|
|
51
50
|
if (options.trackPartial) {
|
|
52
51
|
Utils_1.TrackUtils.setTrackPartial(options.trackPartial);
|
|
53
52
|
delete options.trackPartial;
|
|
@@ -77,6 +76,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
77
76
|
stateStorage: { type: Enums_1.StateStorageType.Collection },
|
|
78
77
|
...options,
|
|
79
78
|
};
|
|
79
|
+
Utils_1.AutoPlayUtils.init(this);
|
|
80
80
|
if (this.options.nodes) {
|
|
81
81
|
for (const nodeOptions of this.options.nodes)
|
|
82
82
|
new Node_1.Node(this, nodeOptions);
|
|
@@ -216,7 +216,20 @@ class Manager extends events_1.EventEmitter {
|
|
|
216
216
|
tracks = tracks.map(processTrack);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
-
|
|
219
|
+
let result;
|
|
220
|
+
switch (res.loadType) {
|
|
221
|
+
case Enums_1.LoadTypes.Playlist:
|
|
222
|
+
result = { loadType: res.loadType, tracks, playlist };
|
|
223
|
+
break;
|
|
224
|
+
case Enums_1.LoadTypes.Search:
|
|
225
|
+
result = { loadType: res.loadType, tracks };
|
|
226
|
+
break;
|
|
227
|
+
case Enums_1.LoadTypes.Track:
|
|
228
|
+
result = { loadType: res.loadType, tracks: [tracks[0]] };
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
return { loadType: res.loadType };
|
|
232
|
+
}
|
|
220
233
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Result ${_source} search for: ${_query.query}: ${JSON.stringify(result)}`);
|
|
221
234
|
return result;
|
|
222
235
|
}
|
|
@@ -791,6 +804,9 @@ class Manager extends events_1.EventEmitter {
|
|
|
791
804
|
async handleShutdown() {
|
|
792
805
|
console.warn("\x1b[31m%s\x1b[0m", "MAGMASTREAM WARNING: Shutting down! Please wait, saving active players...");
|
|
793
806
|
try {
|
|
807
|
+
if (this.options.stateStorage.type === Enums_1.StateStorageType.Collection) {
|
|
808
|
+
await this.clearAllPlayerStates();
|
|
809
|
+
}
|
|
794
810
|
const savePromises = Array.from(this.players.keys()).map(async (guildId) => {
|
|
795
811
|
try {
|
|
796
812
|
await this.savePlayerState(guildId);
|
|
@@ -925,6 +941,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
925
941
|
guildId: player.guildId,
|
|
926
942
|
data: { voice: { token, endpoint, sessionId } },
|
|
927
943
|
});
|
|
944
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `Updated voice server for player ${player.guildId} with token ${token} and endpoint ${endpoint} and sessionId ${sessionId}`);
|
|
928
945
|
return;
|
|
929
946
|
}
|
|
930
947
|
/**
|
|
@@ -935,6 +952,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
935
952
|
* @emits {playerDisconnect} - Emits a player disconnect event if the channel ID is null.
|
|
936
953
|
*/
|
|
937
954
|
async handleVoiceStateUpdate(player, update) {
|
|
955
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `Updated voice state for player ${player.guildId} with channel id ${update.channel_id} and session id ${update.session_id}`);
|
|
938
956
|
if (update.channel_id) {
|
|
939
957
|
if (player.voiceChannelId !== update.channel_id) {
|
|
940
958
|
this.emit(Enums_1.ManagerEventTypes.PlayerMove, player, player.voiceChannelId, update.channel_id);
|
|
@@ -1052,6 +1070,64 @@ class Manager extends events_1.EventEmitter {
|
|
|
1052
1070
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Error cleaning up inactive players: ${error}`);
|
|
1053
1071
|
}
|
|
1054
1072
|
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Clears all player states from the file system.
|
|
1075
|
+
* This is done to prevent stale state files from accumulating on the file system.
|
|
1076
|
+
*/
|
|
1077
|
+
async clearAllPlayerStates() {
|
|
1078
|
+
switch (this.options.stateStorage.type) {
|
|
1079
|
+
case Enums_1.StateStorageType.Collection: {
|
|
1080
|
+
const configDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
|
|
1081
|
+
try {
|
|
1082
|
+
// Check if the directory exists, and create it if it doesn't
|
|
1083
|
+
await promises_1.default.access(configDir).catch(async () => {
|
|
1084
|
+
await promises_1.default.mkdir(configDir, { recursive: true });
|
|
1085
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Created directory: ${configDir}`);
|
|
1086
|
+
});
|
|
1087
|
+
const files = await promises_1.default.readdir(configDir);
|
|
1088
|
+
await Promise.all(files.map((file) => promises_1.default.unlink(path_1.default.join(configDir, file)).catch((err) => console.warn(`Failed to delete file ${file}:`, err))));
|
|
1089
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Cleared all player state files in ${configDir}`);
|
|
1090
|
+
}
|
|
1091
|
+
catch (err) {
|
|
1092
|
+
console.error("Error clearing player state files:", err);
|
|
1093
|
+
}
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
case Enums_1.StateStorageType.Redis: {
|
|
1097
|
+
const prefix = this.options.stateStorage.redisConfig.prefix?.endsWith(":")
|
|
1098
|
+
? this.options.stateStorage.redisConfig.prefix
|
|
1099
|
+
: this.options.stateStorage.redisConfig.prefix ?? "magmastream:";
|
|
1100
|
+
const pattern = `${prefix}playerstore:*`;
|
|
1101
|
+
try {
|
|
1102
|
+
const stream = this.redis.scanStream({
|
|
1103
|
+
match: pattern,
|
|
1104
|
+
count: 100,
|
|
1105
|
+
});
|
|
1106
|
+
let totalDeleted = 0;
|
|
1107
|
+
stream.on("data", async (keys) => {
|
|
1108
|
+
if (keys.length) {
|
|
1109
|
+
const pipeline = this.redis.pipeline();
|
|
1110
|
+
keys.forEach((key) => pipeline.unlink(key));
|
|
1111
|
+
await pipeline.exec();
|
|
1112
|
+
totalDeleted += keys.length;
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
stream.on("end", () => {
|
|
1116
|
+
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Cleared ${totalDeleted} Redis player state keys (pattern: ${pattern})`);
|
|
1117
|
+
});
|
|
1118
|
+
stream.on("error", (err) => {
|
|
1119
|
+
console.error("Error during Redis SCAN stream:", err);
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
catch (err) {
|
|
1123
|
+
console.error("Failed to clear Redis player state keys:", err);
|
|
1124
|
+
}
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
1127
|
+
default:
|
|
1128
|
+
console.warn("[MANAGER] No valid stateStorage.type set, skipping state clearing.");
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1055
1131
|
/**
|
|
1056
1132
|
* Returns the nodes that has the least load.
|
|
1057
1133
|
* The load is calculated by dividing the lavalink load by the number of cores.
|
package/dist/structures/Node.js
CHANGED
|
@@ -31,11 +31,14 @@ class Node {
|
|
|
31
31
|
rest;
|
|
32
32
|
/** Actual Lavalink information of the node. */
|
|
33
33
|
info = null;
|
|
34
|
+
/** Whether the node is a NodeLink. */
|
|
35
|
+
isNodeLink = false;
|
|
34
36
|
reconnectTimeout;
|
|
35
37
|
reconnectAttempts = 1;
|
|
36
38
|
/**
|
|
37
39
|
* Creates an instance of Node.
|
|
38
|
-
* @param
|
|
40
|
+
* @param manager - The manager for the node.
|
|
41
|
+
* @param options - The options for the node.
|
|
39
42
|
*/
|
|
40
43
|
constructor(manager, options) {
|
|
41
44
|
this.manager = manager;
|
|
@@ -185,6 +188,7 @@ class Node {
|
|
|
185
188
|
this.socket = new ws_1.default(`ws${this.options.useSSL ? "s" : ""}://${this.address}/v4/websocket`, { headers });
|
|
186
189
|
this.socket.on("open", this.open.bind(this));
|
|
187
190
|
this.socket.on("close", this.close.bind(this));
|
|
191
|
+
this.socket.on("upgrade", (request) => this.upgrade(request));
|
|
188
192
|
this.socket.on("message", this.message.bind(this));
|
|
189
193
|
this.socket.on("error", this.error.bind(this));
|
|
190
194
|
const debugInfo = {
|
|
@@ -287,6 +291,14 @@ class Node {
|
|
|
287
291
|
this.reconnectAttempts++;
|
|
288
292
|
}, this.options.retryDelayMs);
|
|
289
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Upgrades the node to a NodeLink.
|
|
296
|
+
*
|
|
297
|
+
* @param request - The incoming message.
|
|
298
|
+
*/
|
|
299
|
+
upgrade(request) {
|
|
300
|
+
this.isNodeLink = this.options.isNodeLink ?? Boolean(request.headers.isnodelink) ?? false;
|
|
301
|
+
}
|
|
290
302
|
/**
|
|
291
303
|
* Handles the "open" event emitted by the WebSocket connection.
|
|
292
304
|
*
|
|
@@ -727,13 +739,14 @@ class Node {
|
|
|
727
739
|
*
|
|
728
740
|
* @param {Track} track - The track to fetch the lyrics for.
|
|
729
741
|
* @param {boolean} [skipTrackSource=false] - Whether to skip using the track's source URL.
|
|
730
|
-
* @returns {Promise<Lyrics>} A promise that resolves with the lyrics data.
|
|
742
|
+
* @returns {Promise<Lyrics | NodeLinkGetLyrics>} A promise that resolves with the lyrics data.
|
|
731
743
|
*/
|
|
732
744
|
async getLyrics(track, skipTrackSource = false) {
|
|
745
|
+
if (this.isNodeLink) {
|
|
746
|
+
return (await this.rest.get(`/v4/lyrics?track=${encodeURIComponent(track.track)}&skipTrackSource=${skipTrackSource}`));
|
|
747
|
+
}
|
|
733
748
|
if (!this.info.plugins.some((plugin) => plugin.name === "lavalyrics-plugin"))
|
|
734
749
|
throw new RangeError(`there is no lavalyrics-plugin available in the lavalink node: ${this.options.identifier}`);
|
|
735
|
-
// Make a GET request to the Lavalink node to fetch the lyrics
|
|
736
|
-
// The request includes the track URL and the skipTrackSource parameter
|
|
737
750
|
return ((await this.rest.get(`/v4/lyrics?track=${encodeURIComponent(track.track)}&skipTrackSource=${skipTrackSource}`)) || {
|
|
738
751
|
source: null,
|
|
739
752
|
provider: null,
|