streamify-audio 2.3.0 → 2.3.2

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.
Files changed (39) hide show
  1. package/index.d.ts +9 -0
  2. package/package.json +1 -1
  3. package/src/config.js +11 -0
  4. package/src/discord/Manager.js +1 -1
  5. package/src/discord/Stream.js +9 -12
  6. package/src/providers/spotify.js +2 -2
  7. package/docs/README.md +0 -31
  8. package/docs/automation.md +0 -186
  9. package/docs/configuration.md +0 -198
  10. package/docs/discord/events.md +0 -206
  11. package/docs/discord/manager.md +0 -195
  12. package/docs/discord/player.md +0 -263
  13. package/docs/discord/queue.md +0 -197
  14. package/docs/examples/advanced-bot.md +0 -391
  15. package/docs/examples/basic-bot.md +0 -182
  16. package/docs/examples/lavalink.md +0 -156
  17. package/docs/filters.md +0 -347
  18. package/docs/http/endpoints.md +0 -224
  19. package/docs/http/server.md +0 -174
  20. package/docs/plans/2026-02-22-stream-revamp-design.md +0 -88
  21. package/docs/plans/2026-02-22-stream-revamp-plan.md +0 -814
  22. package/docs/quick-start.md +0 -92
  23. package/docs/sources.md +0 -189
  24. package/docs/sponsorblock.md +0 -95
  25. package/tests/cache.test.js +0 -234
  26. package/tests/config.test.js +0 -44
  27. package/tests/error-handling.test.js +0 -318
  28. package/tests/ffmpeg.test.js +0 -66
  29. package/tests/filters-edge.test.js +0 -333
  30. package/tests/http.test.js +0 -24
  31. package/tests/integration.test.js +0 -325
  32. package/tests/local.test.js +0 -37
  33. package/tests/queue.test.js +0 -94
  34. package/tests/spotify.test.js +0 -238
  35. package/tests/stream.test.js +0 -217
  36. package/tests/twitch.test.js +0 -42
  37. package/tests/utils.test.js +0 -60
  38. package/tests/youtube.test.js +0 -219
  39. package/youtube-cookies.txt +0 -26
@@ -1,219 +0,0 @@
1
- const { describe, it, beforeEach } = require('node:test');
2
- const assert = require('node:assert');
3
-
4
- const youtube = require('../src/providers/youtube');
5
-
6
- describe('YouTube Provider', () => {
7
- const mockConfig = {
8
- ytdlpPath: 'yt-dlp',
9
- ffmpegPath: 'ffmpeg',
10
- cookiesPath: null,
11
- cache: {
12
- searchTTL: 300,
13
- infoTTL: 600
14
- }
15
- };
16
-
17
- describe('search', () => {
18
- it('should return tracks array for valid query', async () => {
19
- const results = await youtube.search('never gonna give you up', 1, mockConfig);
20
-
21
- assert(results.tracks, 'Should have tracks array');
22
- assert(Array.isArray(results.tracks), 'Tracks should be an array');
23
- assert.strictEqual(results.source, 'youtube');
24
- assert(typeof results.searchTime === 'number', 'Should have searchTime');
25
- });
26
-
27
- it('should respect limit parameter', async () => {
28
- const results = await youtube.search('music', 3, mockConfig);
29
-
30
- assert(results.tracks.length <= 3, 'Should not exceed limit');
31
- });
32
-
33
- it('should return track with required fields', async () => {
34
- const results = await youtube.search('test video', 1, mockConfig);
35
-
36
- if (results.tracks.length > 0) {
37
- const track = results.tracks[0];
38
- assert(track.id, 'Track should have id');
39
- assert(track.title, 'Track should have title');
40
- assert(typeof track.duration === 'number', 'Track should have numeric duration');
41
- assert(track.uri, 'Track should have uri');
42
- assert(track.streamUrl, 'Track should have streamUrl');
43
- assert.strictEqual(track.source, 'youtube');
44
- }
45
- });
46
-
47
- it('should handle empty query gracefully', async () => {
48
- await assert.rejects(
49
- () => youtube.search('', 1, mockConfig),
50
- /yt-dlp/
51
- );
52
- });
53
-
54
- it('should handle special characters in query', async () => {
55
- const results = await youtube.search('test & special <chars> "quotes"', 1, mockConfig);
56
- assert(results.tracks, 'Should handle special characters');
57
- });
58
-
59
- it('should handle unicode in query', async () => {
60
- const results = await youtube.search('日本語 テスト', 1, mockConfig);
61
- assert(results.tracks, 'Should handle unicode');
62
- });
63
-
64
- it('should handle very long query', async () => {
65
- const longQuery = 'a'.repeat(200);
66
- const results = await youtube.search(longQuery, 1, mockConfig);
67
- assert(results.tracks, 'Should handle long query');
68
- });
69
-
70
- it('should filter by type when specified', async () => {
71
- const results = await youtube.search('music', 3, mockConfig, { type: 'video' });
72
- assert(results.tracks, 'Should filter by type');
73
- });
74
-
75
- it('should sort by views when specified', async () => {
76
- const results = await youtube.search('music', 3, mockConfig, { sort: 'views' });
77
- assert(results.tracks, 'Should sort by views');
78
- });
79
-
80
- it('should sort by date when specified', async () => {
81
- const results = await youtube.search('music', 3, mockConfig, { sort: 'date' });
82
- assert(results.tracks, 'Should sort by date');
83
- });
84
- });
85
-
86
- describe('getInfo', () => {
87
- it('should return info for valid video ID', async () => {
88
- const info = await youtube.getInfo('dQw4w9WgXcQ', mockConfig);
89
-
90
- assert(info.id, 'Should have id');
91
- assert(info.title, 'Should have title');
92
- assert(typeof info.duration === 'number', 'Should have numeric duration');
93
- assert(info.uri, 'Should have uri');
94
- assert.strictEqual(info.source, 'youtube');
95
- });
96
-
97
- it('should include author/channel info', async () => {
98
- const info = await youtube.getInfo('dQw4w9WgXcQ', mockConfig);
99
- assert(info.author, 'Should have author');
100
- });
101
-
102
- it('should include thumbnail', async () => {
103
- const info = await youtube.getInfo('dQw4w9WgXcQ', mockConfig);
104
- assert(info.thumbnail, 'Should have thumbnail');
105
- });
106
-
107
- it('should throw for invalid video ID', async () => {
108
- await assert.rejects(
109
- () => youtube.getInfo('invalidid123456789', mockConfig),
110
- /yt-dlp/
111
- );
112
- });
113
-
114
- it('should throw for empty video ID', async () => {
115
- await assert.rejects(
116
- () => youtube.getInfo('', mockConfig),
117
- /yt-dlp/
118
- );
119
- });
120
-
121
- it('should detect live streams', async () => {
122
- const info = await youtube.getInfo('dQw4w9WgXcQ', mockConfig);
123
- assert(typeof info.isLive === 'boolean', 'Should have isLive flag');
124
- });
125
-
126
- it('should include streamUrl', async () => {
127
- const info = await youtube.getInfo('dQw4w9WgXcQ', mockConfig);
128
- assert(info.streamUrl.includes('/youtube/stream/'), 'Should have correct streamUrl format');
129
- });
130
- });
131
-
132
- describe('getPlaylist', () => {
133
- it('should return playlist info for valid playlist ID', async () => {
134
- const playlist = await youtube.getPlaylist('PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf', mockConfig);
135
-
136
- assert(playlist.id, 'Should have id');
137
- assert(playlist.tracks, 'Should have tracks');
138
- assert(Array.isArray(playlist.tracks), 'Tracks should be array');
139
- assert.strictEqual(playlist.source, 'youtube');
140
- });
141
-
142
- it('should throw for invalid playlist ID', async () => {
143
- await assert.rejects(
144
- () => youtube.getPlaylist('invalidplaylist', mockConfig),
145
- /yt-dlp/
146
- );
147
- });
148
-
149
- it('should include track details in playlist', async () => {
150
- const playlist = await youtube.getPlaylist('PLrAXtmErZgOeiKm4sgNOknGvNjby9efdf', mockConfig);
151
-
152
- if (playlist.tracks.length > 0) {
153
- const track = playlist.tracks[0];
154
- assert(track.id, 'Track should have id');
155
- assert(track.title, 'Track should have title');
156
- assert(track.streamUrl, 'Track should have streamUrl');
157
- }
158
- });
159
- });
160
-
161
- describe('getRelated', () => {
162
- it('should return related videos', async () => {
163
- const related = await youtube.getRelated('dQw4w9WgXcQ', 5, mockConfig);
164
-
165
- assert(related.tracks, 'Should have tracks');
166
- assert(Array.isArray(related.tracks), 'Tracks should be array');
167
- assert.strictEqual(related.source, 'youtube');
168
- });
169
-
170
- it('should respect limit', async () => {
171
- const related = await youtube.getRelated('dQw4w9WgXcQ', 3, mockConfig);
172
- assert(related.tracks.length <= 3, 'Should not exceed limit');
173
- });
174
-
175
- it('should not include source video in results', async () => {
176
- const sourceId = 'dQw4w9WgXcQ';
177
- const related = await youtube.getRelated(sourceId, 5, mockConfig);
178
-
179
- const hasSourceVideo = related.tracks.some(t => t.id === sourceId);
180
- assert(!hasSourceVideo, 'Should not include source video');
181
- });
182
-
183
- it('should mark tracks as autoplay', async () => {
184
- const related = await youtube.getRelated('dQw4w9WgXcQ', 3, mockConfig);
185
-
186
- if (related.tracks.length > 0) {
187
- assert.strictEqual(related.tracks[0].isAutoplay, true, 'Should be marked as autoplay');
188
- }
189
- });
190
- });
191
-
192
- describe('edge cases', () => {
193
- it('should handle age-restricted content', async () => {
194
- // This test may fail without cookies - that's expected
195
- try {
196
- const info = await youtube.getInfo('6kLq3WMV1nU', mockConfig);
197
- assert(info.id, 'Should get info if cookies available');
198
- } catch (e) {
199
- assert(e.message.includes('yt-dlp'), 'Should fail gracefully without cookies');
200
- }
201
- });
202
-
203
- it('should handle deleted/private videos', async () => {
204
- await assert.rejects(
205
- () => youtube.getInfo('aaaaaaaaaaa', mockConfig),
206
- /yt-dlp/
207
- );
208
- });
209
-
210
- it('should handle region-blocked content gracefully', async () => {
211
- // Most region blocks should produce an error from yt-dlp
212
- try {
213
- await youtube.getInfo('_some_blocked_video_', mockConfig);
214
- } catch (e) {
215
- assert(e.message, 'Should throw with message');
216
- }
217
- });
218
- });
219
- });
@@ -1,26 +0,0 @@
1
- # Netscape HTTP Cookie File
2
- # This file is generated by yt-dlp. Do not edit.
3
-
4
- .youtube.com TRUE / TRUE 1800398983 __Secure-YENID 12.YTE=UfQjguVvlx3WLiJJHSjg4nPS-N-5O3Xj8RZj-wlLmRdjAvaF3TRdMzSmyUmo82Z4P-tggpd89U5d3hMDN886ZuUZUzi5XdEFEmHjL0YrTPBwPhD6pZx5CJ-3bNb3Eb_7eZuq_YlqQb0OX6Hvu2yYtWfWZPq7dZUjnJarOqJB0UaWu4jlsn27LkAmA9ecZK7Tj0NXQsIiDMR_y8pHe-kOfQ9LhLBeMnUWvR7GXsSOo_NqyfHrNnu4W8YnBd45ZUQIhwQ91X7lhuTkbBj3hYNJsWv0G7yda1NfB8j-nh8ZkordnGPIyv5QlCTd745j2DiGeS1GSa2jP2bClx7SoQxTjQ
5
- .youtube.com TRUE / FALSE 0 PREF f6=40000000&tz=UTC&hl=en
6
- .youtube.com TRUE / TRUE 1782082203 NID 527=aqYd85605VNHKMN7IAs-QcA6YfpJm6LGDAjKm929dxg81_ly4EHuc_A0jCgct9sjP-yDkNobeQPSES7fdZYHdzmlnHO_gGQ-oVCIbS3GQvSB89DCDEPB-toK2K62rr6iUVoTg3lcUG5xBhVXwoPPOD6VWWqegOp-IOhJhTb7Ijp_899mbKpj-4Elx8vNwUL0X-lJAe5Th-4Mxv9lDynXDH8axGjFhMHboeuTOHiIXRg10-4BoqyhAGFDhKNohiMwDc66EraGHim03-ZM
7
- .youtube.com TRUE / TRUE 1800826170 __Secure-1PSIDTS sidts-CjUB7I_69MoGgU9hYcmJtLk5dHx1d0LjE7gLaoN86V6V3M8eyIyUH6LOPPFj2llBVQAVsulbqRAA
8
- .youtube.com TRUE / TRUE 1800826170 __Secure-3PSIDTS sidts-CjUB7I_69MoGgU9hYcmJtLk5dHx1d0LjE7gLaoN86V6V3M8eyIyUH6LOPPFj2llBVQAVsulbqRAA
9
- .youtube.com TRUE / FALSE 1803850170 HSID Ab4swI6vjvKUnUkhu
10
- .youtube.com TRUE / TRUE 1803850170 SSID AaxSz8h17yLe-BmmX
11
- .youtube.com TRUE / FALSE 1803850170 APISID pQgk6uQUwAqRtThp/Ape45AAtgBDxnzVco
12
- .youtube.com TRUE / TRUE 1803850170 SAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
13
- .youtube.com TRUE / TRUE 1803850170 __Secure-1PAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
14
- .youtube.com TRUE / TRUE 1803850170 __Secure-3PAPISID y_RgVkrBXATC2XrL/Avlu8CWS6dwZ7LTEg
15
- .youtube.com TRUE / FALSE 1803850170 SID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtb98Ev6KQIph7SQPbMD4aekgACgYKAaMSARMSFQHGX2MijLBjWKdOhQm5VmUkh9wlRhoVAUF8yKqE_WWJQO8PgiZpXVV1MiB30076
16
- .youtube.com TRUE / TRUE 1803850170 __Secure-1PSID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtb9khH10B1YSjuMht-R8LNjAACgYKAQ8SARMSFQHGX2MiWX5D8_L5MAZK1TLabPQMghoVAUF8yKoFUiQLoi8zHLuskryhcx1P0076
17
- .youtube.com TRUE / TRUE 1803850170 __Secure-3PSID g.a0006AhyolP4RoeyrQXcHsFnRGkuVLVIZ9QQsgpwFaXGd822GTtbc5VtVrqvDy9fWzO4vguctgACgYKAUkSARMSFQHGX2MinKYgh3CtvTW5E5T8SwXiERoVAUF8yKqzIJTS4ajNX5uO8nh3r0j10076
18
- .youtube.com TRUE / TRUE 1803850170 LOGIN_INFO AFmmF2swRQIgH6IrdLYFOhW8xu4opIUHTGxAf33LzI5EXw6pdoqsh_gCIQCxYHQL4VZEyb3nE-rhXM6VU2ua99G4AhzKl4JJlzZBEQ:QUQ3MjNmeFpJOS1rVDgtM2I4cm50Z3M4NUplLTlSbXV4OFl4MTM5eUtHX3FEcVNmT2ltVFlSWmpQdlR2QTVqR29mZlUtTVh4OEhkOGw4Rkd5d2tQZm52NXJmQzdrMFJPVk5uYTFLNFFMZWlGelJhRVk1TkVaMm9Uby0xWlcwR3ozYkwwY2lWT21pV2dpU0lsWW5saFhMektISWxwUkRUcXl3
19
- .youtube.com TRUE / FALSE 1803305074 SIDCC AKEyXzW6XAqY9tNhDWlFzlv-TcDtmpxQxQjOpTwkeLq7ddP20Ecx5ttbRGa7K7WKJVXYBIsbGTE
20
- .youtube.com TRUE / TRUE 1803305074 __Secure-1PSIDCC AKEyXzVdeiA5hPJOoWk_iVZXhBC3-3D4ZAlHjwkIdtnQ-y_iHxOeAdYucag2Dv-EMebAtINo-Q
21
- .youtube.com TRUE / TRUE 1803305074 __Secure-3PSIDCC AKEyXzX9LV_1LP1Z1T6SCow5CKbPxteZg-XPIOt3o2Uu6OlsIn6Z2S3gRZBgUTHpaiRcVbPYbg
22
- .youtube.com TRUE / TRUE 1787290794 __Secure-YNID 16.YT=uhIB3j65_j5F-nN_AIVu93J6J4tqe4fviGdBQuGk0X5EW7VRESfm4qMadhbgM04D7x1YyYRXKI0UIHJjiRMWqsP5PmT_qrHoTUSn4MOLA-FPeX09ELODYdpGvps9F6B3EFC2jC4MXYiWVY6KGZRiEoYBh_KWkh4Suwgn38LgfqN0E4Xv3YAzCB390qeKtLVkaqlQDUIvhnqGBPrObW-DzawPn00gHQph8VM2Zrklq_BzRYVaZHKHs2WkKlHqLljxwOiNXcsLrIkLqGsCgKR_onVOnlWN2gd0zojNv0VyuwYgfB9GBOLzweTnTWBZmp9IPWRA39DH4zMFerdTND-Yfg
23
- .youtube.com TRUE / TRUE 0 YSC -LHUdUOZvC4
24
- .youtube.com TRUE / TRUE 1787321074 VISITOR_INFO1_LIVE AuEVGsoJz2Y
25
- .youtube.com TRUE / TRUE 1787321074 VISITOR_PRIVACY_METADATA CgJVUxIEGgAgVQ%3D%3D
26
- .youtube.com TRUE / TRUE 1787290794 __Secure-ROLLOUT_TOKEN CIbdoKq8kOipXhC__cjij6WSAxiZi8-rseySAw%3D%3D