ziplayer 0.0.7 → 0.0.9

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,147 +1,160 @@
1
- import { Track, LoopMode } from "../types";
2
-
3
- export class Queue {
4
- private tracks: Track[] = [];
5
- private current: Track | null = null;
6
- private history: Track[] = [];
7
- private related: Track[] = [];
8
- private _autoPlay = false;
9
- private _loop: LoopMode = "off";
10
- private willnext: Track | null = null;
11
-
12
- add(track: Track): void {
13
- this.tracks.push(track);
14
- }
15
-
16
- addMultiple(tracks: Track[]): void {
17
- this.tracks.push(...tracks);
18
- }
19
-
20
- /** Insert a track at a specific upcoming position (0 = next) */
21
- insert(track: Track, index: number): void {
22
- if (!Number.isFinite(index)) {
23
- this.tracks.push(track);
24
- return;
25
- }
26
- const i = Math.max(0, Math.min(Math.floor(index), this.tracks.length));
27
- if (i === this.tracks.length) {
28
- this.tracks.push(track);
29
- return;
30
- }
31
- if (i <= 0) {
32
- this.tracks.unshift(track);
33
- return;
34
- }
35
- this.tracks.splice(i, 0, track);
36
- }
37
-
38
- /** Insert multiple tracks at a specific upcoming position, preserving order */
39
- insertMultiple(tracks: Track[], index: number): void {
40
- if (!Array.isArray(tracks) || tracks.length === 0) return;
41
- if (!Number.isFinite(index)) {
42
- this.tracks.push(...tracks);
43
- return;
44
- }
45
- const i = Math.max(0, Math.min(Math.floor(index), this.tracks.length));
46
- if (i === 0) {
47
- this.tracks = [...tracks, ...this.tracks];
48
- return;
49
- }
50
- if (i === this.tracks.length) {
51
- this.tracks.push(...tracks);
52
- return;
53
- }
54
- this.tracks.splice(i, 0, ...tracks);
55
- }
56
-
57
- remove(index: number): Track | null {
58
- if (index < 0 || index >= this.tracks.length) return null;
59
- return this.tracks.splice(index, 1)[0];
60
- }
61
-
62
- next(ignoreLoop = false): Track | null {
63
- if (this.current) {
64
- if (this._loop === "track" && !ignoreLoop) {
65
- return this.current;
66
- }
67
- this.history.push(this.current);
68
- if (this.history.length > 200) {
69
- this.history.shift();
70
- }
71
- }
72
- this.current = this.tracks.shift() || null;
73
- if (!this.current && this._loop === "queue" && this.history.length > 0 && !ignoreLoop) {
74
- this.tracks = [...this.history];
75
- this.history = [];
76
- this.current = this.tracks.shift() || null;
77
- }
78
- return this.current;
79
- }
80
-
81
- clear(): void {
82
- this.tracks = [];
83
- }
84
-
85
- autoPlay(value?: boolean): boolean {
86
- if (typeof value !== "undefined") {
87
- this._autoPlay = value;
88
- }
89
- return this._autoPlay;
90
- }
91
-
92
- loop(mode?: LoopMode): LoopMode {
93
- if (mode) {
94
- this._loop = mode;
95
- }
96
- return this._loop;
97
- }
98
-
99
- shuffle(): void {
100
- for (let i = this.tracks.length - 1; i > 0; i--) {
101
- const j = Math.floor(Math.random() * (i + 1));
102
- [this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
103
- }
104
- }
105
-
106
- get size(): number {
107
- return this.tracks.length;
108
- }
109
-
110
- get isEmpty(): boolean {
111
- return this.tracks.length === 0;
112
- }
113
-
114
- get currentTrack(): Track | null {
115
- return this.current;
116
- }
117
-
118
- get previousTracks(): Track[] {
119
- return [...this.history];
120
- }
121
-
122
- get nextTrack(): Track | null {
123
- return this.tracks[0] || null;
124
- }
125
-
126
- willNextTrack(track?: Track): Track | null {
127
- if (track) {
128
- this.willnext = track;
129
- }
130
- return this.willnext;
131
- }
132
-
133
- relatedTracks(track?: Track[]): Track[] | null {
134
- if (track) {
135
- this.related = track;
136
- }
137
- return this.related;
138
- }
139
-
140
- getTracks(): Track[] {
141
- return [...this.tracks];
142
- }
143
-
144
- getTrack(index: number): Track | null {
145
- return this.tracks[index] || null;
146
- }
147
- }
1
+ import { Track, LoopMode } from "../types";
2
+
3
+ export class Queue {
4
+ private tracks: Track[] = [];
5
+ private current: Track | null = null;
6
+ private history: Track[] = [];
7
+ private related: Track[] = [];
8
+ private _autoPlay = false;
9
+ private _loop: LoopMode = "off";
10
+ private willnext: Track | null = null;
11
+
12
+ add(track: Track): void {
13
+ this.tracks.push(track);
14
+ }
15
+
16
+ addMultiple(tracks: Track[]): void {
17
+ this.tracks.push(...tracks);
18
+ }
19
+
20
+ /** Insert a track at a specific upcoming position (0 = next) */
21
+ insert(track: Track, index: number): void {
22
+ if (!Number.isFinite(index)) {
23
+ this.tracks.push(track);
24
+ return;
25
+ }
26
+ const i = Math.max(0, Math.min(Math.floor(index), this.tracks.length));
27
+ if (i === this.tracks.length) {
28
+ this.tracks.push(track);
29
+ return;
30
+ }
31
+ if (i <= 0) {
32
+ this.tracks.unshift(track);
33
+ return;
34
+ }
35
+ this.tracks.splice(i, 0, track);
36
+ }
37
+
38
+ /** Insert multiple tracks at a specific upcoming position, preserving order */
39
+ insertMultiple(tracks: Track[], index: number): void {
40
+ if (!Array.isArray(tracks) || tracks.length === 0) return;
41
+ if (!Number.isFinite(index)) {
42
+ this.tracks.push(...tracks);
43
+ return;
44
+ }
45
+ const i = Math.max(0, Math.min(Math.floor(index), this.tracks.length));
46
+ if (i === 0) {
47
+ this.tracks = [...tracks, ...this.tracks];
48
+ return;
49
+ }
50
+ if (i === this.tracks.length) {
51
+ this.tracks.push(...tracks);
52
+ return;
53
+ }
54
+ this.tracks.splice(i, 0, ...tracks);
55
+ }
56
+
57
+ remove(index: number): Track | null {
58
+ if (index < 0 || index >= this.tracks.length) return null;
59
+ return this.tracks.splice(index, 1)[0];
60
+ }
61
+
62
+ next(ignoreLoop = false): Track | null {
63
+ if (this.current) {
64
+ if (this._loop === "track" && !ignoreLoop) {
65
+ return this.current;
66
+ }
67
+ this.history.push(this.current);
68
+ if (this.history.length > 200) {
69
+ this.history.shift();
70
+ }
71
+ }
72
+ this.current = this.tracks.shift() || null;
73
+ if (!this.current && this._loop === "queue" && this.history.length > 0 && !ignoreLoop) {
74
+ this.tracks = [...this.history];
75
+ this.history = [];
76
+ this.current = this.tracks.shift() || null;
77
+ }
78
+ return this.current;
79
+ }
80
+
81
+ clear(): void {
82
+ this.tracks = [];
83
+ }
84
+
85
+ autoPlay(value?: boolean): boolean {
86
+ if (typeof value !== "undefined") {
87
+ this._autoPlay = value;
88
+ }
89
+ return this._autoPlay;
90
+ }
91
+
92
+ loop(mode?: LoopMode): LoopMode {
93
+ if (mode) {
94
+ this._loop = mode;
95
+ }
96
+ return this._loop;
97
+ }
98
+
99
+ shuffle(): void {
100
+ for (let i = this.tracks.length - 1; i > 0; i--) {
101
+ const j = Math.floor(Math.random() * (i + 1));
102
+ [this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
103
+ }
104
+ }
105
+
106
+ get size(): number {
107
+ return this.tracks.length;
108
+ }
109
+
110
+ get isEmpty(): boolean {
111
+ return this.tracks.length === 0;
112
+ }
113
+
114
+ get currentTrack(): Track | null {
115
+ return this.current;
116
+ }
117
+
118
+ get previousTracks(): Track[] {
119
+ return [...this.history];
120
+ }
121
+
122
+ get nextTrack(): Track | null {
123
+ return this.tracks[0] || null;
124
+ }
125
+
126
+ /**
127
+ * Move back to the previously played track.
128
+ * Makes the current track the next upcoming track, then sets previous as current.
129
+ */
130
+ previous(): Track | null {
131
+ if (this.history.length === 0) return null;
132
+ if (this.current) {
133
+ this.tracks.unshift(this.current);
134
+ }
135
+ this.current = this.history.pop() || null;
136
+ return this.current;
137
+ }
138
+
139
+ willNextTrack(track?: Track): Track | null {
140
+ if (track) {
141
+ this.willnext = track;
142
+ }
143
+ return this.willnext;
144
+ }
145
+
146
+ relatedTracks(track?: Track[]): Track[] | null {
147
+ if (track) {
148
+ this.related = track;
149
+ }
150
+ return this.related;
151
+ }
152
+
153
+ getTracks(): Track[] {
154
+ return [...this.tracks];
155
+ }
156
+
157
+ getTrack(index: number): Track | null {
158
+ return this.tracks[index] || null;
159
+ }
160
+ }
@@ -1,126 +1,131 @@
1
- import { VoiceConnection } from "@discordjs/voice";
2
- import { Readable } from "stream";
3
- import { Player } from "../structures/Player";
4
-
5
- export interface Track {
6
- id: string;
7
- title: string;
8
- url: string;
9
- duration: number;
10
- thumbnail?: string;
11
- requestedBy: string;
12
- source: string;
13
- metadata?: Record<string, any>;
14
- }
15
-
16
- export interface SearchResult {
17
- tracks: Track[];
18
- playlist?: {
19
- name: string;
20
- url: string;
21
- thumbnail?: string;
22
- };
23
- }
24
-
25
- export interface StreamInfo {
26
- stream: Readable;
27
- type: "webm/opus" | "ogg/opus" | "arbitrary";
28
- metadata?: Record<string, any>;
29
- }
30
-
31
- export interface PlayerOptions {
32
- leaveOnEnd?: boolean;
33
- leaveOnEmpty?: boolean;
34
- leaveTimeout?: number;
35
- volume?: number;
36
- quality?: "high" | "low";
37
- selfDeaf?: boolean;
38
- selfMute?: boolean;
39
- /**
40
- * Timeout in milliseconds for plugin operations (search, streaming, etc.)
41
- * to prevent long-running tasks from blocking the player.
42
- */
43
- extractorTimeout?: number;
44
- userdata?: Record<string, any>;
45
- /**
46
- * Text-to-Speech settings. When enabled, the player can create a
47
- * dedicated AudioPlayer to play TTS while pausing the music player
48
- * then resume the music after TTS finishes.
49
- */
50
- tts?: {
51
- /** Create a dedicated tts AudioPlayer at construction time */
52
- createPlayer?: boolean;
53
- /** Pause music and swap subscription to play TTS */
54
- interrupt?: boolean;
55
- /** Default TTS volume multiplier 1 => 100% */
56
- volume?: number;
57
- /** Max time tts playback Duration */
58
- Max_Time_TTS?: number;
59
- };
60
- /**
61
- * Optional per-player extension selection. When provided, only these
62
- * extensions will be activated for the created player.
63
- * - Provide instances or constructors to use them explicitly
64
- * - Or provide names (string) to select from manager-registered extensions
65
- */
66
- extensions?: any[] | string[];
67
- }
68
-
69
- export type SourcePluginCtor<T extends SourcePlugin = SourcePlugin> = new (...args: any[]) => T;
70
- export type SourcePluginLike = SourcePlugin | SourcePluginCtor;
71
-
72
- export interface PlayerManagerOptions {
73
- plugins?: SourcePluginLike[];
74
- extensions?: any[];
75
- }
76
-
77
- export interface ProgressBarOptions {
78
- size?: number;
79
- barChar?: string;
80
- progressChar?: string;
81
- }
82
-
83
- export type LoopMode = "off" | "track" | "queue";
84
-
85
- export interface PlayerEvents {
86
- debug: [message: string, ...args: any[]];
87
- willPlay: [track: Track, upcomingTracks: Track[]];
88
- trackStart: [track: Track];
89
- trackEnd: [track: Track];
90
- queueEnd: [];
91
- playerError: [error: Error, track?: Track];
92
- connectionError: [error: Error];
93
- volumeChange: [oldVolume: number, newVolume: number];
94
- queueAdd: [track: Track];
95
- queueAddList: [tracks: Track[]];
96
- queueRemove: [track: Track, index: number];
97
- playerPause: [track: Track];
98
- playerResume: [track: Track];
99
- playerStop: [];
100
- playerDestroy: [];
101
- /** Emitted when TTS starts playing (interruption mode) */
102
- ttsStart: [payload: { text?: string; track?: Track }];
103
- /** Emitted when TTS finished (interruption mode) */
104
- ttsEnd: [];
105
- }
106
-
107
- // Plugin interfaces
108
- export interface SourcePlugin {
109
- name: string;
110
- version: string;
111
- canHandle(query: string): boolean;
112
- search(query: string, requestedBy: string): Promise<SearchResult>;
113
- getStream(track: Track): Promise<StreamInfo>;
114
- getRelatedTracks?(track: string | number, opts?: { limit?: number; offset?: number }): Promise<Track[]>;
115
- validate?(url: string): boolean;
116
- extractPlaylist?(url: string, requestedBy: string): Promise<Track[]>;
117
- }
118
-
119
- // Extension interfaces
120
- export interface SourceExtension {
121
- name: string;
122
- version: string;
123
- connection?: VoiceConnection;
124
- player: Player | null;
125
- active(alas: any): boolean;
126
- }
1
+ import { VoiceConnection } from "@discordjs/voice";
2
+ import { Readable } from "stream";
3
+ import { Player } from "../structures/Player";
4
+
5
+ export interface Track {
6
+ id: string;
7
+ title: string;
8
+ url: string;
9
+ duration: number;
10
+ thumbnail?: string;
11
+ requestedBy: string;
12
+ source: string;
13
+ metadata?: Record<string, any>;
14
+ }
15
+
16
+ export interface SearchResult {
17
+ tracks: Track[];
18
+ playlist?: {
19
+ name: string;
20
+ url: string;
21
+ thumbnail?: string;
22
+ };
23
+ }
24
+
25
+ export interface StreamInfo {
26
+ stream: Readable;
27
+ type: "webm/opus" | "ogg/opus" | "arbitrary";
28
+ metadata?: Record<string, any>;
29
+ }
30
+
31
+ export interface PlayerOptions {
32
+ leaveOnEnd?: boolean;
33
+ leaveOnEmpty?: boolean;
34
+ leaveTimeout?: number;
35
+ volume?: number;
36
+ quality?: "high" | "low";
37
+ selfDeaf?: boolean;
38
+ selfMute?: boolean;
39
+ /**
40
+ * Timeout in milliseconds for plugin operations (search, streaming, etc.)
41
+ * to prevent long-running tasks from blocking the player.
42
+ */
43
+ extractorTimeout?: number;
44
+ userdata?: Record<string, any>;
45
+ /**
46
+ * Text-to-Speech settings. When enabled, the player can create a
47
+ * dedicated AudioPlayer to play TTS while pausing the music player
48
+ * then resume the music after TTS finishes.
49
+ */
50
+ tts?: {
51
+ /** Create a dedicated tts AudioPlayer at construction time */
52
+ createPlayer?: boolean;
53
+ /** Pause music and swap subscription to play TTS */
54
+ interrupt?: boolean;
55
+ /** Default TTS volume multiplier 1 => 100% */
56
+ volume?: number;
57
+ /** Max time tts playback Duration */
58
+ Max_Time_TTS?: number;
59
+ };
60
+ /**
61
+ * Optional per-player extension selection. When provided, only these
62
+ * extensions will be activated for the created player.
63
+ * - Provide instances or constructors to use them explicitly
64
+ * - Or provide names (string) to select from manager-registered extensions
65
+ */
66
+ extensions?: any[] | string[];
67
+ }
68
+
69
+ export type SourcePluginCtor<T extends SourcePlugin = SourcePlugin> = new (...args: any[]) => T;
70
+ export type SourcePluginLike = SourcePlugin | SourcePluginCtor;
71
+
72
+ export interface PlayerManagerOptions {
73
+ plugins?: SourcePluginLike[];
74
+ extensions?: any[];
75
+ /**
76
+ * Timeout in milliseconds for manager-level operations (e.g. search)
77
+ * when running without a Player instance.
78
+ */
79
+ extractorTimeout?: number;
80
+ }
81
+
82
+ export interface ProgressBarOptions {
83
+ size?: number;
84
+ barChar?: string;
85
+ progressChar?: string;
86
+ }
87
+
88
+ export type LoopMode = "off" | "track" | "queue";
89
+
90
+ export interface PlayerEvents {
91
+ debug: [message: string, ...args: any[]];
92
+ willPlay: [track: Track, upcomingTracks: Track[]];
93
+ trackStart: [track: Track];
94
+ trackEnd: [track: Track];
95
+ queueEnd: [];
96
+ playerError: [error: Error, track?: Track];
97
+ connectionError: [error: Error];
98
+ volumeChange: [oldVolume: number, newVolume: number];
99
+ queueAdd: [track: Track];
100
+ queueAddList: [tracks: Track[]];
101
+ queueRemove: [track: Track, index: number];
102
+ playerPause: [track: Track];
103
+ playerResume: [track: Track];
104
+ playerStop: [];
105
+ playerDestroy: [];
106
+ /** Emitted when TTS starts playing (interruption mode) */
107
+ ttsStart: [payload: { text?: string; track?: Track }];
108
+ /** Emitted when TTS finished (interruption mode) */
109
+ ttsEnd: [];
110
+ }
111
+
112
+ // Plugin interfaces
113
+ export interface SourcePlugin {
114
+ name: string;
115
+ version: string;
116
+ canHandle(query: string): boolean;
117
+ search(query: string, requestedBy: string): Promise<SearchResult>;
118
+ getStream(track: Track): Promise<StreamInfo>;
119
+ getRelatedTracks?(track: string | number, opts?: { limit?: number; offset?: number }): Promise<Track[]>;
120
+ validate?(url: string): boolean;
121
+ extractPlaylist?(url: string, requestedBy: string): Promise<Track[]>;
122
+ }
123
+
124
+ // Extension interfaces
125
+ export interface SourceExtension {
126
+ name: string;
127
+ version: string;
128
+ connection?: VoiceConnection;
129
+ player: Player | null;
130
+ active(alas: any): boolean;
131
+ }