ziplayer 0.3.12 → 0.3.13
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/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +106 -61
- package/dist/plugins/index.js.map +1 -1
- package/dist/structures/FilterManager.d.ts.map +1 -1
- package/dist/structures/FilterManager.js +7 -2
- package/dist/structures/FilterManager.js.map +1 -1
- package/dist/structures/Player.d.ts +1 -1
- package/dist/structures/Player.d.ts.map +1 -1
- package/dist/structures/Player.js +19 -4
- package/dist/structures/Player.js.map +1 -1
- package/dist/structures/PlayerManager.d.ts +1 -0
- package/dist/structures/PlayerManager.d.ts.map +1 -1
- package/dist/structures/PlayerManager.js +74 -59
- package/dist/structures/PlayerManager.js.map +1 -1
- package/dist/structures/PreloadManager.js +1 -1
- package/dist/structures/PreloadManager.js.map +1 -1
- package/dist/structures/Queue.js +2 -2
- package/dist/structures/Queue.js.map +1 -1
- package/dist/utils/timeout.d.ts.map +1 -1
- package/dist/utils/timeout.js +8 -1
- package/dist/utils/timeout.js.map +1 -1
- package/package.json +1 -1
- package/src/plugins/index.ts +115 -63
- package/src/structures/FilterManager.ts +7 -2
- package/src/structures/Player.ts +23 -4
- package/src/structures/PlayerManager.ts +79 -63
- package/src/structures/PreloadManager.ts +1 -1
- package/src/structures/Queue.ts +2 -2
- package/src/utils/timeout.ts +8 -1
|
@@ -91,6 +91,7 @@ interface ManagerCacheEntry<T> {
|
|
|
91
91
|
export class PlayerManager extends EventEmitter {
|
|
92
92
|
private static instance: PlayerManager | null = null;
|
|
93
93
|
private players: Map<string, Player> = new Map();
|
|
94
|
+
private pendingPlayers: Map<string, Promise<Player>> = new Map();
|
|
94
95
|
private searchCache: Map<string, ManagerCacheEntry<SearchResult>>;
|
|
95
96
|
private readonly SEARCH_CACHE_TTL = 60 * 1000; // 1 minute
|
|
96
97
|
private readonly MAX_CACHE_SIZE = 100;
|
|
@@ -317,80 +318,95 @@ export class PlayerManager extends EventEmitter {
|
|
|
317
318
|
return this.players.get(guildId)!;
|
|
318
319
|
}
|
|
319
320
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
this.plugins.forEach((plugin) => player.addPlugin(plugin));
|
|
325
|
-
|
|
326
|
-
// Activate extensions
|
|
327
|
-
let extsToActivate: any[] = [];
|
|
328
|
-
const optExts = (options as any)?.extensions as any[] | string[] | undefined;
|
|
329
|
-
|
|
330
|
-
if (Array.isArray(optExts)) {
|
|
331
|
-
if (optExts.length === 0) {
|
|
332
|
-
extsToActivate = [];
|
|
333
|
-
} else if (typeof optExts[0] === "string") {
|
|
334
|
-
const wanted = new Set(optExts as string[]);
|
|
335
|
-
extsToActivate = this.extensions.filter((ext) => {
|
|
336
|
-
const name = typeof ext === "function" ? ext.name : ext?.name;
|
|
337
|
-
return !!name && wanted.has(name);
|
|
338
|
-
});
|
|
339
|
-
} else {
|
|
340
|
-
extsToActivate = optExts;
|
|
341
|
-
}
|
|
342
|
-
} else {
|
|
343
|
-
// Use all extensions by default
|
|
344
|
-
extsToActivate = this.extensions;
|
|
321
|
+
// Check if a player is already being created for this guild
|
|
322
|
+
if (this.pendingPlayers.has(guildId)) {
|
|
323
|
+
this.debug(`Player creation already in progress for guildId: ${guildId}, awaiting...`);
|
|
324
|
+
return this.pendingPlayers.get(guildId)!;
|
|
345
325
|
}
|
|
346
326
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
327
|
+
const creationPromise = (async () => {
|
|
328
|
+
try {
|
|
329
|
+
this.debug(`Creating player for guildId: ${guildId}`);
|
|
330
|
+
const player = new Player(guildId, options, this);
|
|
331
|
+
|
|
332
|
+
// Add all registered plugins
|
|
333
|
+
this.plugins.forEach((plugin) => player.addPlugin(plugin));
|
|
334
|
+
|
|
335
|
+
// Activate extensions
|
|
336
|
+
let extsToActivate: any[] = [];
|
|
337
|
+
const optExts = (options as any)?.extensions as any[] | string[] | undefined;
|
|
338
|
+
|
|
339
|
+
if (Array.isArray(optExts)) {
|
|
340
|
+
if (optExts.length === 0) {
|
|
341
|
+
extsToActivate = [];
|
|
342
|
+
} else if (typeof optExts[0] === "string") {
|
|
343
|
+
const wanted = new Set(optExts as string[]);
|
|
344
|
+
extsToActivate = this.extensions.filter((ext) => {
|
|
345
|
+
const name = typeof ext === "function" ? ext.name : ext?.name;
|
|
346
|
+
return !!name && wanted.has(name);
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
extsToActivate = optExts;
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
// Use all extensions by default
|
|
353
|
+
extsToActivate = this.extensions;
|
|
355
354
|
}
|
|
356
|
-
}
|
|
357
355
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
Promise.resolve(extInstance.active({ manager: this, player })),
|
|
368
|
-
player.options.extractorTimeout ?? 15000,
|
|
369
|
-
`Extension ${extInstance?.name} activation timed out`,
|
|
370
|
-
);
|
|
371
|
-
this.debug(`Extension ${extInstance?.name} active check returned: ${activated}`);
|
|
372
|
-
} catch (e) {
|
|
373
|
-
activated = false;
|
|
374
|
-
this.debug(`Extension activation error for ${extInstance?.name}:`, e);
|
|
356
|
+
for (const ext of extsToActivate) {
|
|
357
|
+
let instance = ext;
|
|
358
|
+
if (typeof ext === "function") {
|
|
359
|
+
try {
|
|
360
|
+
instance = new ext(player);
|
|
361
|
+
} catch (e) {
|
|
362
|
+
this.debug(`Extension constructor error for ${ext.name}:`, e);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
375
365
|
}
|
|
376
366
|
|
|
377
|
-
if (
|
|
378
|
-
|
|
379
|
-
|
|
367
|
+
if (instance && typeof instance === "object") {
|
|
368
|
+
const extInstance = instance as BaseExtension;
|
|
369
|
+
if ("player" in extInstance && !extInstance.player) extInstance.player = player;
|
|
370
|
+
player.attachExtension(extInstance);
|
|
371
|
+
|
|
372
|
+
if (typeof extInstance.active === "function") {
|
|
373
|
+
let activated: boolean | void = true;
|
|
374
|
+
try {
|
|
375
|
+
activated = await withTimeout(
|
|
376
|
+
Promise.resolve(extInstance.active({ manager: this, player })),
|
|
377
|
+
player.options.extractorTimeout ?? 15000,
|
|
378
|
+
`Extension ${extInstance?.name} activation timed out`,
|
|
379
|
+
);
|
|
380
|
+
this.debug(`Extension ${extInstance?.name} active check returned: ${activated}`);
|
|
381
|
+
} catch (e) {
|
|
382
|
+
activated = false;
|
|
383
|
+
this.debug(`Extension activation error for ${extInstance?.name}:`, e);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (activated === false) {
|
|
387
|
+
player.detachExtension(extInstance);
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
380
391
|
}
|
|
381
392
|
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
393
|
|
|
385
|
-
|
|
386
|
-
|
|
394
|
+
// Forward all player events to manager
|
|
395
|
+
this.setupEventForwarding(player, guildId);
|
|
387
396
|
|
|
388
|
-
|
|
389
|
-
|
|
397
|
+
// Mark last activity
|
|
398
|
+
(player as any)._lastActivity = Date.now();
|
|
390
399
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
400
|
+
this.players.set(guildId, player);
|
|
401
|
+
this.debug(`Player created for guildId: ${guildId}`);
|
|
402
|
+
return player;
|
|
403
|
+
} finally {
|
|
404
|
+
this.pendingPlayers.delete(guildId);
|
|
405
|
+
}
|
|
406
|
+
})();
|
|
407
|
+
|
|
408
|
+
this.pendingPlayers.set(guildId, creationPromise);
|
|
409
|
+
return creationPromise;
|
|
394
410
|
}
|
|
395
411
|
|
|
396
412
|
private setupEventForwarding(player: Player, guildId: string): void {
|
|
@@ -281,7 +281,7 @@ export class PreloadManager {
|
|
|
281
281
|
signal.removeEventListener("abort", handler);
|
|
282
282
|
reject(new Error("PRELOAD_CANCELLED"));
|
|
283
283
|
};
|
|
284
|
-
signal.addEventListener("abort", handler);
|
|
284
|
+
signal.addEventListener("abort", handler, { once: true });
|
|
285
285
|
});
|
|
286
286
|
|
|
287
287
|
const existingStream = this.streamManager.getStreamByTrack(track.id || track.title);
|
package/src/structures/Queue.ts
CHANGED
|
@@ -231,9 +231,9 @@ export class Queue {
|
|
|
231
231
|
this.current = this.tracks.shift() || null;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
// Skip bypassed track loop but no other track exists →
|
|
234
|
+
// Skip bypassed track loop but no other track exists → trigger queue end
|
|
235
235
|
if (!this.current && this._loop === "track" && ignoreLoop && this.history.length > 0) {
|
|
236
|
-
|
|
236
|
+
return null;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
return this.current;
|
package/src/utils/timeout.ts
CHANGED
|
@@ -6,5 +6,12 @@
|
|
|
6
6
|
* @returns Promise that rejects if timeout is reached
|
|
7
7
|
*/
|
|
8
8
|
export function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
|
|
9
|
-
|
|
9
|
+
let timeoutId: NodeJS.Timeout;
|
|
10
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
11
|
+
timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return Promise.race([promise, timeoutPromise]).finally(() => {
|
|
15
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
16
|
+
});
|
|
10
17
|
}
|