magmastream 2.9.3-dev.17 → 2.9.3-dev.19
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 +31 -12
- package/dist/statestorage/RedisQueue.js +1 -5
- package/dist/structures/Manager.js +5 -15
- package/dist/structures/Node.js +89 -118
- package/dist/structures/Player.js +1 -1
- package/dist/structures/Utils.js +12 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1308,11 +1308,7 @@ interface LavaPlayer {
|
|
|
1308
1308
|
connected: boolean;
|
|
1309
1309
|
ping: number;
|
|
1310
1310
|
};
|
|
1311
|
-
voice:
|
|
1312
|
-
token: string;
|
|
1313
|
-
endpoint: string;
|
|
1314
|
-
sessionId: string;
|
|
1315
|
-
};
|
|
1311
|
+
voice: LavalinkVoiceStateResponse;
|
|
1316
1312
|
filters: Record<string, unknown>;
|
|
1317
1313
|
}
|
|
1318
1314
|
/**
|
|
@@ -1917,16 +1913,29 @@ interface RestPlayOptions {
|
|
|
1917
1913
|
/** The audio effects. */
|
|
1918
1914
|
filters?: object;
|
|
1919
1915
|
/** voice payload. */
|
|
1920
|
-
voice?:
|
|
1921
|
-
token: string;
|
|
1922
|
-
sessionId: string;
|
|
1923
|
-
endpoint: string;
|
|
1924
|
-
channelId: string;
|
|
1925
|
-
};
|
|
1916
|
+
voice?: LavalinkVoiceStateUpdate;
|
|
1926
1917
|
/** Whether to not replace the track if a play payload is sent. */
|
|
1927
1918
|
noReplace?: boolean;
|
|
1928
1919
|
};
|
|
1929
1920
|
}
|
|
1921
|
+
/**
|
|
1922
|
+
* Lavalink voice state response
|
|
1923
|
+
*/
|
|
1924
|
+
type LavalinkVoiceStateResponse = {
|
|
1925
|
+
token: string;
|
|
1926
|
+
endpoint: string;
|
|
1927
|
+
sessionId: string;
|
|
1928
|
+
channelId: string | null;
|
|
1929
|
+
};
|
|
1930
|
+
/**
|
|
1931
|
+
* Lavalink voice state update
|
|
1932
|
+
*/
|
|
1933
|
+
type LavalinkVoiceStateUpdate = {
|
|
1934
|
+
token: string;
|
|
1935
|
+
endpoint: string;
|
|
1936
|
+
sessionId: string;
|
|
1937
|
+
channelId: string;
|
|
1938
|
+
};
|
|
1930
1939
|
/**
|
|
1931
1940
|
* ManagerInitOptions interface
|
|
1932
1941
|
*/
|
|
@@ -2539,6 +2548,10 @@ declare class Node {
|
|
|
2539
2548
|
get connected(): boolean;
|
|
2540
2549
|
/** Returns the full address for this node, including the host and port. */
|
|
2541
2550
|
get address(): string;
|
|
2551
|
+
private getCompositeKey;
|
|
2552
|
+
private getRedisSessionIdsKey;
|
|
2553
|
+
private getNodeSessionsDir;
|
|
2554
|
+
private getNodeSessionPath;
|
|
2542
2555
|
/**
|
|
2543
2556
|
* Creates the sessionIds.json file if it doesn't exist. This file is used to
|
|
2544
2557
|
* store the session IDs for each node. The session IDs are used to identify
|
|
@@ -2566,6 +2579,8 @@ declare class Node {
|
|
|
2566
2579
|
* be used with the same node identifier.
|
|
2567
2580
|
*/
|
|
2568
2581
|
updateSessionId(): Promise<void>;
|
|
2582
|
+
private updateSessionIdFile;
|
|
2583
|
+
private updateSessionIdRedis;
|
|
2569
2584
|
/**
|
|
2570
2585
|
* Connects to the Node.
|
|
2571
2586
|
*
|
|
@@ -3626,6 +3641,10 @@ declare abstract class PlayerUtils {
|
|
|
3626
3641
|
* Gets the path to the player's previous tracks file.
|
|
3627
3642
|
*/
|
|
3628
3643
|
static getPlayerPreviousPath(guildId: string): string;
|
|
3644
|
+
/**
|
|
3645
|
+
* Gets the Redis key for player storage.
|
|
3646
|
+
*/
|
|
3647
|
+
static getRedisKey(): string;
|
|
3629
3648
|
}
|
|
3630
3649
|
/** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
|
|
3631
3650
|
declare abstract class Structure {
|
|
@@ -3736,4 +3755,4 @@ declare class SeyfertManager extends Manager {
|
|
|
3736
3755
|
}
|
|
3737
3756
|
|
|
3738
3757
|
export { AutoPlayPlatform, AutoPlayUtils, AvailableFilters, DiscordJSManager, DiscordenoManager, ErisManager, Filters, JSONUtils, JsonQueue, LoadTypes, MagmaStreamError, MagmaStreamErrorCode, MagmaStreamErrorNumbers, Manager, ManagerEventTypes, MemoryQueue, Node, OceanicManager, Player, PlayerStateEventTypes, PlayerUtils, Plugin, RedisQueue, Rest, SearchPlatform, SeverityTypes, SeyfertManager, SponsorBlockSegment, StateStorageType, StateTypes, Structure, TrackEndReasonTypes, TrackPartial, TrackSourceTypes, TrackUtils, UseNodeOptions };
|
|
3739
|
-
export type { AlbumSearchResult, AnyMessage, AnyUser, ArtistSearchResult, CPUStats, DiscordPacket, DistortionOptions, EndSpeakingEventVoiceReceiver, EndSpeakingEventVoiceReceiverData, EqualizerBand, ErrorOrEmptySearchResult, Exception, Extendable, FrameStats, IQueue, JsonConfig, KaraokeOptions, LavaPlayer, LavalinkInfo, LavalinkResponse, LoadType, Lyrics, LyricsEvent, LyricsEventType, LyricsFoundEvent, LyricsLine, LyricsLineEvent, LyricsNotFoundEvent, ManagerEvents, ManagerInitOptions, ManagerOptions, MemoryStats, NodeLinkGetLyrics, NodeLinkGetLyricsEmpty, NodeLinkGetLyricsError, NodeLinkGetLyricsMultiple, NodeLinkGetLyricsSingle, NodeMessage, NodeOptions, NodeStats, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerStateUpdateEvent, PlayerUpdateVoiceState, PlaylistData, PlaylistInfoData, PlaylistRawData, PlaylistSearchResult, PodcastSearchResult, PortableMessage, PortableUser, RedisConfig, RestPlayOptions, ReverbOptions, RotationOptions, SearchQuery, SearchResult, SearchSearchResult, Severity, ShortSearchResult, ShowSearchResult, Sizes, SponsorBlockChapterStarted, SponsorBlockChaptersLoaded, SponsorBlockSegmentEventType, SponsorBlockSegmentEvents, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, StartSpeakingEventVoiceReceiver, StartSpeakingEventVoiceReceiverData, StateStorageOptions, StationSearchResult, TimescaleOptions, Track, TrackData, TrackDataInfo, TrackEndEvent, TrackEndReason, TrackExceptionEvent, TrackPluginInfo, TrackSearchResult, TrackSourceName, TrackStartEvent, TrackStuckEvent, UseNodeOption, VibratoOptions, VoicePacket, VoiceReceiverEvent, VoiceServer, VoiceServerUpdate, VoiceState, WebSocketClosedEvent };
|
|
3758
|
+
export type { AlbumSearchResult, AnyMessage, AnyUser, ArtistSearchResult, CPUStats, DiscordPacket, DistortionOptions, EndSpeakingEventVoiceReceiver, EndSpeakingEventVoiceReceiverData, EqualizerBand, ErrorOrEmptySearchResult, Exception, Extendable, FrameStats, IQueue, JsonConfig, KaraokeOptions, LavaPlayer, LavalinkInfo, LavalinkResponse, LavalinkVoiceStateResponse, LavalinkVoiceStateUpdate, LoadType, Lyrics, LyricsEvent, LyricsEventType, LyricsFoundEvent, LyricsLine, LyricsLineEvent, LyricsNotFoundEvent, ManagerEvents, ManagerInitOptions, ManagerOptions, MemoryStats, NodeLinkGetLyrics, NodeLinkGetLyricsEmpty, NodeLinkGetLyricsError, NodeLinkGetLyricsMultiple, NodeLinkGetLyricsSingle, NodeMessage, NodeOptions, NodeStats, PlayOptions, PlayerEvent, PlayerEventType, PlayerEvents, PlayerOptions, PlayerStateUpdateEvent, PlayerUpdateVoiceState, PlaylistData, PlaylistInfoData, PlaylistRawData, PlaylistSearchResult, PodcastSearchResult, PortableMessage, PortableUser, RedisConfig, RestPlayOptions, ReverbOptions, RotationOptions, SearchQuery, SearchResult, SearchSearchResult, Severity, ShortSearchResult, ShowSearchResult, Sizes, SponsorBlockChapterStarted, SponsorBlockChaptersLoaded, SponsorBlockSegmentEventType, SponsorBlockSegmentEvents, SponsorBlockSegmentSkipped, SponsorBlockSegmentsLoaded, StartSpeakingEventVoiceReceiver, StartSpeakingEventVoiceReceiverData, StateStorageOptions, StationSearchResult, TimescaleOptions, Track, TrackData, TrackDataInfo, TrackEndEvent, TrackEndReason, TrackExceptionEvent, TrackPluginInfo, TrackSearchResult, TrackSourceName, TrackStartEvent, TrackStuckEvent, UseNodeOption, VibratoOptions, VoicePacket, VoiceReceiverEvent, VoiceServer, VoiceServerUpdate, VoiceState, WebSocketClosedEvent };
|
|
@@ -31,11 +31,7 @@ class RedisQueue {
|
|
|
31
31
|
this.guildId = guildId;
|
|
32
32
|
this.manager = manager;
|
|
33
33
|
this.redis = manager.redis;
|
|
34
|
-
|
|
35
|
-
let clean = typeof rawPrefix === "string" ? rawPrefix.trim() : "";
|
|
36
|
-
if (!clean.endsWith(":"))
|
|
37
|
-
clean = clean || "magmastream";
|
|
38
|
-
this.redisPrefix = `${clean}:`;
|
|
34
|
+
this.redisPrefix = Utils_1.PlayerUtils.getRedisKey();
|
|
39
35
|
}
|
|
40
36
|
// #region Public
|
|
41
37
|
/**
|
|
@@ -471,9 +471,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
471
471
|
case Enums_1.StateStorageType.Redis:
|
|
472
472
|
{
|
|
473
473
|
try {
|
|
474
|
-
const redisKey = `${
|
|
475
|
-
? this.options.stateStorage.redisConfig.prefix
|
|
476
|
-
: (this.options.stateStorage.redisConfig.prefix ?? "magmastream:")}playerstore:${guildId}`;
|
|
474
|
+
const redisKey = `${Utils_1.PlayerUtils.getRedisKey()}playerstore:${guildId}`;
|
|
477
475
|
await this.redis.set(redisKey, JSON.stringify(serializedPlayer));
|
|
478
476
|
this.emit(Enums_1.ManagerEventTypes.Debug, `[MANAGER] Player state saved to Redis: ${guildId}`);
|
|
479
477
|
}
|
|
@@ -726,9 +724,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
726
724
|
{
|
|
727
725
|
try {
|
|
728
726
|
// Get all keys matching our pattern
|
|
729
|
-
const redisKeyPattern = `${
|
|
730
|
-
? this.options.stateStorage.redisConfig.prefix
|
|
731
|
-
: (this.options.stateStorage.redisConfig.prefix ?? "magmastream:")}playerstore:*`;
|
|
727
|
+
const redisKeyPattern = `${Utils_1.PlayerUtils.getRedisKey()}playerstore:*`;
|
|
732
728
|
const keys = await this.redis.keys(redisKeyPattern);
|
|
733
729
|
for (const key of keys) {
|
|
734
730
|
try {
|
|
@@ -1175,9 +1171,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
1175
1171
|
break;
|
|
1176
1172
|
case Enums_1.StateStorageType.Redis:
|
|
1177
1173
|
{
|
|
1178
|
-
const prefix =
|
|
1179
|
-
? this.options.stateStorage.redisConfig.prefix
|
|
1180
|
-
: (this.options.stateStorage.redisConfig.prefix ?? "magmastream:");
|
|
1174
|
+
const prefix = Utils_1.PlayerUtils.getRedisKey();
|
|
1181
1175
|
const pattern = `${prefix}queue:*:current`;
|
|
1182
1176
|
try {
|
|
1183
1177
|
const stream = this.redis.scanStream({
|
|
@@ -1250,9 +1244,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
1250
1244
|
{
|
|
1251
1245
|
try {
|
|
1252
1246
|
if (!player) {
|
|
1253
|
-
const prefix =
|
|
1254
|
-
? this.options.stateStorage.redisConfig.prefix
|
|
1255
|
-
: `${this.options.stateStorage.redisConfig.prefix ?? "magmastream"}:`;
|
|
1247
|
+
const prefix = Utils_1.PlayerUtils.getRedisKey();
|
|
1256
1248
|
const keysToDelete = [
|
|
1257
1249
|
`${prefix}playerstore:${guildId}`,
|
|
1258
1250
|
`${prefix}queue:${guildId}:tracks`,
|
|
@@ -1360,9 +1352,7 @@ class Manager extends events_1.EventEmitter {
|
|
|
1360
1352
|
break;
|
|
1361
1353
|
}
|
|
1362
1354
|
case Enums_1.StateStorageType.Redis: {
|
|
1363
|
-
const prefix =
|
|
1364
|
-
? this.options.stateStorage.redisConfig.prefix
|
|
1365
|
-
: (this.options.stateStorage.redisConfig.prefix ?? "magmastream:");
|
|
1355
|
+
const prefix = Utils_1.PlayerUtils.getRedisKey();
|
|
1366
1356
|
const patterns = [`${prefix}playerstore:*`, `${prefix}queue:*`];
|
|
1367
1357
|
try {
|
|
1368
1358
|
for (const pattern of patterns) {
|
package/dist/structures/Node.js
CHANGED
|
@@ -125,6 +125,19 @@ class Node {
|
|
|
125
125
|
get address() {
|
|
126
126
|
return `${this.options.host}:${this.options.port}`;
|
|
127
127
|
}
|
|
128
|
+
getCompositeKey() {
|
|
129
|
+
return `${this.options.identifier}::${this.manager.options.clusterId}`;
|
|
130
|
+
}
|
|
131
|
+
getRedisSessionIdsKey() {
|
|
132
|
+
return `${this.redisPrefix}node:sessionIds`;
|
|
133
|
+
}
|
|
134
|
+
getNodeSessionsDir() {
|
|
135
|
+
return path_1.default.join(process.cwd(), "magmastream", "sessionData", "cluster", String(this.manager.options.clusterId), "nodeSessions");
|
|
136
|
+
}
|
|
137
|
+
getNodeSessionPath() {
|
|
138
|
+
const safeId = String(this.options.identifier).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
139
|
+
return path_1.default.join(this.getNodeSessionsDir(), `${safeId}.txt`);
|
|
140
|
+
}
|
|
128
141
|
/**
|
|
129
142
|
* Creates the sessionIds.json file if it doesn't exist. This file is used to
|
|
130
143
|
* store the session IDs for each node. The session IDs are used to identify
|
|
@@ -148,49 +161,43 @@ class Node {
|
|
|
148
161
|
switch (this.manager.options.stateStorage.type) {
|
|
149
162
|
case Enums_1.StateStorageType.Memory:
|
|
150
163
|
case Enums_1.StateStorageType.JSON: {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
164
|
+
const dir = this.getNodeSessionsDir();
|
|
165
|
+
const filePath = this.getNodeSessionPath();
|
|
166
|
+
if (!fs_1.default.existsSync(dir))
|
|
167
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
168
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
169
|
+
this.sessionId = null;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const raw = fs_1.default.readFileSync(filePath, "utf-8").trim();
|
|
174
|
+
this.sessionId = raw.length ? raw : null;
|
|
175
|
+
if (this.sessionId)
|
|
176
|
+
this.sessionIdsMap.set(this.getCompositeKey(), this.sessionId);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
this.sessionId = null;
|
|
159
180
|
}
|
|
160
181
|
break;
|
|
161
182
|
}
|
|
162
|
-
case Enums_1.StateStorageType.Redis:
|
|
163
|
-
const key =
|
|
164
|
-
this.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
message: "Invalid sessionIds data type from Redis.",
|
|
173
|
-
context: { sessionIds },
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
this.sessionIdsMap = new Map(Object.entries(sessionIds));
|
|
177
|
-
const compositeKey = `${this.options.identifier}::${this.manager.options.clusterId}`;
|
|
178
|
-
if (this.sessionIdsMap.has(compositeKey)) {
|
|
179
|
-
this.sessionId = this.sessionIdsMap.get(compositeKey) || null;
|
|
180
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Restored sessionId for ${compositeKey}: ${this.sessionId}`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Failed to parse Redis sessionIds: ${err.message}`);
|
|
185
|
-
this.sessionIdsMap = new Map();
|
|
183
|
+
case Enums_1.StateStorageType.Redis: {
|
|
184
|
+
const key = this.getRedisSessionIdsKey();
|
|
185
|
+
const compositeKey = this.getCompositeKey();
|
|
186
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Loading sessionId from Redis hash: ${key} field: ${compositeKey}`);
|
|
187
|
+
try {
|
|
188
|
+
const sid = await this.manager.redis.hget(key, compositeKey);
|
|
189
|
+
this.sessionId = sid ?? null;
|
|
190
|
+
if (this.sessionId) {
|
|
191
|
+
this.sessionIdsMap.set(compositeKey, this.sessionId);
|
|
192
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Restored sessionId for ${compositeKey}: ${this.sessionId}`);
|
|
186
193
|
}
|
|
187
194
|
}
|
|
188
|
-
|
|
189
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE]
|
|
190
|
-
|
|
191
|
-
this.sessionIdsMap = new Map();
|
|
195
|
+
catch (err) {
|
|
196
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Failed to load sessionId from Redis hash: ${err.message}`);
|
|
197
|
+
this.sessionId = null;
|
|
192
198
|
}
|
|
193
199
|
break;
|
|
200
|
+
}
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
/**
|
|
@@ -207,85 +214,54 @@ class Node {
|
|
|
207
214
|
async updateSessionId() {
|
|
208
215
|
switch (this.manager.options.stateStorage.type) {
|
|
209
216
|
case Enums_1.StateStorageType.Memory:
|
|
210
|
-
case Enums_1.StateStorageType.JSON:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
this.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
fs_1.default.writeFileSync(tmpPath, Utils_1.JSONUtils.safe(fileData, 2), "utf-8");
|
|
232
|
-
fs_1.default.renameSync(tmpPath, filePath);
|
|
233
|
-
this.sessionIdsMap = new Map(Object.entries(fileData));
|
|
234
|
-
updated = true;
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
retries--;
|
|
238
|
-
if (retries === 0) {
|
|
239
|
-
throw new MagmastreamError_1.MagmaStreamError({
|
|
240
|
-
code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
|
|
241
|
-
message: `Failed to update sessionIds after retries.`,
|
|
242
|
-
cause: err instanceof Error ? err : undefined,
|
|
243
|
-
context: { filePath, compositeKey, storage: "file" },
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
break;
|
|
217
|
+
case Enums_1.StateStorageType.JSON:
|
|
218
|
+
return this.updateSessionIdFile();
|
|
219
|
+
case Enums_1.StateStorageType.Redis:
|
|
220
|
+
return this.updateSessionIdRedis();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async updateSessionIdFile() {
|
|
224
|
+
const dir = this.getNodeSessionsDir();
|
|
225
|
+
const filePath = this.getNodeSessionPath();
|
|
226
|
+
const tmpPath = `${filePath}.tmp`;
|
|
227
|
+
if (!fs_1.default.existsSync(dir))
|
|
228
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
229
|
+
if (this.sessionId) {
|
|
230
|
+
fs_1.default.writeFileSync(tmpPath, this.sessionId, "utf-8");
|
|
231
|
+
fs_1.default.renameSync(tmpPath, filePath);
|
|
232
|
+
this.sessionIdsMap.set(this.getCompositeKey(), this.sessionId);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
try {
|
|
236
|
+
if (fs_1.default.existsSync(filePath))
|
|
237
|
+
fs_1.default.unlinkSync(filePath);
|
|
250
238
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
catch (err) {
|
|
270
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Corrupted Redis sessionIds, reinitializing: ${err.message}`);
|
|
271
|
-
sessionIds = {};
|
|
272
|
-
}
|
|
273
|
-
try {
|
|
274
|
-
sessionIds[compositeKey] = this.sessionId;
|
|
275
|
-
this.sessionIdsMap = new Map(Object.entries(sessionIds));
|
|
276
|
-
await this.manager.redis.set(key, Utils_1.JSONUtils.safe(sessionIds));
|
|
277
|
-
}
|
|
278
|
-
catch (err) {
|
|
279
|
-
throw new MagmastreamError_1.MagmaStreamError({
|
|
280
|
-
code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
|
|
281
|
-
message: `Failed to update sessionIds in Redis.`,
|
|
282
|
-
cause: err instanceof Error ? err : undefined,
|
|
283
|
-
context: { key, compositeKey, storage: "redis" },
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
break;
|
|
239
|
+
catch { }
|
|
240
|
+
this.sessionIdsMap.delete(this.getCompositeKey());
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async updateSessionIdRedis() {
|
|
244
|
+
const key = this.getRedisSessionIdsKey();
|
|
245
|
+
const compositeKey = this.getCompositeKey();
|
|
246
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Updating sessionId in Redis hash: ${key} field: ${compositeKey}`);
|
|
247
|
+
try {
|
|
248
|
+
if (this.sessionId) {
|
|
249
|
+
await this.manager.redis.hset(key, compositeKey, this.sessionId);
|
|
250
|
+
this.sessionIdsMap.set(compositeKey, this.sessionId);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
await this.manager.redis.hdel(key, compositeKey);
|
|
254
|
+
this.sessionIdsMap.delete(compositeKey);
|
|
287
255
|
}
|
|
288
256
|
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
259
|
+
code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
|
|
260
|
+
message: "Failed to update sessionId in Redis hash.",
|
|
261
|
+
cause: err instanceof Error ? err : undefined,
|
|
262
|
+
context: { key, compositeKey, storage: "redis-hash" },
|
|
263
|
+
});
|
|
264
|
+
}
|
|
289
265
|
}
|
|
290
266
|
/**
|
|
291
267
|
* Connects to the Node.
|
|
@@ -305,12 +281,7 @@ class Node {
|
|
|
305
281
|
"User-Id": this.manager.options.clientId,
|
|
306
282
|
"Client-Name": this.manager.options.clientName,
|
|
307
283
|
};
|
|
308
|
-
|
|
309
|
-
if (this.sessionId) {
|
|
310
|
-
headers["Session-Id"] = this.sessionId;
|
|
311
|
-
}
|
|
312
|
-
else if (this.options.enableSessionResumeOption && this.sessionIdsMap.has(compositeKey)) {
|
|
313
|
-
this.sessionId = this.sessionIdsMap.get(compositeKey) || null;
|
|
284
|
+
if (typeof this.sessionId === "string" && this.sessionId.length > 0) {
|
|
314
285
|
headers["Session-Id"] = this.sessionId;
|
|
315
286
|
}
|
|
316
287
|
this.socket = new ws_1.default(`ws${this.options.useSSL ? "s" : ""}://${this.address}/v4/websocket`, { headers });
|
|
@@ -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 = {
|
package/dist/structures/Utils.js
CHANGED
|
@@ -737,7 +737,7 @@ class PlayerUtils {
|
|
|
737
737
|
* Gets the base directory for player data.
|
|
738
738
|
*/
|
|
739
739
|
static getPlayersBaseDir() {
|
|
740
|
-
return path_1.default.join(process.cwd(), "magmastream", "sessionData", "players");
|
|
740
|
+
return path_1.default.join(process.cwd(), "magmastream", "sessionData", "cluster", String(this.manager.options.clusterId), "players");
|
|
741
741
|
}
|
|
742
742
|
/**
|
|
743
743
|
* Gets the path to the player's directory.
|
|
@@ -769,6 +769,17 @@ class PlayerUtils {
|
|
|
769
769
|
static getPlayerPreviousPath(guildId) {
|
|
770
770
|
return path_1.default.join(this.getGuildDir(guildId), "previous.json");
|
|
771
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Gets the Redis key for player storage.
|
|
774
|
+
*/
|
|
775
|
+
static getRedisKey() {
|
|
776
|
+
const cfg = this.manager.options.stateStorage.redisConfig;
|
|
777
|
+
// Default prefix
|
|
778
|
+
let prefix = (cfg.prefix ?? "magmastream:").trim();
|
|
779
|
+
prefix = prefix.replace(/:+$/g, "") + ":";
|
|
780
|
+
const clusterId = String(this.manager.options.clusterId ?? 0).trim() || "0";
|
|
781
|
+
return `${prefix}cluster:${clusterId}:`;
|
|
782
|
+
}
|
|
772
783
|
}
|
|
773
784
|
exports.PlayerUtils = PlayerUtils;
|
|
774
785
|
/** Gets or extends structures to extend the built in, or already extended, classes to add more functionality. */
|