magmastream 2.9.3-dev.3 → 2.9.3-dev.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/blockedWords.d.ts +1 -0
- package/dist/index.d.ts +19 -3687
- package/dist/index.js +1 -1
- package/dist/statestorage/JsonQueue.d.ts +173 -0
- package/dist/statestorage/JsonQueue.js +32 -4
- package/dist/statestorage/MemoryQueue.d.ts +154 -0
- package/dist/statestorage/MemoryQueue.js +56 -36
- package/dist/statestorage/RedisQueue.d.ts +178 -0
- package/dist/statestorage/RedisQueue.js +29 -7
- package/dist/structures/Enums.d.ts +310 -0
- package/dist/structures/Enums.js +6 -0
- package/dist/structures/Filters.d.ts +352 -0
- package/dist/structures/Filters.js +5 -4
- package/dist/structures/MagmastreamError.d.ts +14 -0
- package/dist/structures/Manager.d.ts +259 -0
- package/dist/structures/Manager.js +296 -555
- package/dist/structures/Node.d.ts +390 -0
- package/dist/structures/Node.js +100 -145
- package/dist/structures/Player.d.ts +347 -0
- package/dist/structures/Player.js +55 -132
- package/dist/structures/Plugin.d.ts +23 -0
- package/dist/structures/Rest.d.ts +93 -0
- package/dist/structures/Rest.js +41 -21
- package/dist/structures/Types.d.ts +1315 -0
- package/dist/structures/Utils.d.ts +169 -0
- package/dist/structures/Utils.js +145 -71
- package/dist/utils/filtersEqualizers.d.ts +16 -0
- package/dist/utils/managerCheck.d.ts +7 -0
- package/dist/utils/nodeCheck.d.ts +7 -0
- package/dist/utils/playerCheck.d.ts +7 -0
- package/dist/wrappers/discord.js.d.ts +15 -0
- package/dist/wrappers/discord.js.js +19 -4
- package/dist/wrappers/discordeno.d.ts +19 -0
- package/dist/wrappers/discordeno.js +77 -0
- package/dist/wrappers/eris.d.ts +15 -0
- package/dist/wrappers/eris.js +20 -3
- package/dist/wrappers/oceanic.d.ts +15 -0
- package/dist/wrappers/oceanic.js +22 -4
- package/dist/wrappers/seyfert.d.ts +37 -0
- package/dist/wrappers/seyfert.js +25 -1
- package/package.json +106 -98
- package/dist/wrappers/detritus.js +0 -52
package/dist/structures/Node.js
CHANGED
|
@@ -31,7 +31,6 @@ class Node {
|
|
|
31
31
|
reconnectTimeout;
|
|
32
32
|
reconnectAttempts = 1;
|
|
33
33
|
redisPrefix;
|
|
34
|
-
sessionIdsFilePath;
|
|
35
34
|
sessionIdsMap = new Map();
|
|
36
35
|
/**
|
|
37
36
|
* Creates an instance of Node.
|
|
@@ -97,18 +96,10 @@ class Node {
|
|
|
97
96
|
switch (this.manager.options.stateStorage.type) {
|
|
98
97
|
case Enums_1.StateStorageType.Memory:
|
|
99
98
|
case Enums_1.StateStorageType.JSON:
|
|
100
|
-
this.sessionIdsFilePath = path_1.default.join(process.cwd(), "magmastream", "sessionData", "sessionIds.json");
|
|
101
|
-
const configDir = path_1.default.dirname(this.sessionIdsFilePath);
|
|
102
|
-
if (!fs_1.default.existsSync(configDir)) {
|
|
103
|
-
fs_1.default.mkdirSync(configDir, { recursive: true });
|
|
104
|
-
}
|
|
105
|
-
this.createSessionIdsFile();
|
|
106
99
|
this.createReadmeFile();
|
|
107
100
|
break;
|
|
108
101
|
case Enums_1.StateStorageType.Redis:
|
|
109
|
-
this.redisPrefix =
|
|
110
|
-
? this.manager.options.stateStorage.redisConfig.prefix
|
|
111
|
-
: this.manager.options.stateStorage.redisConfig.prefix ?? "magmastream:";
|
|
102
|
+
this.redisPrefix = Utils_1.PlayerUtils.getRedisKey();
|
|
112
103
|
break;
|
|
113
104
|
}
|
|
114
105
|
}
|
|
@@ -125,16 +116,19 @@ class Node {
|
|
|
125
116
|
get address() {
|
|
126
117
|
return `${this.options.host}:${this.options.port}`;
|
|
127
118
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
119
|
+
getCompositeKey() {
|
|
120
|
+
return `${this.options.identifier}::${this.manager.options.clusterId}`;
|
|
121
|
+
}
|
|
122
|
+
getRedisSessionIdsKey() {
|
|
123
|
+
return `${this.redisPrefix}node:sessionIds`;
|
|
124
|
+
}
|
|
125
|
+
getNodeSessionsDir() {
|
|
126
|
+
return path_1.default.join(process.cwd(), "magmastream", "sessionData", "nodeSessions");
|
|
127
|
+
}
|
|
128
|
+
getNodeSessionPath() {
|
|
129
|
+
const safeId = String(this.options.identifier).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
130
|
+
const clusterId = String(this.manager.options.clusterId ?? 0);
|
|
131
|
+
return path_1.default.join(this.getNodeSessionsDir(), `${safeId}__${clusterId}.txt`);
|
|
138
132
|
}
|
|
139
133
|
/**
|
|
140
134
|
* Loads session IDs from the sessionIds.json file if it exists.
|
|
@@ -148,49 +142,43 @@ class Node {
|
|
|
148
142
|
switch (this.manager.options.stateStorage.type) {
|
|
149
143
|
case Enums_1.StateStorageType.Memory:
|
|
150
144
|
case Enums_1.StateStorageType.JSON: {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
145
|
+
const dir = this.getNodeSessionsDir();
|
|
146
|
+
const filePath = this.getNodeSessionPath();
|
|
147
|
+
if (!fs_1.default.existsSync(dir))
|
|
148
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
149
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
150
|
+
this.sessionId = null;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const raw = fs_1.default.readFileSync(filePath, "utf-8").trim();
|
|
155
|
+
this.sessionId = raw.length ? raw : null;
|
|
156
|
+
if (this.sessionId)
|
|
157
|
+
this.sessionIdsMap.set(this.getCompositeKey(), this.sessionId);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
this.sessionId = null;
|
|
159
161
|
}
|
|
160
162
|
break;
|
|
161
163
|
}
|
|
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();
|
|
164
|
+
case Enums_1.StateStorageType.Redis: {
|
|
165
|
+
const key = this.getRedisSessionIdsKey();
|
|
166
|
+
const compositeKey = this.getCompositeKey();
|
|
167
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Loading sessionId from Redis hash: ${key} field: ${compositeKey}`);
|
|
168
|
+
try {
|
|
169
|
+
const sid = await this.manager.redis.hget(key, compositeKey);
|
|
170
|
+
this.sessionId = sid ?? null;
|
|
171
|
+
if (this.sessionId) {
|
|
172
|
+
this.sessionIdsMap.set(compositeKey, this.sessionId);
|
|
173
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Restored sessionId for ${compositeKey}: ${this.sessionId}`);
|
|
186
174
|
}
|
|
187
175
|
}
|
|
188
|
-
|
|
189
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE]
|
|
190
|
-
|
|
191
|
-
this.sessionIdsMap = new Map();
|
|
176
|
+
catch (err) {
|
|
177
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Failed to load sessionId from Redis hash: ${err.message}`);
|
|
178
|
+
this.sessionId = null;
|
|
192
179
|
}
|
|
193
180
|
break;
|
|
181
|
+
}
|
|
194
182
|
}
|
|
195
183
|
}
|
|
196
184
|
/**
|
|
@@ -207,84 +195,53 @@ class Node {
|
|
|
207
195
|
async updateSessionId() {
|
|
208
196
|
switch (this.manager.options.stateStorage.type) {
|
|
209
197
|
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;
|
|
198
|
+
case Enums_1.StateStorageType.JSON:
|
|
199
|
+
return this.updateSessionIdFile();
|
|
200
|
+
case Enums_1.StateStorageType.Redis:
|
|
201
|
+
return this.updateSessionIdRedis();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async updateSessionIdFile() {
|
|
205
|
+
const dir = this.getNodeSessionsDir();
|
|
206
|
+
const filePath = this.getNodeSessionPath();
|
|
207
|
+
const tmpPath = `${filePath}.tmp`;
|
|
208
|
+
if (!fs_1.default.existsSync(dir))
|
|
209
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
210
|
+
if (this.sessionId) {
|
|
211
|
+
fs_1.default.writeFileSync(tmpPath, this.sessionId, "utf-8");
|
|
212
|
+
fs_1.default.renameSync(tmpPath, filePath);
|
|
213
|
+
this.sessionIdsMap.set(this.getCompositeKey(), this.sessionId);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
try {
|
|
217
|
+
if (fs_1.default.existsSync(filePath))
|
|
218
|
+
fs_1.default.unlinkSync(filePath);
|
|
250
219
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Redis key not found — creating new sessionIds key.`);
|
|
266
|
-
sessionIds = {};
|
|
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;
|
|
220
|
+
catch { }
|
|
221
|
+
this.sessionIdsMap.delete(this.getCompositeKey());
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async updateSessionIdRedis() {
|
|
225
|
+
const key = this.getRedisSessionIdsKey();
|
|
226
|
+
const compositeKey = this.getCompositeKey();
|
|
227
|
+
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Updating sessionId in Redis hash: ${key} field: ${compositeKey}`);
|
|
228
|
+
try {
|
|
229
|
+
if (this.sessionId) {
|
|
230
|
+
await this.manager.redis.hset(key, compositeKey, this.sessionId);
|
|
231
|
+
this.sessionIdsMap.set(compositeKey, this.sessionId);
|
|
287
232
|
}
|
|
233
|
+
else {
|
|
234
|
+
await this.manager.redis.hdel(key, compositeKey);
|
|
235
|
+
this.sessionIdsMap.delete(compositeKey);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
throw new MagmastreamError_1.MagmaStreamError({
|
|
240
|
+
code: Enums_1.MagmaStreamErrorCode.NODE_SESSION_IDS_UPDATE_FAILED,
|
|
241
|
+
message: "Failed to update sessionId in Redis hash.",
|
|
242
|
+
cause: err instanceof Error ? err : undefined,
|
|
243
|
+
context: { key, compositeKey, storage: "redis-hash" },
|
|
244
|
+
});
|
|
288
245
|
}
|
|
289
246
|
}
|
|
290
247
|
/**
|
|
@@ -305,12 +262,7 @@ class Node {
|
|
|
305
262
|
"User-Id": this.manager.options.clientId,
|
|
306
263
|
"Client-Name": this.manager.options.clientName,
|
|
307
264
|
};
|
|
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;
|
|
265
|
+
if (typeof this.sessionId === "string" && this.sessionId.length > 0) {
|
|
314
266
|
headers["Session-Id"] = this.sessionId;
|
|
315
267
|
}
|
|
316
268
|
this.socket = new ws_1.default(`ws${this.options.useSSL ? "s" : ""}://${this.address}/v4/websocket`, { headers });
|
|
@@ -356,9 +308,7 @@ class Node {
|
|
|
356
308
|
// Automove all players connected to that node
|
|
357
309
|
const players = this.manager.players.filter((p) => p.node == this);
|
|
358
310
|
if (players.size) {
|
|
359
|
-
|
|
360
|
-
await player.autoMoveNode();
|
|
361
|
-
}
|
|
311
|
+
await Promise.all(Array.from(players.values(), (player) => player.autoMoveNode()));
|
|
362
312
|
}
|
|
363
313
|
this.socket.close(1000, "destroy");
|
|
364
314
|
this.socket.removeAllListeners();
|
|
@@ -537,10 +487,11 @@ class Node {
|
|
|
537
487
|
case "ready":
|
|
538
488
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Node message: ${Utils_1.JSONUtils.safe(payload, 2)}`);
|
|
539
489
|
this.rest.setSessionId(payload.sessionId);
|
|
490
|
+
const hadPreviousSession = this.sessionId && this.sessionId !== payload.sessionId;
|
|
540
491
|
this.sessionId = payload.sessionId;
|
|
541
492
|
await this.updateSessionId();
|
|
542
493
|
this.info = await this.fetchInfo();
|
|
543
|
-
if (payload.resumed) {
|
|
494
|
+
if (payload.resumed || !hadPreviousSession) {
|
|
544
495
|
await this.manager.loadPlayerStates(this.options.identifier);
|
|
545
496
|
}
|
|
546
497
|
if (this.options.enableSessionResumeOption) {
|
|
@@ -808,7 +759,7 @@ class Node {
|
|
|
808
759
|
}
|
|
809
760
|
}
|
|
810
761
|
if (playNextOnEnd)
|
|
811
|
-
await player.play();
|
|
762
|
+
await player.play({ startTime: 0 });
|
|
812
763
|
}
|
|
813
764
|
/**
|
|
814
765
|
* Plays the next track in the queue.
|
|
@@ -826,7 +777,7 @@ class Node {
|
|
|
826
777
|
await player.queue.setCurrent(await player.queue.dequeue());
|
|
827
778
|
this.manager.emit(Enums_1.ManagerEventTypes.TrackEnd, player, track, payload);
|
|
828
779
|
if (this.manager.options.playNextOnEnd)
|
|
829
|
-
await player.play();
|
|
780
|
+
await player.play({ startTime: 0 });
|
|
830
781
|
}
|
|
831
782
|
/**
|
|
832
783
|
* Handles the event when a queue ends.
|
|
@@ -1222,8 +1173,12 @@ class Node {
|
|
|
1222
1173
|
* @private
|
|
1223
1174
|
*/
|
|
1224
1175
|
createReadmeFile() {
|
|
1225
|
-
const
|
|
1176
|
+
const baseDir = path_1.default.join(process.cwd(), "magmastream");
|
|
1177
|
+
const readmeFilePath = path_1.default.join(baseDir, "README.md");
|
|
1226
1178
|
const message = "Please do NOT delete the magmastream/ folder as it is used to store player data for autoresume etc.";
|
|
1179
|
+
if (!fs_1.default.existsSync(baseDir)) {
|
|
1180
|
+
fs_1.default.mkdirSync(baseDir, { recursive: true });
|
|
1181
|
+
}
|
|
1227
1182
|
if (!fs_1.default.existsSync(readmeFilePath)) {
|
|
1228
1183
|
fs_1.default.writeFileSync(readmeFilePath, message, "utf-8");
|
|
1229
1184
|
this.manager.emit(Enums_1.ManagerEventTypes.Debug, `[NODE] Created README file at: ${readmeFilePath}`);
|