streamify-audio 2.0.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.
@@ -0,0 +1,180 @@
1
+ # Manager
2
+
3
+ The Manager handles player creation, searching, and playlist loading.
4
+
5
+ ## Creating a Manager
6
+
7
+ ```javascript
8
+ const Streamify = require('streamify-audio');
9
+
10
+ const manager = new Streamify.Manager(client, {
11
+ ytdlpPath: '/usr/local/bin/yt-dlp',
12
+ ffmpegPath: '/usr/bin/ffmpeg',
13
+ cookiesPath: './cookies.txt',
14
+ spotify: {
15
+ clientId: process.env.SPOTIFY_CLIENT_ID,
16
+ clientSecret: process.env.SPOTIFY_CLIENT_SECRET
17
+ }
18
+ });
19
+ ```
20
+
21
+ See [Configuration](../configuration.md) for all options.
22
+
23
+ ## Methods
24
+
25
+ ### create(guildId, voiceChannelId, textChannelId)
26
+
27
+ Creates or retrieves a player for a guild.
28
+
29
+ ```javascript
30
+ const player = await manager.create(
31
+ message.guild.id,
32
+ voiceChannel.id,
33
+ message.channel.id
34
+ );
35
+ ```
36
+
37
+ If a player already exists for the guild, returns the existing player. If the voice channel differs, disconnects and reconnects.
38
+
39
+ ### get(guildId)
40
+
41
+ Gets an existing player without creating one.
42
+
43
+ ```javascript
44
+ const player = manager.get(message.guild.id);
45
+ if (!player) {
46
+ return message.reply('No player in this server.');
47
+ }
48
+ ```
49
+
50
+ ### destroy(guildId)
51
+
52
+ Destroys a player and disconnects from voice.
53
+
54
+ ```javascript
55
+ manager.destroy(message.guild.id);
56
+ ```
57
+
58
+ ### destroyAll()
59
+
60
+ Destroys all players. Useful for graceful shutdown.
61
+
62
+ ```javascript
63
+ process.on('SIGINT', () => {
64
+ manager.destroyAll();
65
+ process.exit();
66
+ });
67
+ ```
68
+
69
+ ### search(query, options?)
70
+
71
+ Searches for tracks.
72
+
73
+ ```javascript
74
+ // Basic search (YouTube)
75
+ const result = await manager.search('never gonna give you up');
76
+
77
+ // With options
78
+ const result = await manager.search('never gonna give you up', {
79
+ source: 'spotify', // youtube, spotify, soundcloud
80
+ limit: 10
81
+ });
82
+
83
+ // Result
84
+ {
85
+ loadType: 'search', // search, empty, error
86
+ tracks: [{
87
+ id: 'dQw4w9WgXcQ',
88
+ title: 'Rick Astley - Never Gonna Give You Up',
89
+ author: 'Rick Astley',
90
+ duration: 213,
91
+ thumbnail: 'https://...',
92
+ uri: 'https://youtube.com/...',
93
+ source: 'youtube'
94
+ }]
95
+ }
96
+ ```
97
+
98
+ ### resolve(query)
99
+
100
+ Resolves a URL or falls back to search.
101
+
102
+ ```javascript
103
+ // URL - loads directly
104
+ const result = await manager.resolve('https://youtube.com/watch?v=dQw4w9WgXcQ');
105
+ // { loadType: 'track', tracks: [track] }
106
+
107
+ // Search query - searches
108
+ const result = await manager.resolve('never gonna give you up');
109
+ // { loadType: 'search', tracks: [...] }
110
+ ```
111
+
112
+ ### loadPlaylist(url)
113
+
114
+ Loads a playlist or album.
115
+
116
+ ```javascript
117
+ // YouTube playlist
118
+ const result = await manager.loadPlaylist('https://youtube.com/playlist?list=PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf');
119
+
120
+ // Spotify playlist
121
+ const result = await manager.loadPlaylist('https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M');
122
+
123
+ // Spotify album
124
+ const result = await manager.loadPlaylist('https://open.spotify.com/album/4LH4d3cOWNNsVw41Gqt2kv');
125
+
126
+ // Result
127
+ {
128
+ loadType: 'playlist',
129
+ playlist: {
130
+ id: 'PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf',
131
+ title: 'My Playlist',
132
+ author: 'User',
133
+ thumbnail: 'https://...',
134
+ source: 'youtube'
135
+ },
136
+ tracks: [...]
137
+ }
138
+ ```
139
+
140
+ ### getRelated(track, limit?)
141
+
142
+ Gets related tracks for autoplay.
143
+
144
+ ```javascript
145
+ const result = await manager.getRelated(currentTrack, 5);
146
+ // { tracks: [...] }
147
+ ```
148
+
149
+ ### getStats()
150
+
151
+ Gets manager statistics.
152
+
153
+ ```javascript
154
+ const stats = manager.getStats();
155
+ // {
156
+ // players: 5,
157
+ // playingPlayers: 3,
158
+ // memory: { heapUsed: 52428800, ... }
159
+ // }
160
+ ```
161
+
162
+ ## Events
163
+
164
+ ```javascript
165
+ manager.on('playerCreate', (player) => {
166
+ console.log(`Player created: ${player.guildId}`);
167
+ });
168
+
169
+ manager.on('playerDestroy', (player) => {
170
+ console.log(`Player destroyed: ${player.guildId}`);
171
+ });
172
+ ```
173
+
174
+ ## Properties
175
+
176
+ ```javascript
177
+ manager.players // Map<guildId, Player>
178
+ manager.client // Discord.js client
179
+ manager.config // Resolved configuration
180
+ ```
@@ -0,0 +1,180 @@
1
+ # Player
2
+
3
+ The Player handles playback, filters, and voice connection for a single guild.
4
+
5
+ ## Getting a Player
6
+
7
+ ```javascript
8
+ // Create new or get existing
9
+ const player = await manager.create(guildId, voiceChannelId, textChannelId);
10
+
11
+ // Get existing only
12
+ const player = manager.get(guildId);
13
+ ```
14
+
15
+ ## Playback Methods
16
+
17
+ ### play(track)
18
+
19
+ Plays a track immediately. If something is playing, adds to queue and skips.
20
+
21
+ ```javascript
22
+ const result = await manager.search('never gonna give you up');
23
+ await player.play(result.tracks[0]);
24
+ ```
25
+
26
+ ### pause()
27
+
28
+ Pauses playback and destroys the stream to save resources.
29
+
30
+ ```javascript
31
+ player.pause();
32
+ ```
33
+
34
+ ### resume()
35
+
36
+ Resumes playback by recreating the stream and seeking to the saved position.
37
+
38
+ ```javascript
39
+ await player.resume();
40
+ ```
41
+
42
+ ### skip()
43
+
44
+ Skips to the next track in queue.
45
+
46
+ ```javascript
47
+ await player.skip();
48
+ ```
49
+
50
+ ### previous()
51
+
52
+ Goes back to the previous track.
53
+
54
+ ```javascript
55
+ await player.previous();
56
+ ```
57
+
58
+ ### stop()
59
+
60
+ Stops playback and clears the queue.
61
+
62
+ ```javascript
63
+ player.stop();
64
+ ```
65
+
66
+ ### seek(positionMs)
67
+
68
+ Seeks to a position in milliseconds.
69
+
70
+ ```javascript
71
+ await player.seek(30000); // Seek to 30 seconds
72
+ ```
73
+
74
+ ## Volume
75
+
76
+ ```javascript
77
+ // Set volume (0-200)
78
+ player.setVolume(80);
79
+
80
+ // Get current volume
81
+ console.log(player.volume); // 80
82
+ ```
83
+
84
+ ## Filters
85
+
86
+ ```javascript
87
+ // Set a filter
88
+ await player.setFilter('bass', 10);
89
+ await player.setFilter('nightcore', true);
90
+
91
+ // Clear all filters
92
+ await player.clearFilters();
93
+
94
+ // Get current filters
95
+ console.log(player.filters); // { bass: 10, nightcore: true }
96
+ ```
97
+
98
+ See [Filters](../filters.md) for all available filters.
99
+
100
+ ## Loop Modes
101
+
102
+ ```javascript
103
+ player.setLoop('off'); // No looping
104
+ player.setLoop('track'); // Loop current track
105
+ player.setLoop('queue'); // Loop entire queue
106
+ ```
107
+
108
+ ## Toggles
109
+
110
+ ```javascript
111
+ // Autoplay (play related tracks when queue ends)
112
+ player.setAutoplay(true);
113
+ player.setAutoplay(false);
114
+
115
+ // Auto-pause (pause when channel empty)
116
+ player.setAutoPause(true);
117
+ player.setAutoPause(false);
118
+ ```
119
+
120
+ ## Connection
121
+
122
+ ```javascript
123
+ // Connect to voice
124
+ await player.connect();
125
+
126
+ // Disconnect (keeps player)
127
+ player.disconnect();
128
+
129
+ // Destroy player completely
130
+ player.destroy();
131
+ ```
132
+
133
+ ## State Properties
134
+
135
+ ```javascript
136
+ player.connected // true if connected to voice
137
+ player.playing // true if playing (not paused)
138
+ player.paused // true if paused
139
+ player.position // Current position in ms
140
+ player.volume // Current volume (0-200)
141
+ player.filters // Current filters object
142
+
143
+ player.guildId // Guild ID
144
+ player.voiceChannelId // Voice channel ID
145
+ player.textChannelId // Text channel ID
146
+
147
+ player.autoplay // { enabled, maxTracks }
148
+ player.autoPause // { enabled, minUsers }
149
+ player.autoLeave // { enabled, emptyDelay, inactivityTimeout }
150
+ ```
151
+
152
+ ## Queue Access
153
+
154
+ ```javascript
155
+ player.queue.current // Currently playing track
156
+ player.queue.tracks // Upcoming tracks
157
+ player.queue.previous // Previously played tracks
158
+ ```
159
+
160
+ See [Queue](./queue.md) for queue methods.
161
+
162
+ ## Serialization
163
+
164
+ ```javascript
165
+ const json = player.toJSON();
166
+ // {
167
+ // guildId: '...',
168
+ // voiceChannelId: '...',
169
+ // connected: true,
170
+ // playing: true,
171
+ // paused: false,
172
+ // volume: 80,
173
+ // position: 45000,
174
+ // filters: { bass: 10 },
175
+ // queue: { current: {...}, tracks: [...] },
176
+ // autoplay: { enabled: false },
177
+ // autoPause: { enabled: true },
178
+ // autoLeave: { enabled: true }
179
+ // }
180
+ ```
@@ -0,0 +1,197 @@
1
+ # Queue
2
+
3
+ The Queue manages tracks for a player.
4
+
5
+ ## Accessing the Queue
6
+
7
+ ```javascript
8
+ const player = manager.get(guildId);
9
+ const queue = player.queue;
10
+ ```
11
+
12
+ ## Properties
13
+
14
+ ```javascript
15
+ queue.current // Currently playing track (or null)
16
+ queue.tracks // Array of upcoming tracks
17
+ queue.previous // Array of previously played tracks
18
+ queue.size // Number of upcoming tracks
19
+ queue.isEmpty // true if no upcoming tracks
20
+ queue.totalDuration // Total duration in ms (current + upcoming)
21
+ queue.repeatMode // 'off', 'track', or 'queue'
22
+ ```
23
+
24
+ ## Adding Tracks
25
+
26
+ ### add(track, position?)
27
+
28
+ Add a single track.
29
+
30
+ ```javascript
31
+ // Add to end
32
+ queue.add(track);
33
+
34
+ // Add at specific position
35
+ queue.add(track, 0); // Next up
36
+ queue.add(track, 2); // Third in queue
37
+ ```
38
+
39
+ ### addMany(tracks, position?)
40
+
41
+ Add multiple tracks.
42
+
43
+ ```javascript
44
+ // Add to end
45
+ queue.addMany(tracks);
46
+
47
+ // Add at position
48
+ queue.addMany(tracks, 0);
49
+ ```
50
+
51
+ ## Removing Tracks
52
+
53
+ ### remove(index)
54
+
55
+ Remove a track by index.
56
+
57
+ ```javascript
58
+ const removed = queue.remove(0); // Remove next track
59
+ console.log(removed.title);
60
+ ```
61
+
62
+ ### clear()
63
+
64
+ Clear all upcoming tracks.
65
+
66
+ ```javascript
67
+ const count = queue.clear();
68
+ console.log(`Cleared ${count} tracks`);
69
+ ```
70
+
71
+ ## Reordering
72
+
73
+ ### shuffle()
74
+
75
+ Randomize track order.
76
+
77
+ ```javascript
78
+ queue.shuffle();
79
+ ```
80
+
81
+ ### move(from, to)
82
+
83
+ Move a track to a different position.
84
+
85
+ ```javascript
86
+ queue.move(5, 0); // Move track 5 to next up
87
+ queue.move(0, 3); // Move next track to position 3
88
+ ```
89
+
90
+ ## Loop Mode
91
+
92
+ ```javascript
93
+ queue.setRepeatMode('off'); // No looping
94
+ queue.setRepeatMode('track'); // Repeat current track
95
+ queue.setRepeatMode('queue'); // Repeat entire queue
96
+ ```
97
+
98
+ Or use the player shorthand:
99
+
100
+ ```javascript
101
+ player.setLoop('queue');
102
+ ```
103
+
104
+ ## Internal Methods
105
+
106
+ These are used internally by the Player:
107
+
108
+ ### shift()
109
+
110
+ Moves current to previous, gets next track as current.
111
+
112
+ ```javascript
113
+ const next = queue.shift(); // Returns next track or null
114
+ ```
115
+
116
+ ### unshift()
117
+
118
+ Goes back to previous track.
119
+
120
+ ```javascript
121
+ const prev = queue.unshift(); // Returns previous track or null
122
+ ```
123
+
124
+ ### setCurrent(track)
125
+
126
+ Sets the current track directly.
127
+
128
+ ```javascript
129
+ queue.setCurrent(track);
130
+ ```
131
+
132
+ ## Example: Queue Display
133
+
134
+ ```javascript
135
+ function displayQueue(player) {
136
+ const { current, tracks } = player.queue;
137
+
138
+ let text = '';
139
+
140
+ if (current) {
141
+ text += `**Now Playing:** ${current.title}\n\n`;
142
+ }
143
+
144
+ if (tracks.length > 0) {
145
+ text += '**Up Next:**\n';
146
+ tracks.slice(0, 10).forEach((track, i) => {
147
+ text += `${i + 1}. ${track.title}\n`;
148
+ });
149
+ if (tracks.length > 10) {
150
+ text += `... and ${tracks.length - 10} more`;
151
+ }
152
+ } else {
153
+ text += 'Queue is empty.';
154
+ }
155
+
156
+ return text;
157
+ }
158
+ ```
159
+
160
+ ## Example: Playlist Loading
161
+
162
+ ```javascript
163
+ async function loadPlaylist(player, url) {
164
+ const result = await manager.loadPlaylist(url);
165
+
166
+ if (result.loadType === 'error') {
167
+ throw new Error(result.error);
168
+ }
169
+
170
+ const tracks = result.tracks;
171
+
172
+ if (player.queue.current) {
173
+ // Add all to queue
174
+ player.queue.addMany(tracks);
175
+ return `Added ${tracks.length} tracks to queue`;
176
+ } else {
177
+ // Play first, queue rest
178
+ const first = tracks.shift();
179
+ player.queue.addMany(tracks);
180
+ await player.play(first);
181
+ return `Playing **${result.playlist.title}** (${tracks.length + 1} tracks)`;
182
+ }
183
+ }
184
+ ```
185
+
186
+ ## Serialization
187
+
188
+ ```javascript
189
+ const json = queue.toJSON();
190
+ // {
191
+ // current: { id, title, ... },
192
+ // tracks: [...],
193
+ // previous: [...],
194
+ // repeatMode: 'off',
195
+ // size: 5
196
+ // }
197
+ ```