magmastream 2.9.0-dev.7 → 2.9.0-dev.9
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 +23 -25
- package/dist/storage/CollectionPlayerStore.js +1 -0
- package/dist/storage/RedisPlayerStore.js +6 -2
- package/dist/structures/Manager.js +34 -79
- package/dist/structures/Player.js +7 -4
- package/dist/structures/Queue.js +15 -0
- package/dist/structures/RedisQueue.js +39 -16
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -649,6 +649,11 @@ declare class Queue extends Array<Track> implements IQueue {
|
|
|
649
649
|
getTracks(): Promise<Track[]>;
|
|
650
650
|
getSlice(start?: number, end?: number): Promise<Track[]>;
|
|
651
651
|
modifyAt(start: number, deleteCount?: number, ...items: Track[]): Promise<Track[]>;
|
|
652
|
+
mapAsync<T>(callback: (track: Track, index: number, array: Track[]) => T): Promise<T[]>;
|
|
653
|
+
filterAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<Track[]>;
|
|
654
|
+
findAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<Track | undefined>;
|
|
655
|
+
someAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<boolean>;
|
|
656
|
+
everyAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<boolean>;
|
|
652
657
|
}
|
|
653
658
|
|
|
654
659
|
declare abstract class TrackUtils {
|
|
@@ -929,6 +934,11 @@ interface IQueue {
|
|
|
929
934
|
shuffle(): Promise<void>;
|
|
930
935
|
userBlockShuffle(): Promise<void>;
|
|
931
936
|
roundRobinShuffle(): Promise<void>;
|
|
937
|
+
mapAsync<T>(callback: (track: Track, index: number, array: Track[]) => T): Promise<T[]>;
|
|
938
|
+
filterAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<Track[]>;
|
|
939
|
+
findAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<Track | undefined>;
|
|
940
|
+
someAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<boolean>;
|
|
941
|
+
everyAsync(callback: (track: Track, index: number, array: Track[]) => boolean): Promise<boolean>;
|
|
932
942
|
}
|
|
933
943
|
|
|
934
944
|
/**
|
|
@@ -936,7 +946,7 @@ interface IQueue {
|
|
|
936
946
|
*/
|
|
937
947
|
declare class Manager extends EventEmitter {
|
|
938
948
|
/** The map of players. */
|
|
939
|
-
|
|
949
|
+
readonly players: Collection<string, Player>;
|
|
940
950
|
/** The map of nodes. */
|
|
941
951
|
readonly nodes: Collection<string, Node>;
|
|
942
952
|
/** The options that were set. */
|
|
@@ -959,7 +969,6 @@ declare class Manager extends EventEmitter {
|
|
|
959
969
|
* @param options.eventBatchInterval - The interval to wait before processing the collected player state events.
|
|
960
970
|
*/
|
|
961
971
|
constructor(options: ManagerOptions);
|
|
962
|
-
get players(): PlayerStore;
|
|
963
972
|
/**
|
|
964
973
|
* Initiates the Manager.
|
|
965
974
|
* @param clientId - The Discord client ID (required).
|
|
@@ -979,30 +988,20 @@ declare class Manager extends EventEmitter {
|
|
|
979
988
|
* @param guildId The guild ID of the player to retrieve.
|
|
980
989
|
* @returns The player if it exists, undefined otherwise.
|
|
981
990
|
*/
|
|
982
|
-
getPlayer(guildId: string):
|
|
991
|
+
getPlayer(guildId: string): Player | undefined;
|
|
983
992
|
/**
|
|
984
|
-
*
|
|
985
|
-
*
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
/**
|
|
989
|
-
* Remove player data.
|
|
990
|
-
* @param guildId The guild ID of the player to remove.
|
|
993
|
+
* @deprecated - Will be removed with v2.10.0 use {@link getPlayer} instead
|
|
994
|
+
* Returns a player or undefined if it does not exist.
|
|
995
|
+
* @param guildId The guild ID of the player to retrieve.
|
|
996
|
+
* @returns The player if it exists, undefined otherwise.
|
|
991
997
|
*/
|
|
992
|
-
|
|
998
|
+
get(guildId: string): Promise<Player | undefined>;
|
|
993
999
|
/**
|
|
994
1000
|
* Creates a player or returns one if it already exists.
|
|
995
1001
|
* @param options The options to create the player with.
|
|
996
1002
|
* @returns The created player.
|
|
997
1003
|
*/
|
|
998
|
-
create(options: PlayerOptions):
|
|
999
|
-
/**
|
|
1000
|
-
* @deprecated - Will be removed with v2.10.0 use {@link setPlayer} instead
|
|
1001
|
-
* Returns a player or undefined if it does not exist.
|
|
1002
|
-
* @param guildId The guild ID of the player to retrieve.
|
|
1003
|
-
* @returns The player if it exists, undefined otherwise.
|
|
1004
|
-
*/
|
|
1005
|
-
get(guildId: string): Promise<Player | undefined>;
|
|
1004
|
+
create(options: PlayerOptions): Player;
|
|
1006
1005
|
/**
|
|
1007
1006
|
* Destroys a player.
|
|
1008
1007
|
* @param guildId The guild ID of the player to destroy.
|
|
@@ -1138,7 +1137,7 @@ declare class Manager extends EventEmitter {
|
|
|
1138
1137
|
* @param player The Player instance to serialize
|
|
1139
1138
|
* @returns The serialized Player instance
|
|
1140
1139
|
*/
|
|
1141
|
-
|
|
1140
|
+
serializePlayer(player: Player): Record<string, unknown>;
|
|
1142
1141
|
/**
|
|
1143
1142
|
* Checks for players that are no longer active and deletes their saved state files.
|
|
1144
1143
|
* This is done to prevent stale state files from accumulating on the file system.
|
|
@@ -1168,7 +1167,6 @@ declare class Manager extends EventEmitter {
|
|
|
1168
1167
|
* @returns {Node} The node to use.
|
|
1169
1168
|
*/
|
|
1170
1169
|
private get priorityNode();
|
|
1171
|
-
private getAllGuildIds;
|
|
1172
1170
|
}
|
|
1173
1171
|
interface Payload {
|
|
1174
1172
|
/** The OP code */
|
|
@@ -1472,7 +1470,7 @@ interface PlayerStore {
|
|
|
1472
1470
|
declare class Player {
|
|
1473
1471
|
options: PlayerOptions;
|
|
1474
1472
|
/** The Queue for the Player. */
|
|
1475
|
-
|
|
1473
|
+
queue: IQueue;
|
|
1476
1474
|
/** The filters applied to the audio. */
|
|
1477
1475
|
filters: Filters;
|
|
1478
1476
|
/** Whether the queue repeats the track. */
|
|
@@ -1514,7 +1512,7 @@ declare class Player {
|
|
|
1514
1512
|
private static _manager;
|
|
1515
1513
|
private readonly data;
|
|
1516
1514
|
private dynamicLoopInterval;
|
|
1517
|
-
|
|
1515
|
+
dynamicRepeatIntervalMs: number | null;
|
|
1518
1516
|
/**
|
|
1519
1517
|
* Creates a new player, returns one if it already exists.
|
|
1520
1518
|
* @param options The player options.
|
|
@@ -1561,11 +1559,11 @@ declare class Player {
|
|
|
1561
1559
|
/**
|
|
1562
1560
|
* Destroys the player and clears the queue.
|
|
1563
1561
|
* @param {boolean} disconnect - Whether to disconnect the player from the voice channel.
|
|
1564
|
-
* @returns {Promise<
|
|
1562
|
+
* @returns {Promise<boolean>} - Whether the player was successfully destroyed.
|
|
1565
1563
|
* @emits {PlayerDestroy} - Emitted when the player is destroyed.
|
|
1566
1564
|
* @emits {PlayerStateUpdate} - Emitted when the player state is updated.
|
|
1567
1565
|
*/
|
|
1568
|
-
destroy(disconnect?: boolean): Promise<
|
|
1566
|
+
destroy(disconnect?: boolean): Promise<boolean>;
|
|
1569
1567
|
/**
|
|
1570
1568
|
* Sets the player voice channel.
|
|
1571
1569
|
* @param {string} channel - The new voice channel ID.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
// THIS WILL BE REMOVED IF YOU DONT FIND A USE FOR IT.
|
|
2
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
exports.RedisPlayerStore = void 0;
|
|
4
5
|
class RedisPlayerStore {
|
|
5
6
|
redis;
|
|
7
|
+
manager;
|
|
6
8
|
prefix;
|
|
7
|
-
constructor(redis, prefix = "magmastream:") {
|
|
9
|
+
constructor(redis, manager, prefix = "magmastream:") {
|
|
8
10
|
this.redis = redis;
|
|
11
|
+
this.manager = manager;
|
|
9
12
|
this.prefix = prefix;
|
|
10
13
|
}
|
|
11
14
|
getKey(guildId) {
|
|
@@ -18,7 +21,8 @@ class RedisPlayerStore {
|
|
|
18
21
|
return JSON.parse(raw);
|
|
19
22
|
}
|
|
20
23
|
async set(guildId, player) {
|
|
21
|
-
|
|
24
|
+
const serialized = this.manager.serializePlayer(player);
|
|
25
|
+
await this.redis.set(this.getKey(guildId), JSON.stringify(serialized));
|
|
22
26
|
}
|
|
23
27
|
async delete(guildId) {
|
|
24
28
|
await this.redis.del(this.getKey(guildId));
|
|
@@ -11,14 +11,12 @@ const blockedWords_1 = require("../config/blockedWords");
|
|
|
11
11
|
const promises_1 = tslib_1.__importDefault(require("fs/promises"));
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
13
13
|
const ioredis_1 = tslib_1.__importDefault(require("ioredis"));
|
|
14
|
-
const RedisPlayerStore_1 = require("../storage/RedisPlayerStore");
|
|
15
|
-
const CollectionPlayerStore_1 = require("../storage/CollectionPlayerStore");
|
|
16
14
|
/**
|
|
17
15
|
* The main hub for interacting with Lavalink and using Magmastream,
|
|
18
16
|
*/
|
|
19
17
|
class Manager extends events_1.EventEmitter {
|
|
20
18
|
/** The map of players. */
|
|
21
|
-
|
|
19
|
+
players = new collection_1.Collection();
|
|
22
20
|
/** The map of nodes. */
|
|
23
21
|
nodes = new collection_1.Collection();
|
|
24
22
|
/** The options that were set. */
|
|
@@ -102,9 +100,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
102
100
|
}
|
|
103
101
|
});
|
|
104
102
|
}
|
|
105
|
-
get players() {
|
|
106
|
-
return this._players;
|
|
107
|
-
}
|
|
108
103
|
/**
|
|
109
104
|
* Initiates the Manager.
|
|
110
105
|
* @param clientId - The Discord client ID (required).
|
|
@@ -141,17 +136,12 @@ class Manager extends events_1.EventEmitter {
|
|
|
141
136
|
}
|
|
142
137
|
if (this.options.stateStorage?.type === StateStorageType.Redis) {
|
|
143
138
|
const config = this.options.stateStorage.redisConfig;
|
|
144
|
-
const prefix = config.prefix?.endsWith(":") ? config.prefix : `${config.prefix ?? "magmastream"}:`;
|
|
145
139
|
this.redis = new ioredis_1.default({
|
|
146
140
|
host: config.host,
|
|
147
141
|
port: Number(config.port),
|
|
148
142
|
password: config.password,
|
|
149
143
|
db: config.db ?? 0,
|
|
150
144
|
});
|
|
151
|
-
this._players = new RedisPlayerStore_1.RedisPlayerStore(this.redis, prefix);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
this._players = new CollectionPlayerStore_1.CollectionPlayerStore();
|
|
155
145
|
}
|
|
156
146
|
this.initiated = true;
|
|
157
147
|
return this;
|
|
@@ -225,61 +215,30 @@ class Manager extends events_1.EventEmitter {
|
|
|
225
215
|
* @param guildId The guild ID of the player to retrieve.
|
|
226
216
|
* @returns The player if it exists, undefined otherwise.
|
|
227
217
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return this._players.get(guildId);
|
|
231
|
-
}
|
|
232
|
-
return await this._players.get(guildId);
|
|
218
|
+
getPlayer(guildId) {
|
|
219
|
+
return this.players.get(guildId);
|
|
233
220
|
}
|
|
234
221
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (this._players instanceof collection_1.Collection) {
|
|
240
|
-
this._players.set(guildId, player);
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
await this._players.set(guildId, player);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Remove player data.
|
|
248
|
-
* @param guildId The guild ID of the player to remove.
|
|
222
|
+
* @deprecated - Will be removed with v2.10.0 use {@link getPlayer} instead
|
|
223
|
+
* Returns a player or undefined if it does not exist.
|
|
224
|
+
* @param guildId The guild ID of the player to retrieve.
|
|
225
|
+
* @returns The player if it exists, undefined otherwise.
|
|
249
226
|
*/
|
|
250
|
-
async
|
|
251
|
-
|
|
252
|
-
this._players.delete(guildId);
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
await this._players.delete(guildId);
|
|
256
|
-
}
|
|
227
|
+
async get(guildId) {
|
|
228
|
+
return this.players.get(guildId);
|
|
257
229
|
}
|
|
258
230
|
/**
|
|
259
231
|
* Creates a player or returns one if it already exists.
|
|
260
232
|
* @param options The options to create the player with.
|
|
261
233
|
* @returns The created player.
|
|
262
234
|
*/
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return existing;
|
|
267
|
-
this.emit(ManagerEventTypes.Debug, `[MANAGER] Creating new player with options: ${JSON.stringify(options)}`);
|
|
268
|
-
const player = new (Utils_1.Structure.get("Player"))(options);
|
|
269
|
-
await this.setPlayer(options.guildId, player);
|
|
270
|
-
return player;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* @deprecated - Will be removed with v2.10.0 use {@link setPlayer} instead
|
|
274
|
-
* Returns a player or undefined if it does not exist.
|
|
275
|
-
* @param guildId The guild ID of the player to retrieve.
|
|
276
|
-
* @returns The player if it exists, undefined otherwise.
|
|
277
|
-
*/
|
|
278
|
-
async get(guildId) {
|
|
279
|
-
if (this._players instanceof collection_1.Collection) {
|
|
280
|
-
return this._players.get(guildId);
|
|
235
|
+
create(options) {
|
|
236
|
+
if (this.players.has(options.guildId)) {
|
|
237
|
+
return this.players.get(options.guildId);
|
|
281
238
|
}
|
|
282
|
-
|
|
239
|
+
// Create a new player with the given options
|
|
240
|
+
this.emit(ManagerEventTypes.Debug, `[MANAGER] Creating new player with options: ${JSON.stringify(options)}`);
|
|
241
|
+
return new (Utils_1.Structure.get("Player"))(options);
|
|
283
242
|
}
|
|
284
243
|
/**
|
|
285
244
|
* Destroys a player.
|
|
@@ -289,7 +248,8 @@ class Manager extends events_1.EventEmitter {
|
|
|
289
248
|
async destroy(guildId) {
|
|
290
249
|
// Emit debug message for player destruction
|
|
291
250
|
this.emit(ManagerEventTypes.Debug, `[MANAGER] Destroying player: ${guildId}`);
|
|
292
|
-
|
|
251
|
+
// Remove the player from the manager's collection
|
|
252
|
+
this.players.delete(guildId);
|
|
293
253
|
// Clean up any inactive players
|
|
294
254
|
await this.cleanupInactivePlayers();
|
|
295
255
|
}
|
|
@@ -344,7 +304,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
344
304
|
const update = "d" in data ? data.d : data;
|
|
345
305
|
if (!this.isValidUpdate(update))
|
|
346
306
|
return;
|
|
347
|
-
const player =
|
|
307
|
+
const player = this.getPlayer(update.guild_id);
|
|
348
308
|
if (!player)
|
|
349
309
|
return;
|
|
350
310
|
this.emit(ManagerEventTypes.Debug, `[MANAGER] Updating voice state: ${JSON.stringify(update)}`);
|
|
@@ -399,7 +359,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
399
359
|
async savePlayerState(guildId) {
|
|
400
360
|
try {
|
|
401
361
|
const playerStateFilePath = await this.getPlayerFilePath(guildId);
|
|
402
|
-
const player =
|
|
362
|
+
const player = this.getPlayer(guildId);
|
|
403
363
|
if (!player || player.state === Utils_1.StateTypes.Disconnected || !player.voiceChannelId) {
|
|
404
364
|
console.warn(`Skipping save for inactive player: ${guildId}`);
|
|
405
365
|
return;
|
|
@@ -455,7 +415,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
455
415
|
node: nodeId,
|
|
456
416
|
};
|
|
457
417
|
this.emit(ManagerEventTypes.Debug, `[MANAGER] Recreating player: ${state.guildId} from saved file: ${JSON.stringify(state.options)}`);
|
|
458
|
-
const player =
|
|
418
|
+
const player = this.create(playerOptions);
|
|
459
419
|
await player.node.rest.updatePlayer({
|
|
460
420
|
guildId: state.options.guildId,
|
|
461
421
|
data: { voice: { token: state.voiceState.event.token, endpoint: state.voiceState.event.endpoint, sessionId: state.voiceState.sessionId } },
|
|
@@ -613,8 +573,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
613
573
|
async handleShutdown() {
|
|
614
574
|
console.warn("\x1b[31m%s\x1b[0m", "MAGMASTREAM WARNING: Shutting down! Please wait, saving active players...");
|
|
615
575
|
try {
|
|
616
|
-
const
|
|
617
|
-
const savePromises = Array.from(guildIds).map(async (guildId) => {
|
|
576
|
+
const savePromises = Array.from(this.players.keys()).map(async (guildId) => {
|
|
618
577
|
try {
|
|
619
578
|
await this.savePlayerState(guildId);
|
|
620
579
|
}
|
|
@@ -813,6 +772,8 @@ class Manager extends events_1.EventEmitter {
|
|
|
813
772
|
return null;
|
|
814
773
|
}
|
|
815
774
|
if (key === "filters") {
|
|
775
|
+
if (!value || typeof value !== "object")
|
|
776
|
+
return null;
|
|
816
777
|
return {
|
|
817
778
|
distortion: value.distortion ?? null,
|
|
818
779
|
equalizer: value.equalizer ?? [],
|
|
@@ -823,14 +784,14 @@ class Manager extends events_1.EventEmitter {
|
|
|
823
784
|
reverb: value.reverb ?? null,
|
|
824
785
|
volume: value.volume ?? 1.0,
|
|
825
786
|
bassBoostlevel: value.bassBoostlevel ?? null,
|
|
826
|
-
filterStatus: { ...value.filtersStatus },
|
|
787
|
+
filterStatus: value.filtersStatus ? { ...value.filtersStatus } : {},
|
|
827
788
|
};
|
|
828
789
|
}
|
|
829
790
|
if (key === "queue") {
|
|
830
791
|
return {
|
|
831
792
|
current: value.current || null,
|
|
832
|
-
tracks: [...value],
|
|
833
|
-
previous: [...value.previous],
|
|
793
|
+
tracks: Array.isArray(value) ? [...value] : [],
|
|
794
|
+
previous: Array.isArray(value.previous) ? [...value.previous] : [],
|
|
834
795
|
};
|
|
835
796
|
}
|
|
836
797
|
if (key === "data") {
|
|
@@ -853,17 +814,18 @@ class Manager extends events_1.EventEmitter {
|
|
|
853
814
|
await promises_1.default.mkdir(playerStatesDir, { recursive: true });
|
|
854
815
|
this.emit(ManagerEventTypes.Debug, `[MANAGER] Created directory: ${playerStatesDir}`);
|
|
855
816
|
});
|
|
856
|
-
// Get
|
|
817
|
+
// Get the list of player state files
|
|
857
818
|
const playerFiles = await promises_1.default.readdir(playerStatesDir);
|
|
858
|
-
// Get active guild IDs from
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
// Delete state files that don't match active players
|
|
819
|
+
// Get the set of active guild IDs from the manager's player collection
|
|
820
|
+
const activeGuildIds = new Set(this.players.keys());
|
|
821
|
+
// Iterate over the player state files
|
|
862
822
|
for (const file of playerFiles) {
|
|
823
|
+
// Get the guild ID from the file name
|
|
863
824
|
const guildId = path_1.default.basename(file, ".json");
|
|
825
|
+
// If the guild ID is not in the set of active guild IDs, delete the file
|
|
864
826
|
if (!activeGuildIds.has(guildId)) {
|
|
865
827
|
const filePath = path_1.default.join(playerStatesDir, file);
|
|
866
|
-
await promises_1.default.unlink(filePath);
|
|
828
|
+
await promises_1.default.unlink(filePath); // Delete the file asynchronously
|
|
867
829
|
this.emit(ManagerEventTypes.Debug, `[MANAGER] Deleting inactive player: ${guildId}`);
|
|
868
830
|
}
|
|
869
831
|
}
|
|
@@ -932,14 +894,6 @@ class Manager extends events_1.EventEmitter {
|
|
|
932
894
|
// If no node has a cumulative weight greater than or equal to the random number, return the node with the lowest load
|
|
933
895
|
return this.options.useNode === UseNodeOptions.LeastLoad ? this.leastLoadNode.first() : this.leastPlayersNode.first();
|
|
934
896
|
}
|
|
935
|
-
async getAllGuildIds() {
|
|
936
|
-
if (this._players instanceof collection_1.Collection) {
|
|
937
|
-
return Array.from(await this._players.keys());
|
|
938
|
-
}
|
|
939
|
-
else {
|
|
940
|
-
return await this._players.keys();
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
897
|
}
|
|
944
898
|
exports.Manager = Manager;
|
|
945
899
|
var StateStorageType;
|
|
@@ -1046,3 +1000,4 @@ var ManagerEventTypes;
|
|
|
1046
1000
|
ManagerEventTypes["ChapterStarted"] = "chapterStarted";
|
|
1047
1001
|
ManagerEventTypes["ChaptersLoaded"] = "chaptersLoaded";
|
|
1048
1002
|
})(ManagerEventTypes || (exports.ManagerEventTypes = ManagerEventTypes = {}));
|
|
1003
|
+
// PlayerStore WILL BE REMOVED IF YOU DONT FIND A USE FOR IT.
|
|
@@ -218,7 +218,7 @@ class Player {
|
|
|
218
218
|
/**
|
|
219
219
|
* Destroys the player and clears the queue.
|
|
220
220
|
* @param {boolean} disconnect - Whether to disconnect the player from the voice channel.
|
|
221
|
-
* @returns {Promise<
|
|
221
|
+
* @returns {Promise<boolean>} - Whether the player was successfully destroyed.
|
|
222
222
|
* @emits {PlayerDestroy} - Emitted when the player is destroyed.
|
|
223
223
|
* @emits {PlayerStateUpdate} - Emitted when the player state is updated.
|
|
224
224
|
*/
|
|
@@ -229,13 +229,16 @@ class Player {
|
|
|
229
229
|
await this.disconnect();
|
|
230
230
|
}
|
|
231
231
|
await this.node.rest.destroyPlayer(this.guildId);
|
|
232
|
-
this.queue.clear();
|
|
232
|
+
await this.queue.clear();
|
|
233
233
|
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, null, {
|
|
234
234
|
changeType: Manager_1.PlayerStateEventTypes.PlayerDestroy,
|
|
235
235
|
});
|
|
236
236
|
this.manager.emit(Manager_1.ManagerEventTypes.PlayerDestroy, this);
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
const deleted = this.manager.players.delete(this.guildId);
|
|
238
|
+
if (!deleted) {
|
|
239
|
+
console.warn(`Failed to delete player with guildId: ${this.guildId}`);
|
|
240
|
+
}
|
|
241
|
+
return deleted;
|
|
239
242
|
}
|
|
240
243
|
/**
|
|
241
244
|
* Sets the player voice channel.
|
package/dist/structures/Queue.js
CHANGED
|
@@ -330,5 +330,20 @@ class Queue extends Array {
|
|
|
330
330
|
async modifyAt(start, deleteCount = 0, ...items) {
|
|
331
331
|
return super.splice(start, deleteCount, ...items);
|
|
332
332
|
}
|
|
333
|
+
async mapAsync(callback) {
|
|
334
|
+
return this.map(callback);
|
|
335
|
+
}
|
|
336
|
+
async filterAsync(callback) {
|
|
337
|
+
return this.filter(callback);
|
|
338
|
+
}
|
|
339
|
+
async findAsync(callback) {
|
|
340
|
+
return this.find(callback);
|
|
341
|
+
}
|
|
342
|
+
async someAsync(callback) {
|
|
343
|
+
return this.some(callback);
|
|
344
|
+
}
|
|
345
|
+
async everyAsync(callback) {
|
|
346
|
+
return this.every(callback);
|
|
347
|
+
}
|
|
333
348
|
}
|
|
334
349
|
exports.Queue = Queue;
|
|
@@ -51,8 +51,11 @@ class RedisQueue {
|
|
|
51
51
|
}
|
|
52
52
|
async addPrevious(track) {
|
|
53
53
|
const tracks = Array.isArray(track) ? track : [track];
|
|
54
|
+
if (!tracks.length)
|
|
55
|
+
return;
|
|
54
56
|
const serialized = tracks.map(this.serialize);
|
|
55
|
-
|
|
57
|
+
if (!serialized.length)
|
|
58
|
+
return; // avoid lpush with no values
|
|
56
59
|
await this.redis.lpush(this.previousKey, ...serialized.reverse());
|
|
57
60
|
}
|
|
58
61
|
async clearPrevious() {
|
|
@@ -62,7 +65,7 @@ class RedisQueue {
|
|
|
62
65
|
const isArray = Array.isArray(track);
|
|
63
66
|
const tracks = isArray ? track : [track];
|
|
64
67
|
const serialized = tracks.map((t) => this.serialize(t));
|
|
65
|
-
const oldPlayer =
|
|
68
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
66
69
|
// If there's no current track, pop one from the list
|
|
67
70
|
if (!this.current) {
|
|
68
71
|
const current = serialized.shift();
|
|
@@ -83,11 +86,11 @@ class RedisQueue {
|
|
|
83
86
|
await this.redis.rpush(this.queueKey, ...serialized);
|
|
84
87
|
}
|
|
85
88
|
this.manager.emit(Manager_1.ManagerEventTypes.Debug, `[QUEUE] Added ${tracks.length} track(s) to queue`);
|
|
86
|
-
if (
|
|
89
|
+
if (this.manager.players.has(this.guildId) && this.manager.players.get(this.guildId).isAutoplay) {
|
|
87
90
|
if (!Array.isArray(track)) {
|
|
88
|
-
const botUser = (await
|
|
91
|
+
const botUser = (await this.manager.players.get(this.guildId).get("Internal_BotUser"));
|
|
89
92
|
if (botUser && botUser.id === track.requester.id) {
|
|
90
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
93
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
91
94
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
92
95
|
details: {
|
|
93
96
|
changeType: "autoPlayAdd",
|
|
@@ -98,7 +101,7 @@ class RedisQueue {
|
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
104
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
102
105
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
103
106
|
details: {
|
|
104
107
|
changeType: "add",
|
|
@@ -107,7 +110,7 @@ class RedisQueue {
|
|
|
107
110
|
});
|
|
108
111
|
}
|
|
109
112
|
async remove(startOrPos = 0, end) {
|
|
110
|
-
const oldPlayer =
|
|
113
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
111
114
|
const queue = await this.redis.lrange(this.queueKey, 0, -1);
|
|
112
115
|
let removed = [];
|
|
113
116
|
if (typeof end === "number") {
|
|
@@ -126,7 +129,7 @@ class RedisQueue {
|
|
|
126
129
|
}
|
|
127
130
|
const deserialized = removed.map(this.deserialize);
|
|
128
131
|
this.manager.emit(Manager_1.ManagerEventTypes.Debug, `[QUEUE] Removed ${removed.length} track(s) from position ${startOrPos}${end ? ` to ${end}` : ""}`);
|
|
129
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
132
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
130
133
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
131
134
|
details: {
|
|
132
135
|
changeType: "remove",
|
|
@@ -136,9 +139,9 @@ class RedisQueue {
|
|
|
136
139
|
return deserialized;
|
|
137
140
|
}
|
|
138
141
|
async clear() {
|
|
139
|
-
const oldPlayer =
|
|
142
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
140
143
|
await this.redis.del(this.queueKey);
|
|
141
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
144
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
142
145
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
143
146
|
details: {
|
|
144
147
|
changeType: "clear",
|
|
@@ -169,7 +172,7 @@ class RedisQueue {
|
|
|
169
172
|
return total;
|
|
170
173
|
}
|
|
171
174
|
async shuffle() {
|
|
172
|
-
const oldPlayer =
|
|
175
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
173
176
|
const queue = await this.redis.lrange(this.queueKey, 0, -1);
|
|
174
177
|
for (let i = queue.length - 1; i > 0; i--) {
|
|
175
178
|
const j = Math.floor(Math.random() * (i + 1));
|
|
@@ -179,14 +182,14 @@ class RedisQueue {
|
|
|
179
182
|
if (queue.length > 0) {
|
|
180
183
|
await this.redis.rpush(this.queueKey, ...queue);
|
|
181
184
|
}
|
|
182
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
185
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
183
186
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
184
187
|
details: { changeType: "shuffle" },
|
|
185
188
|
});
|
|
186
189
|
this.manager.emit(Manager_1.ManagerEventTypes.Debug, `[QUEUE] Shuffled the queue for: ${this.guildId}`);
|
|
187
190
|
}
|
|
188
191
|
async userBlockShuffle() {
|
|
189
|
-
const oldPlayer =
|
|
192
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
190
193
|
const rawTracks = await this.redis.lrange(this.queueKey, 0, -1);
|
|
191
194
|
const deserialized = rawTracks.map(this.deserialize);
|
|
192
195
|
const userMap = new Map();
|
|
@@ -206,14 +209,14 @@ class RedisQueue {
|
|
|
206
209
|
}
|
|
207
210
|
await this.redis.del(this.queueKey);
|
|
208
211
|
await this.redis.rpush(this.queueKey, ...shuffledQueue.map(this.serialize));
|
|
209
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
212
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
210
213
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
211
214
|
details: { changeType: "userBlock" },
|
|
212
215
|
});
|
|
213
216
|
this.manager.emit(Manager_1.ManagerEventTypes.Debug, `[QUEUE] userBlockShuffled the queue for: ${this.guildId}`);
|
|
214
217
|
}
|
|
215
218
|
async roundRobinShuffle() {
|
|
216
|
-
const oldPlayer =
|
|
219
|
+
const oldPlayer = this.manager.players.get(this.guildId) ? { ...this.manager.players.get(this.guildId) } : null;
|
|
217
220
|
const rawTracks = await this.redis.lrange(this.queueKey, 0, -1);
|
|
218
221
|
const deserialized = rawTracks.map(this.deserialize);
|
|
219
222
|
const userMap = new Map();
|
|
@@ -242,7 +245,7 @@ class RedisQueue {
|
|
|
242
245
|
}
|
|
243
246
|
await this.redis.del(this.queueKey);
|
|
244
247
|
await this.redis.rpush(this.queueKey, ...shuffledQueue.map(this.serialize));
|
|
245
|
-
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer,
|
|
248
|
+
this.manager.emit(Manager_1.ManagerEventTypes.PlayerStateUpdate, oldPlayer, this.manager.players.get(this.guildId), {
|
|
246
249
|
changeType: Manager_1.PlayerStateEventTypes.QueueChange,
|
|
247
250
|
details: { changeType: "roundRobin" },
|
|
248
251
|
});
|
|
@@ -274,5 +277,25 @@ class RedisQueue {
|
|
|
274
277
|
}
|
|
275
278
|
return removed.map(this.deserialize);
|
|
276
279
|
}
|
|
280
|
+
async mapAsync(callback) {
|
|
281
|
+
const tracks = await this.getTracks(); // same as lrange + deserialize
|
|
282
|
+
return tracks.map(callback);
|
|
283
|
+
}
|
|
284
|
+
async filterAsync(callback) {
|
|
285
|
+
const tracks = await this.getTracks();
|
|
286
|
+
return tracks.filter(callback);
|
|
287
|
+
}
|
|
288
|
+
async findAsync(callback) {
|
|
289
|
+
const tracks = await this.getTracks();
|
|
290
|
+
return tracks.find(callback);
|
|
291
|
+
}
|
|
292
|
+
async someAsync(callback) {
|
|
293
|
+
const tracks = await this.getTracks();
|
|
294
|
+
return tracks.some(callback);
|
|
295
|
+
}
|
|
296
|
+
async everyAsync(callback) {
|
|
297
|
+
const tracks = await this.getTracks();
|
|
298
|
+
return tracks.every(callback);
|
|
299
|
+
}
|
|
277
300
|
}
|
|
278
301
|
exports.RedisQueue = RedisQueue;
|