magmastream 2.9.0-dev.40 → 2.9.0-dev.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -965,10 +965,10 @@ interface NodeOptions {
965
965
  * @default false
966
966
  */
967
967
  enableSessionResumeOption?: boolean;
968
- /** The time the lavalink server will wait before it removes the player.
969
- * @default 1000
968
+ /** The time in seconds the lavalink server will wait before it removes the player.
969
+ * @default 60
970
970
  */
971
- sessionTimeoutMs?: number;
971
+ sessionTimeoutSeconds?: number;
972
972
  /** The timeout used for api calls.
973
973
  * @default 10000
974
974
  */
@@ -981,6 +981,10 @@ interface NodeOptions {
981
981
  * @default false
982
982
  */
983
983
  isNodeLink?: boolean;
984
+ /** Whether the node is a backup node.
985
+ * @default false
986
+ */
987
+ isBackup?: boolean;
984
988
  }
985
989
  /**
986
990
  * Discord Packet
@@ -70,7 +70,7 @@ class Manager extends events_1.EventEmitter {
70
70
  password: "Try BlackForHosting",
71
71
  useSSL: true,
72
72
  enableSessionResumeOption: false,
73
- sessionTimeoutMs: 1000,
73
+ sessionTimeoutSeconds: 1000,
74
74
  nodePriority: 69,
75
75
  },
76
76
  ],
@@ -1127,30 +1127,30 @@ class Manager extends events_1.EventEmitter {
1127
1127
  switch (this.options.stateStorage.type) {
1128
1128
  case Enums_1.StateStorageType.JSON:
1129
1129
  {
1130
- const playersStoreDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playersStore");
1131
- const playersDataDir = this.options.stateStorage?.jsonConfig?.path ?? path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
1130
+ const playerStoreDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playerStore");
1131
+ const playerDataDir = this.options.stateStorage?.jsonConfig?.path ?? path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
1132
1132
  try {
1133
- await promises_1.default.mkdir(playersStoreDir, { recursive: true });
1134
- await promises_1.default.mkdir(playersDataDir, { recursive: true });
1133
+ await promises_1.default.mkdir(playerStoreDir, { recursive: true });
1134
+ await promises_1.default.mkdir(playerDataDir, { recursive: true });
1135
1135
  const activeGuildIds = new Set(this.players.keys());
1136
- // Clean up playersStore/*.json
1137
- const playerStateFiles = await promises_1.default.readdir(playersStoreDir);
1136
+ // Clean up playerStore/*.json
1137
+ const playerStateFiles = await promises_1.default.readdir(playerStoreDir);
1138
1138
  for (const file of playerStateFiles) {
1139
1139
  const guildId = path_1.default.basename(file, ".json");
1140
1140
  if (!activeGuildIds.has(guildId)) {
1141
- const filePath = path_1.default.join(playersStoreDir, file);
1141
+ const filePath = path_1.default.join(playerStoreDir, file);
1142
1142
  await promises_1.default.unlink(filePath);
1143
1143
  this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted inactive player state: ${guildId}`);
1144
1144
  }
1145
1145
  }
1146
1146
  // Clean up players/<guildId>/ folders
1147
- const guildDirs = await promises_1.default.readdir(playersDataDir, { withFileTypes: true });
1147
+ const guildDirs = await promises_1.default.readdir(playerDataDir, { withFileTypes: true });
1148
1148
  for (const dirent of guildDirs) {
1149
1149
  if (!dirent.isDirectory())
1150
1150
  continue;
1151
1151
  const guildId = dirent.name;
1152
1152
  if (!activeGuildIds.has(guildId)) {
1153
- const guildPath = path_1.default.join(playersDataDir, guildId);
1153
+ const guildPath = path_1.default.join(playerDataDir, guildId);
1154
1154
  await promises_1.default.rm(guildPath, { recursive: true, force: true });
1155
1155
  this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Deleted inactive player data folder: ${guildId}`);
1156
1156
  }
@@ -1202,7 +1202,7 @@ class Manager extends events_1.EventEmitter {
1202
1202
  switch (this.options.stateStorage.type) {
1203
1203
  case Enums_1.StateStorageType.JSON:
1204
1204
  {
1205
- const playersStoreDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playersStore");
1205
+ const playersStoreDir = path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "playerStore");
1206
1206
  const playersDataDir = this.options.stateStorage?.jsonConfig?.path ?? path_1.default.join(process.cwd(), "magmastream", "dist", "sessionData", "players");
1207
1207
  try {
1208
1208
  if (!this.players.has(guildId)) {
@@ -1344,7 +1344,7 @@ class Manager extends events_1.EventEmitter {
1344
1344
  */
1345
1345
  get leastLoadNode() {
1346
1346
  return this.nodes
1347
- .filter((node) => node.connected)
1347
+ .filter((node) => node.connected && !node.options.isBackup)
1348
1348
  .sort((a, b) => {
1349
1349
  const aload = a.stats.cpu ? (a.stats.cpu.lavalinkLoad / a.stats.cpu.cores) * 100 : 0;
1350
1350
  const bload = b.stats.cpu ? (b.stats.cpu.lavalinkLoad / b.stats.cpu.cores) * 100 : 0;
@@ -1359,9 +1359,7 @@ class Manager extends events_1.EventEmitter {
1359
1359
  * @returns {Collection<string, Node>} A collection of nodes sorted by player count.
1360
1360
  */
1361
1361
  get leastPlayersNode() {
1362
- return this.nodes
1363
- .filter((node) => node.connected) // Filter out nodes that are not connected
1364
- .sort((a, b) => a.stats.players - b.stats.players); // Sort by the number of players
1362
+ return this.nodes.filter((node) => node.connected && !node.options.isBackup).sort((a, b) => a.stats.players - b.stats.players);
1365
1363
  }
1366
1364
  /**
1367
1365
  * Returns a node based on priority.
@@ -56,10 +56,11 @@ class Node {
56
56
  maxRetryAttempts: options.maxRetryAttempts ?? 30,
57
57
  retryDelayMs: options.retryDelayMs ?? 60000,
58
58
  enableSessionResumeOption: options.enableSessionResumeOption ?? false,
59
- sessionTimeoutMs: options.sessionTimeoutMs ?? 1000,
59
+ sessionTimeoutSeconds: options.sessionTimeoutSeconds ?? 60,
60
60
  apiRequestTimeoutMs: options.apiRequestTimeoutMs ?? 10000,
61
61
  nodePriority: options.nodePriority ?? 0,
62
62
  isNodeLink: options.isNodeLink ?? false,
63
+ isBackup: options.isBackup ?? false,
63
64
  };
64
65
  if (this.options.useSSL) {
65
66
  this.options.port = 443;
@@ -373,6 +374,10 @@ class Node {
373
374
  };
374
375
  this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Connected node: ${JSON.stringify(debugInfo)}`);
375
376
  this.manager.emit(Enums_1.ManagerEventTypes.NodeConnect, this);
377
+ const playersOnBackupNode = this.manager.players.filter((p) => p.node.options.isBackup);
378
+ if (playersOnBackupNode.size) {
379
+ Promise.all(Array.from(playersOnBackupNode.values(), (player) => player.moveNode(this.options.identifier)));
380
+ }
376
381
  }
377
382
  /**
378
383
  * Handles the "close" event emitted by the WebSocket connection.
@@ -401,6 +406,13 @@ class Node {
401
406
  await Promise.all(Array.from(players.values(), (player) => player.autoMoveNode()));
402
407
  }
403
408
  }
409
+ else {
410
+ const backUpNodes = this.manager.nodes.filter((node) => node.options.isBackup && node.connected);
411
+ const backupNode = backUpNodes.first();
412
+ if (backupNode) {
413
+ await Promise.all(Array.from(this.manager.players.values(), (player) => player.moveNode(backupNode.options.identifier)));
414
+ }
415
+ }
404
416
  if (code !== 1000 || reason !== "destroy")
405
417
  await this.reconnect();
406
418
  }
@@ -474,7 +486,7 @@ class Node {
474
486
  if (this.options.enableSessionResumeOption) {
475
487
  await this.rest.patch(`/v4/sessions/${this.sessionId}`, {
476
488
  resuming: this.options.enableSessionResumeOption,
477
- timeout: this.options.sessionTimeoutMs,
489
+ timeout: this.options.sessionTimeoutSeconds,
478
490
  });
479
491
  }
480
492
  break;
@@ -12,7 +12,7 @@ function nodeCheck(options) {
12
12
  throw new TypeError("NodeOptions must not be empty.");
13
13
  // Validate the host option
14
14
  // The host option must be present and be a non-empty string.
15
- const { host, identifier, password, port, enableSessionResumeOption, sessionTimeoutMs, maxRetryAttempts, retryDelayMs, useSSL, nodePriority } = options;
15
+ const { host, identifier, password, port, enableSessionResumeOption, sessionTimeoutSeconds, maxRetryAttempts, retryDelayMs, useSSL, nodePriority } = options;
16
16
  if (typeof host !== "string" || !/.+/.test(host)) {
17
17
  throw new TypeError('Node option "host" must be present and be a non-empty string.');
18
18
  }
@@ -36,10 +36,10 @@ function nodeCheck(options) {
36
36
  if (typeof enableSessionResumeOption !== "undefined" && typeof enableSessionResumeOption !== "boolean") {
37
37
  throw new TypeError('Node option "enableSessionResumeOption" must be a boolean.');
38
38
  }
39
- // Validate the sessionTimeoutMs option
40
- // The sessionTimeoutMs option must be a number or undefined.
41
- if (typeof sessionTimeoutMs !== "undefined" && typeof sessionTimeoutMs !== "number") {
42
- throw new TypeError('Node option "sessionTimeoutMs" must be a number.');
39
+ // Validate the sessionTimeoutSeconds option
40
+ // The sessionTimeoutSeconds option must be a number or undefined.
41
+ if (typeof sessionTimeoutSeconds !== "undefined" && typeof sessionTimeoutSeconds !== "number") {
42
+ throw new TypeError('Node option "sessionTimeoutSeconds" must be a number.');
43
43
  }
44
44
  // Validate the maxRetryAttempts option
45
45
  // The maxRetryAttempts option must be a number or undefined.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magmastream",
3
- "version": "2.9.0-dev.40",
3
+ "version": "2.9.0-dev.41",
4
4
  "description": "A user-friendly Lavalink client designed for NodeJS.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",