ziplayer 0.0.8 → 0.1.0

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.
@@ -1,7 +1,55 @@
1
1
  import { VoiceConnection } from "@discordjs/voice";
2
2
  import { Readable } from "stream";
3
3
  import { Player } from "../structures/Player";
4
+ import type { PlayerManager } from "../structures/PlayerManager";
4
5
 
6
+ /**
7
+ * Represents a music track with metadata and streaming information.
8
+ *
9
+ * @example
10
+ * // Basic track from YouTube
11
+ * const track: Track = {
12
+ * id: "dQw4w9WgXcQ",
13
+ * title: "Never Gonna Give You Up",
14
+ * url: "https://youtube.com/watch?v=dQw4w9WgXcQ",
15
+ * duration: 212000,
16
+ * thumbnail: "https://img.youtube.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
17
+ * requestedBy: "123456789",
18
+ * source: "youtube",
19
+ * metadata: {
20
+ * artist: "Rick Astley",
21
+ * album: "Whenever You Need Somebody"
22
+ * }
23
+ * };
24
+ *
25
+ * // Track from SoundCloud
26
+ * const soundcloudTrack: Track = {
27
+ * id: "soundcloud-track-123",
28
+ * title: "Electronic Song",
29
+ * url: "https://soundcloud.com/artist/electronic-song",
30
+ * duration: 180000,
31
+ * requestedBy: "user456",
32
+ * source: "soundcloud",
33
+ * metadata: {
34
+ * artist: "Electronic Artist",
35
+ * genre: "Electronic"
36
+ * }
37
+ * };
38
+ *
39
+ * // TTS track
40
+ * const ttsTrack: Track = {
41
+ * id: "tts-" + Date.now(),
42
+ * title: "TTS: Hello everyone!",
43
+ * url: "tts: Hello everyone!",
44
+ * duration: 5000,
45
+ * requestedBy: "user789",
46
+ * source: "tts",
47
+ * metadata: {
48
+ * text: "Hello everyone!",
49
+ * language: "en"
50
+ * }
51
+ * };
52
+ */
5
53
  export interface Track {
6
54
  id: string;
7
55
  title: string;
@@ -13,6 +61,28 @@ export interface Track {
13
61
  metadata?: Record<string, any>;
14
62
  }
15
63
 
64
+ /**
65
+ * Contains search results from plugins, including tracks and optional playlist information.
66
+ *
67
+ * @example
68
+ * const result: SearchResult = {
69
+ * tracks: [
70
+ * {
71
+ * id: "track1",
72
+ * title: "Song 1",
73
+ * url: "https://example.com/track1",
74
+ * duration: 180000,
75
+ * requestedBy: "user123",
76
+ * source: "youtube"
77
+ * }
78
+ * ],
79
+ * playlist: {
80
+ * name: "My Playlist",
81
+ * url: "https://example.com/playlist",
82
+ * thumbnail: "https://example.com/thumb.jpg"
83
+ * }
84
+ * };
85
+ */
16
86
  export interface SearchResult {
17
87
  tracks: Track[];
18
88
  playlist?: {
@@ -22,12 +92,46 @@ export interface SearchResult {
22
92
  };
23
93
  }
24
94
 
95
+ /**
96
+ * Contains streaming information for audio playback.
97
+ *
98
+ * @example
99
+ * const streamInfo: StreamInfo = {
100
+ * stream: audioStream,
101
+ * type: "webm/opus",
102
+ * metadata: {
103
+ * bitrate: 128000,
104
+ * sampleRate: 48000
105
+ * }
106
+ * };
107
+ */
25
108
  export interface StreamInfo {
26
109
  stream: Readable;
27
110
  type: "webm/opus" | "ogg/opus" | "arbitrary";
28
111
  metadata?: Record<string, any>;
29
112
  }
30
113
 
114
+ /**
115
+ * Configuration options for creating a new player instance.
116
+ *
117
+ * @example
118
+ * const options: PlayerOptions = {
119
+ * leaveOnEnd: true,
120
+ * leaveOnEmpty: true,
121
+ * leaveTimeout: 30000,
122
+ * volume: 0.5,
123
+ * quality: "high",
124
+ * selfDeaf: false,
125
+ * selfMute: false,
126
+ * extractorTimeout: 10000,
127
+ * tts: {
128
+ * createPlayer: true,
129
+ * interrupt: true,
130
+ * volume: 1.0,
131
+ * Max_Time_TTS: 30000
132
+ * }
133
+ * };
134
+ */
31
135
  export interface PlayerOptions {
32
136
  leaveOnEnd?: boolean;
33
137
  leaveOnEmpty?: boolean;
@@ -66,9 +170,42 @@ export interface PlayerOptions {
66
170
  extensions?: any[] | string[];
67
171
  }
68
172
 
173
+ /**
174
+ * Constructor for a SourcePlugin
175
+ *
176
+ * @example
177
+ * const plugin = new YouTubePlugin();
178
+ * console.log(`Plugin: ${plugin.name}`);
179
+ */
69
180
  export type SourcePluginCtor<T extends SourcePlugin = SourcePlugin> = new (...args: any[]) => T;
181
+
182
+ /**
183
+ * SourcePlugin or SourcePluginCtor
184
+ *
185
+ * @example
186
+ * const plugin = new YouTubePlugin();
187
+ * console.log(`Plugin: ${plugin.name}`);
188
+ */
70
189
  export type SourcePluginLike = SourcePlugin | SourcePluginCtor;
71
190
 
191
+ /**
192
+ * Configuration options for creating a PlayerManager instance.
193
+ *
194
+ * @example
195
+ * const managerOptions: PlayerManagerOptions = {
196
+ * plugins: [
197
+ * new YouTubePlugin(),
198
+ * new SoundCloudPlugin(),
199
+ * new SpotifyPlugin(),
200
+ * new TTSPlugin({ defaultLang: "en" })
201
+ * ],
202
+ * extensions: [
203
+ * new voiceExt(null, { lang: "en-US" }),
204
+ * new lavalinkExt(null, { nodes: [...] })
205
+ * ],
206
+ * extractorTimeout: 10000
207
+ * };
208
+ */
72
209
  export interface PlayerManagerOptions {
73
210
  plugins?: SourcePluginLike[];
74
211
  extensions?: any[];
@@ -79,6 +216,16 @@ export interface PlayerManagerOptions {
79
216
  extractorTimeout?: number;
80
217
  }
81
218
 
219
+ /**
220
+ * Options for the progress bar
221
+ *
222
+ * @example
223
+ * const options: ProgressBarOptions = {
224
+ * size: 10,
225
+ * barChar: "=",
226
+ * progressChar: ">"
227
+ * };
228
+ */
82
229
  export interface ProgressBarOptions {
83
230
  size?: number;
84
231
  barChar?: string;
@@ -87,6 +234,168 @@ export interface ProgressBarOptions {
87
234
 
88
235
  export type LoopMode = "off" | "track" | "queue";
89
236
 
237
+ /**
238
+ * Context for the extension
239
+ *
240
+ * @example
241
+ * const context: ExtensionContext = {
242
+ * player: player,
243
+ * manager: manager
244
+ * };
245
+ */
246
+ export interface ExtensionContext {
247
+ player: Player;
248
+ manager: PlayerManager;
249
+ }
250
+
251
+ /**
252
+ * Request for the extension to play a track
253
+ *
254
+ * @example
255
+ * const request: ExtensionPlayRequest = {
256
+ * query: "Song Name",
257
+ * requestedBy: "user123"
258
+ * };
259
+ */
260
+ export interface ExtensionPlayRequest {
261
+ query: string | Track;
262
+ requestedBy?: string;
263
+ }
264
+
265
+ /**
266
+ * Response for the extension to play a track
267
+ *
268
+ * @example
269
+ * const response: ExtensionPlayResponse = {
270
+ * handled: true,
271
+ * query: "Song Name",
272
+ * requestedBy: "user123"
273
+ * };
274
+ */
275
+ export interface ExtensionPlayResponse {
276
+ handled?: boolean;
277
+ query?: string | Track;
278
+ requestedBy?: string;
279
+ tracks?: Track[];
280
+ isPlaylist?: boolean;
281
+ success?: boolean;
282
+ error?: Error;
283
+ }
284
+
285
+ /**
286
+ * Payload for the extension to play a track
287
+ *
288
+ * @example
289
+ * const payload: ExtensionAfterPlayPayload = {
290
+ * success: true,
291
+ * query: "Song Name",
292
+ * requestedBy: "user123"
293
+ * };
294
+ */
295
+ export interface ExtensionAfterPlayPayload {
296
+ success: boolean;
297
+ query: string | Track;
298
+ requestedBy?: string;
299
+ tracks?: Track[];
300
+ isPlaylist?: boolean;
301
+ error?: Error;
302
+ }
303
+
304
+ /**
305
+ * Request for the extension to stream a track
306
+ *
307
+ * @example
308
+ * const request: ExtensionStreamRequest = {
309
+ * track: track
310
+ * };
311
+ */
312
+ export interface ExtensionStreamRequest {
313
+ track: Track;
314
+ }
315
+
316
+ /**
317
+ * Request for the extension to search for a track
318
+ *
319
+ * @example
320
+ * const request: ExtensionSearchRequest = {
321
+ * query: "Song Name",
322
+ * requestedBy: "user123"
323
+ * };
324
+ */
325
+ export interface ExtensionSearchRequest {
326
+ query: string;
327
+ requestedBy: string;
328
+ }
329
+
330
+ /**
331
+ * Event types emitted by Player instances.
332
+ *
333
+ * @example
334
+ *
335
+ * player.on("willPlay", (player, track) => {
336
+ * console.log(`Up next: ${track.title}`);
337
+ * });
338
+ *
339
+ * player.on("trackEnd", (player, track) => {
340
+ * console.log(`Now playing: ${track.title}`);
341
+ * });
342
+ *
343
+ * player.on("queueAdd", (player, track) => {
344
+ * console.log(`Queue added: ${track.title}`);
345
+ * });
346
+ *
347
+ * player.on("queueAddList", (player, tracks) => {
348
+ * console.log(`Queue added: ${tracks.length} tracks`);
349
+ * });
350
+ *
351
+ * player.on("queueRemove", (player, track, index) => {
352
+ * console.log(`Queue removed: ${track.title} at index ${index}`);
353
+ * });
354
+ *
355
+ * player.on("playerPause", (player, track) => {
356
+ * console.log(`Player paused: ${track.title}`);
357
+ * });
358
+ *
359
+ * player.on("playerResume", (player, track) => {
360
+ * console.log(`Player resumed: ${track.title}`);
361
+ * });
362
+ *
363
+ * player.on("playerStop", (player) => {
364
+ * console.log("Player stopped");
365
+ * });
366
+ *
367
+ * player.on("playerDestroy", (player) => {
368
+ * console.log("Player destroyed");
369
+ * });
370
+ *
371
+ * player.on("ttsStart", (player, payload) => {
372
+ * console.log(`TTS started: ${payload.text}`);
373
+ * });
374
+ *
375
+ * player.on("ttsEnd", (player) => {
376
+ * console.log("TTS ended");
377
+ * });
378
+ *
379
+ * player.on("playerError", (player, error, track) => {
380
+ * console.log(`Player error: ${error.message}`);
381
+ * });
382
+ *
383
+ * player.on("connectionError", (player, error) => {
384
+ * console.log(`Connection error: ${error.message}`);
385
+ * });
386
+ * player.on("trackStart", (player, track) => {
387
+ * console.log(`Track started: ${track.title}`);
388
+ * });
389
+ *
390
+ * player.on("volumeChange", (player, oldVolume, newVolume) => {
391
+ * console.log(`Volume changed: ${oldVolume} -> ${newVolume}`);
392
+ * });
393
+ *
394
+ * player.on("queueEnd", (player) => {
395
+ * console.log("Queue finished");
396
+ * });
397
+ *
398
+ */
90
399
  export interface PlayerEvents {
91
400
  debug: [message: string, ...args: any[]];
92
401
  willPlay: [track: Track, upcomingTracks: Track[]];
@@ -108,8 +417,15 @@ export interface PlayerEvents {
108
417
  /** Emitted when TTS finished (interruption mode) */
109
418
  ttsEnd: [];
110
419
  }
111
-
112
- // Plugin interfaces
420
+ /**
421
+ * Plugin interface
422
+ *
423
+ * @example
424
+ * const plugin: SourcePlugin = {
425
+ * name: "YouTube",
426
+ * version: "1.0.0"
427
+ * };
428
+ */
113
429
  export interface SourcePlugin {
114
430
  name: string;
115
431
  version: string;
@@ -121,11 +437,34 @@ export interface SourcePlugin {
121
437
  extractPlaylist?(url: string, requestedBy: string): Promise<Track[]>;
122
438
  }
123
439
 
124
- // Extension interfaces
440
+ /**
441
+ * Extension interface
442
+ *
443
+ * @example
444
+ * const extension: SourceExtension = {
445
+ * name: "YouTube",
446
+ * version: "1.0.0"
447
+ * };
448
+ */
125
449
  export interface SourceExtension {
126
450
  name: string;
127
451
  version: string;
128
452
  connection?: VoiceConnection;
129
453
  player: Player | null;
130
- active(alas: any): boolean;
454
+ active(alas: any): boolean | Promise<boolean>;
455
+ onRegister?(context: ExtensionContext): void | Promise<void>;
456
+ onDestroy?(context: ExtensionContext): void | Promise<void>;
457
+ beforePlay?(
458
+ context: ExtensionContext,
459
+ payload: ExtensionPlayRequest,
460
+ ): Promise<ExtensionPlayResponse | void> | ExtensionPlayResponse | void;
461
+ afterPlay?(context: ExtensionContext, payload: ExtensionAfterPlayPayload): Promise<void> | void;
462
+ provideSearch?(
463
+ context: ExtensionContext,
464
+ payload: ExtensionSearchRequest,
465
+ ): Promise<SearchResult | null | undefined> | SearchResult | null | undefined;
466
+ provideStream?(
467
+ context: ExtensionContext,
468
+ payload: ExtensionStreamRequest,
469
+ ): Promise<StreamInfo | null | undefined> | StreamInfo | null | undefined;
131
470
  }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Utility function to add timeout to a promise
3
+ * @param promise The promise to add timeout to
4
+ * @param timeoutMs Timeout in milliseconds
5
+ * @param message Error message when timeout occurs
6
+ * @returns Promise that rejects if timeout is reached
7
+ */
8
+ export function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
9
+ return Promise.race([promise, new Promise<never>((_, reject) => setTimeout(() => reject(new Error(message)), timeoutMs))]);
10
+ }