navidrome-mcp 1.0.1

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 (195) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +397 -0
  3. package/dist/capabilities.d.ts +20 -0
  4. package/dist/capabilities.d.ts.map +1 -0
  5. package/dist/capabilities.js +25 -0
  6. package/dist/capabilities.js.map +1 -0
  7. package/dist/client/auth-manager.d.ts +27 -0
  8. package/dist/client/auth-manager.d.ts.map +1 -0
  9. package/dist/client/auth-manager.js +54 -0
  10. package/dist/client/auth-manager.js.map +1 -0
  11. package/dist/client/navidrome-client.d.ts +28 -0
  12. package/dist/client/navidrome-client.d.ts.map +1 -0
  13. package/dist/client/navidrome-client.js +84 -0
  14. package/dist/client/navidrome-client.js.map +1 -0
  15. package/dist/config.d.ts +41 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +132 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/constants/defaults.d.ts +29 -0
  20. package/dist/constants/defaults.d.ts.map +1 -0
  21. package/dist/constants/defaults.js +37 -0
  22. package/dist/constants/defaults.js.map +1 -0
  23. package/dist/constants/timeouts.d.ts +66 -0
  24. package/dist/constants/timeouts.d.ts.map +1 -0
  25. package/dist/constants/timeouts.js +66 -0
  26. package/dist/constants/timeouts.js.map +1 -0
  27. package/dist/index.d.ts +20 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +70 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/resources/index.d.ts +21 -0
  32. package/dist/resources/index.d.ts.map +1 -0
  33. package/dist/resources/index.js +83 -0
  34. package/dist/resources/index.js.map +1 -0
  35. package/dist/schemas/common.d.ts +68 -0
  36. package/dist/schemas/common.d.ts.map +1 -0
  37. package/dist/schemas/common.js +69 -0
  38. package/dist/schemas/common.js.map +1 -0
  39. package/dist/schemas/index.d.ts +21 -0
  40. package/dist/schemas/index.d.ts.map +1 -0
  41. package/dist/schemas/index.js +24 -0
  42. package/dist/schemas/index.js.map +1 -0
  43. package/dist/schemas/pagination.d.ts +153 -0
  44. package/dist/schemas/pagination.d.ts.map +1 -0
  45. package/dist/schemas/pagination.js +93 -0
  46. package/dist/schemas/pagination.js.map +1 -0
  47. package/dist/schemas/validation.d.ts +147 -0
  48. package/dist/schemas/validation.d.ts.map +1 -0
  49. package/dist/schemas/validation.js +143 -0
  50. package/dist/schemas/validation.js.map +1 -0
  51. package/dist/tools/handlers/lastfm-handlers.d.ts +5 -0
  52. package/dist/tools/handlers/lastfm-handlers.d.ts.map +1 -0
  53. package/dist/tools/handlers/lastfm-handlers.js +143 -0
  54. package/dist/tools/handlers/lastfm-handlers.js.map +1 -0
  55. package/dist/tools/handlers/lyrics-handlers.d.ts +5 -0
  56. package/dist/tools/handlers/lyrics-handlers.d.ts.map +1 -0
  57. package/dist/tools/handlers/lyrics-handlers.js +51 -0
  58. package/dist/tools/handlers/lyrics-handlers.js.map +1 -0
  59. package/dist/tools/handlers/playlist-handlers.d.ts +5 -0
  60. package/dist/tools/handlers/playlist-handlers.d.ts.map +1 -0
  61. package/dist/tools/handlers/playlist-handlers.js +316 -0
  62. package/dist/tools/handlers/playlist-handlers.js.map +1 -0
  63. package/dist/tools/handlers/queue-handlers.d.ts +5 -0
  64. package/dist/tools/handlers/queue-handlers.d.ts.map +1 -0
  65. package/dist/tools/handlers/queue-handlers.js +135 -0
  66. package/dist/tools/handlers/queue-handlers.js.map +1 -0
  67. package/dist/tools/handlers/radio-handlers.d.ts +5 -0
  68. package/dist/tools/handlers/radio-handlers.d.ts.map +1 -0
  69. package/dist/tools/handlers/radio-handlers.js +323 -0
  70. package/dist/tools/handlers/radio-handlers.js.map +1 -0
  71. package/dist/tools/handlers/registry.d.ts +26 -0
  72. package/dist/tools/handlers/registry.d.ts.map +1 -0
  73. package/dist/tools/handlers/registry.js +77 -0
  74. package/dist/tools/handlers/registry.js.map +1 -0
  75. package/dist/tools/handlers/search-handlers.d.ts +5 -0
  76. package/dist/tools/handlers/search-handlers.d.ts.map +1 -0
  77. package/dist/tools/handlers/search-handlers.js +125 -0
  78. package/dist/tools/handlers/search-handlers.js.map +1 -0
  79. package/dist/tools/handlers/tag-handlers.d.ts +5 -0
  80. package/dist/tools/handlers/tag-handlers.d.ts.map +1 -0
  81. package/dist/tools/handlers/tag-handlers.js +155 -0
  82. package/dist/tools/handlers/tag-handlers.js.map +1 -0
  83. package/dist/tools/handlers/user-preferences-handlers.d.ts +5 -0
  84. package/dist/tools/handlers/user-preferences-handlers.d.ts.map +1 -0
  85. package/dist/tools/handlers/user-preferences-handlers.js +155 -0
  86. package/dist/tools/handlers/user-preferences-handlers.js.map +1 -0
  87. package/dist/tools/index.d.ts +19 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +20 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/lastfm-discovery.d.ts +107 -0
  92. package/dist/tools/lastfm-discovery.d.ts.map +1 -0
  93. package/dist/tools/lastfm-discovery.js +238 -0
  94. package/dist/tools/lastfm-discovery.js.map +1 -0
  95. package/dist/tools/library.d.ts +31 -0
  96. package/dist/tools/library.d.ts.map +1 -0
  97. package/dist/tools/library.js +272 -0
  98. package/dist/tools/library.js.map +1 -0
  99. package/dist/tools/listening-history.d.ts +51 -0
  100. package/dist/tools/listening-history.d.ts.map +1 -0
  101. package/dist/tools/listening-history.js +126 -0
  102. package/dist/tools/listening-history.js.map +1 -0
  103. package/dist/tools/lyrics.d.ts +35 -0
  104. package/dist/tools/lyrics.d.ts.map +1 -0
  105. package/dist/tools/lyrics.js +222 -0
  106. package/dist/tools/lyrics.js.map +1 -0
  107. package/dist/tools/media-library.d.ts +46 -0
  108. package/dist/tools/media-library.d.ts.map +1 -0
  109. package/dist/tools/media-library.js +179 -0
  110. package/dist/tools/media-library.js.map +1 -0
  111. package/dist/tools/playlist-management.d.ts +80 -0
  112. package/dist/tools/playlist-management.d.ts.map +1 -0
  113. package/dist/tools/playlist-management.js +384 -0
  114. package/dist/tools/playlist-management.js.map +1 -0
  115. package/dist/tools/queue-management.d.ts +48 -0
  116. package/dist/tools/queue-management.d.ts.map +1 -0
  117. package/dist/tools/queue-management.js +83 -0
  118. package/dist/tools/queue-management.js.map +1 -0
  119. package/dist/tools/radio-discovery.d.ts +95 -0
  120. package/dist/tools/radio-discovery.d.ts.map +1 -0
  121. package/dist/tools/radio-discovery.js +352 -0
  122. package/dist/tools/radio-discovery.js.map +1 -0
  123. package/dist/tools/radio-validation.d.ts +49 -0
  124. package/dist/tools/radio-validation.d.ts.map +1 -0
  125. package/dist/tools/radio-validation.js +463 -0
  126. package/dist/tools/radio-validation.js.map +1 -0
  127. package/dist/tools/radio.d.ts +38 -0
  128. package/dist/tools/radio.d.ts.map +1 -0
  129. package/dist/tools/radio.js +315 -0
  130. package/dist/tools/radio.js.map +1 -0
  131. package/dist/tools/search.d.ts +54 -0
  132. package/dist/tools/search.d.ts.map +1 -0
  133. package/dist/tools/search.js +165 -0
  134. package/dist/tools/search.js.map +1 -0
  135. package/dist/tools/tags.d.ts +63 -0
  136. package/dist/tools/tags.d.ts.map +1 -0
  137. package/dist/tools/tags.js +260 -0
  138. package/dist/tools/tags.js.map +1 -0
  139. package/dist/tools/test.d.ts +50 -0
  140. package/dist/tools/test.d.ts.map +1 -0
  141. package/dist/tools/test.js +121 -0
  142. package/dist/tools/test.js.map +1 -0
  143. package/dist/tools/user-preferences.d.ts +73 -0
  144. package/dist/tools/user-preferences.d.ts.map +1 -0
  145. package/dist/tools/user-preferences.js +231 -0
  146. package/dist/tools/user-preferences.js.map +1 -0
  147. package/dist/transformers/song-transformer.d.ts +122 -0
  148. package/dist/transformers/song-transformer.d.ts.map +1 -0
  149. package/dist/transformers/song-transformer.js +232 -0
  150. package/dist/transformers/song-transformer.js.map +1 -0
  151. package/dist/types/core.d.ts +147 -0
  152. package/dist/types/core.d.ts.map +1 -0
  153. package/dist/types/core.js +19 -0
  154. package/dist/types/core.js.map +1 -0
  155. package/dist/types/index.d.ts +23 -0
  156. package/dist/types/index.d.ts.map +1 -0
  157. package/dist/types/index.js +19 -0
  158. package/dist/types/index.js.map +1 -0
  159. package/dist/types/lyrics.d.ts +58 -0
  160. package/dist/types/lyrics.d.ts.map +1 -0
  161. package/dist/types/lyrics.js +19 -0
  162. package/dist/types/lyrics.js.map +1 -0
  163. package/dist/types/playlists.d.ts +150 -0
  164. package/dist/types/playlists.d.ts.map +1 -0
  165. package/dist/types/playlists.js +19 -0
  166. package/dist/types/playlists.js.map +1 -0
  167. package/dist/types/radio.d.ts +192 -0
  168. package/dist/types/radio.d.ts.map +1 -0
  169. package/dist/types/radio.js +19 -0
  170. package/dist/types/radio.js.map +1 -0
  171. package/dist/types/tags.d.ts +72 -0
  172. package/dist/types/tags.d.ts.map +1 -0
  173. package/dist/types/tags.js +19 -0
  174. package/dist/types/tags.js.map +1 -0
  175. package/dist/utils/cache.d.ts +32 -0
  176. package/dist/utils/cache.d.ts.map +1 -0
  177. package/dist/utils/cache.js +84 -0
  178. package/dist/utils/cache.js.map +1 -0
  179. package/dist/utils/error-formatter.d.ts +108 -0
  180. package/dist/utils/error-formatter.d.ts.map +1 -0
  181. package/dist/utils/error-formatter.js +161 -0
  182. package/dist/utils/error-formatter.js.map +1 -0
  183. package/dist/utils/logger.d.ts +33 -0
  184. package/dist/utils/logger.d.ts.map +1 -0
  185. package/dist/utils/logger.js +52 -0
  186. package/dist/utils/logger.js.map +1 -0
  187. package/dist/utils/message-manager.d.ts +74 -0
  188. package/dist/utils/message-manager.d.ts.map +1 -0
  189. package/dist/utils/message-manager.js +134 -0
  190. package/dist/utils/message-manager.js.map +1 -0
  191. package/dist/utils/version.d.ts +5 -0
  192. package/dist/utils/version.d.ts.map +1 -0
  193. package/dist/utils/version.js +19 -0
  194. package/dist/utils/version.js.map +1 -0
  195. package/package.json +78 -0
@@ -0,0 +1,463 @@
1
+ /**
2
+ * Navidrome MCP Server - Radio Stream Validation Tool
3
+ * Copyright (C) 2025
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Affero General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU Affero General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Affero General Public License
16
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import { z } from 'zod';
19
+ import { fileTypeFromBuffer } from 'file-type';
20
+ import { SINGLE_VALIDATION_TIMEOUT, MIN_VALIDATION_TIMEOUT, MAX_VALIDATION_TIMEOUT, RADIO_VALIDATION } from '../constants/timeouts.js';
21
+ // Validation parameter schema
22
+ const ValidateStreamSchema = z.object({
23
+ url: z.string().url('URL must be a valid URL'),
24
+ timeout: z.number().min(MIN_VALIDATION_TIMEOUT).max(MAX_VALIDATION_TIMEOUT).optional().default(SINGLE_VALIDATION_TIMEOUT),
25
+ followRedirects: z.boolean().optional().default(true),
26
+ });
27
+ // Valid audio MIME types
28
+ const VALID_AUDIO_MIMES = [
29
+ 'audio/mpeg',
30
+ 'audio/mp3',
31
+ 'audio/aac',
32
+ 'audio/aacp',
33
+ 'audio/ogg',
34
+ 'audio/opus',
35
+ 'audio/flac',
36
+ 'audio/x-ms-wma',
37
+ 'application/ogg',
38
+ 'audio/webm',
39
+ 'audio/x-mpegurl', // M3U playlist
40
+ 'audio/x-scpls', // PLS playlist
41
+ 'application/vnd.apple.mpegurl', // HLS
42
+ ];
43
+ // Streaming-specific headers to check
44
+ const STREAMING_HEADERS = [
45
+ 'icy-name',
46
+ 'icy-br',
47
+ 'icy-metaint',
48
+ 'icy-genre',
49
+ 'icy-url',
50
+ 'icy-pub',
51
+ 'x-audiocast-name',
52
+ 'x-audiocast-genre',
53
+ 'x-audiocast-bitrate',
54
+ ];
55
+ /**
56
+ * Extract streaming headers from response
57
+ */
58
+ function extractStreamingHeaders(headers) {
59
+ const streamHeaders = {};
60
+ headers.forEach((value, key) => {
61
+ const lowerKey = key.toLowerCase();
62
+ if (STREAMING_HEADERS.includes(lowerKey) || lowerKey.startsWith('icy-')) {
63
+ streamHeaders[lowerKey] = value;
64
+ }
65
+ });
66
+ return streamHeaders;
67
+ }
68
+ /**
69
+ * Check if content type indicates audio
70
+ */
71
+ function isAudioContentType(contentType) {
72
+ if (!contentType)
73
+ return false;
74
+ const normalized = contentType.toLowerCase();
75
+ return VALID_AUDIO_MIMES.some(mime => normalized.includes(mime));
76
+ }
77
+ /**
78
+ * Detect audio format from buffer
79
+ */
80
+ async function detectAudioFormat(buffer) {
81
+ try {
82
+ const fileType = await fileTypeFromBuffer(buffer);
83
+ if (fileType && fileType.mime.startsWith('audio/')) {
84
+ return {
85
+ detected: true,
86
+ format: fileType.ext,
87
+ mime: fileType.mime,
88
+ };
89
+ }
90
+ // Check for common audio signatures manually if file-type doesn't detect
91
+ const signatures = [
92
+ { bytes: [0xFF, 0xFB], format: 'mp3', mime: 'audio/mpeg' }, // MP3
93
+ { bytes: [0xFF, 0xF1], format: 'aac', mime: 'audio/aac' }, // AAC
94
+ { bytes: [0xFF, 0xF9], format: 'aac', mime: 'audio/aac' }, // AAC
95
+ { bytes: [0x4F, 0x67, 0x67, 0x53], format: 'ogg', mime: 'audio/ogg' }, // OGG
96
+ ];
97
+ for (const sig of signatures) {
98
+ let matches = true;
99
+ for (let i = 0; i < sig.bytes.length; i++) {
100
+ if (buffer[i] !== sig.bytes[i]) {
101
+ matches = false;
102
+ break;
103
+ }
104
+ }
105
+ if (matches) {
106
+ return {
107
+ detected: true,
108
+ format: sig.format,
109
+ mime: sig.mime,
110
+ };
111
+ }
112
+ }
113
+ return { detected: false };
114
+ }
115
+ catch {
116
+ return { detected: false };
117
+ }
118
+ }
119
+ /**
120
+ * Perform HEAD request validation
121
+ */
122
+ async function validateWithHead(context) {
123
+ try {
124
+ const controller = new AbortController();
125
+ const headTimeout = Math.min(RADIO_VALIDATION.FALLBACK_HEAD_TIMEOUT, Math.floor(context.timeout * RADIO_VALIDATION.HEAD_TIMEOUT_RATIO)); // Use 60% of total timeout
126
+ const timeoutId = setTimeout(() => {
127
+ controller.abort();
128
+ }, headTimeout);
129
+ const response = await fetch(context.url, {
130
+ method: 'HEAD',
131
+ redirect: context.followRedirects ? 'follow' : 'manual',
132
+ signal: controller.signal,
133
+ headers: {
134
+ 'User-Agent': 'Mozilla/5.0 (compatible; NavidromeBot/1.0)',
135
+ 'Accept': 'audio/*',
136
+ },
137
+ });
138
+ clearTimeout(timeoutId);
139
+ return { response, error: null };
140
+ }
141
+ catch (err) {
142
+ if (err instanceof Error) {
143
+ if (err.name === 'AbortError') {
144
+ return { response: null, error: `HEAD request timeout after ${Math.min(RADIO_VALIDATION.FALLBACK_HEAD_TIMEOUT, Math.floor(context.timeout * RADIO_VALIDATION.HEAD_TIMEOUT_RATIO))}ms` };
145
+ }
146
+ return { response: null, error: `HEAD request failed: ${err.message}` };
147
+ }
148
+ return { response: null, error: 'Unknown HEAD request error' };
149
+ }
150
+ }
151
+ /**
152
+ * Sample audio data from stream
153
+ */
154
+ async function sampleAudioData(url, remainingTimeout) {
155
+ try {
156
+ const controller = new AbortController();
157
+ const sampleTimeout = Math.max(RADIO_VALIDATION.MIN_SAMPLE_TIMEOUT, remainingTimeout); // Ensure at least 2 seconds
158
+ const timeoutId = setTimeout(() => {
159
+ controller.abort();
160
+ }, sampleTimeout);
161
+ const response = await fetch(url, {
162
+ method: 'GET',
163
+ headers: {
164
+ 'Range': `bytes=0-${RADIO_VALIDATION.SAMPLE_BUFFER_SIZE - 1}`, // Get first 8KB
165
+ 'User-Agent': 'Mozilla/5.0 (compatible; NavidromeBot/1.0)',
166
+ 'Accept': 'audio/*',
167
+ },
168
+ signal: controller.signal,
169
+ });
170
+ clearTimeout(timeoutId);
171
+ if (!response.ok && response.status !== 206) {
172
+ return {
173
+ buffer: null,
174
+ headers: response.headers,
175
+ error: `HTTP ${response.status}: ${response.statusText}`
176
+ };
177
+ }
178
+ // Some servers don't handle Range requests properly and hang on arrayBuffer()
179
+ // Use streaming approach with timeout protection
180
+ try {
181
+ const reader = response.body?.getReader();
182
+ if (!reader) {
183
+ return {
184
+ buffer: null,
185
+ headers: response.headers,
186
+ error: 'No response body reader available'
187
+ };
188
+ }
189
+ const chunks = [];
190
+ let totalLength = 0;
191
+ const maxBytes = RADIO_VALIDATION.SAMPLE_BUFFER_SIZE; // 8KB limit
192
+ const startTime = Date.now();
193
+ const readTimeout = RADIO_VALIDATION.STREAM_READ_TIMEOUT; // 3 second timeout for reading
194
+ while (true) {
195
+ // Check if we've exceeded our read timeout
196
+ if (Date.now() - startTime > readTimeout) {
197
+ await reader.cancel();
198
+ return {
199
+ buffer: totalLength > 0 ? new Uint8Array(totalLength) : null,
200
+ headers: response.headers,
201
+ error: 'Read timeout - got partial data'
202
+ };
203
+ }
204
+ const { value, done } = await reader.read();
205
+ if (done)
206
+ break;
207
+ if (value) {
208
+ chunks.push(value);
209
+ totalLength += value.length;
210
+ // Stop if we have enough data
211
+ if (totalLength >= maxBytes) {
212
+ await reader.cancel();
213
+ break;
214
+ }
215
+ }
216
+ }
217
+ // Combine chunks
218
+ if (totalLength > 0) {
219
+ const buffer = new Uint8Array(totalLength);
220
+ let offset = 0;
221
+ for (const chunk of chunks) {
222
+ buffer.set(chunk, offset);
223
+ offset += chunk.length;
224
+ }
225
+ return {
226
+ buffer,
227
+ headers: response.headers,
228
+ error: null
229
+ };
230
+ }
231
+ else {
232
+ return {
233
+ buffer: null,
234
+ headers: response.headers,
235
+ error: 'No data received from stream'
236
+ };
237
+ }
238
+ }
239
+ catch (streamErr) {
240
+ if (streamErr instanceof Error && streamErr.name === 'AbortError') {
241
+ return { buffer: null, headers: response.headers, error: 'Stream reading aborted' };
242
+ }
243
+ throw streamErr;
244
+ }
245
+ }
246
+ catch (err) {
247
+ if (err instanceof Error) {
248
+ if (err.name === 'AbortError') {
249
+ return { buffer: null, headers: null, error: `Audio sampling timeout after ${Math.max(RADIO_VALIDATION.MIN_SAMPLE_TIMEOUT, remainingTimeout)}ms` };
250
+ }
251
+ return { buffer: null, headers: null, error: `Audio sampling failed: ${err.message}` };
252
+ }
253
+ return { buffer: null, headers: null, error: 'Unknown audio sampling error' };
254
+ }
255
+ }
256
+ /**
257
+ * Generate recommendations based on validation results
258
+ */
259
+ function generateRecommendations(result) {
260
+ const recommendations = [];
261
+ if (result.status === 'valid') {
262
+ recommendations.push('✅ Stream validated successfully');
263
+ if (result.streamingHeaders?.['icy-name']) {
264
+ recommendations.push(`🎵 Station: ${result.streamingHeaders['icy-name']}`);
265
+ }
266
+ if (result.streamingHeaders?.['icy-br']) {
267
+ recommendations.push(`📊 Bitrate: ${result.streamingHeaders['icy-br']}kbps`);
268
+ }
269
+ if (result.audioFormat?.format) {
270
+ recommendations.push(`🎧 Format: ${result.audioFormat.format.toUpperCase()}`);
271
+ }
272
+ recommendations.push('✨ Ready to add as radio station');
273
+ }
274
+ else if (result.status === 'invalid') {
275
+ recommendations.push('❌ Stream validation failed');
276
+ if (result.httpStatus === 404) {
277
+ recommendations.push('🔍 Stream URL appears to be offline or moved');
278
+ recommendations.push('💡 Check the station\'s official website for updated URLs');
279
+ }
280
+ else if (!result.validation?.hasAudioContentType) {
281
+ recommendations.push('⚠️ URL does not serve audio content');
282
+ recommendations.push('💡 Ensure you\'re using the stream URL, not the website URL');
283
+ }
284
+ else if (!result.validation?.audioDataDetected) {
285
+ recommendations.push('⚠️ Could not detect valid audio data');
286
+ recommendations.push('💡 The stream may be geo-restricted or require authentication');
287
+ }
288
+ recommendations.push('🌐 Try finding alternative streams at radio-browser.info');
289
+ }
290
+ else {
291
+ recommendations.push('⚠️ Stream validation encountered an error');
292
+ recommendations.push('🔄 Try again later or check your network connection');
293
+ }
294
+ return recommendations;
295
+ }
296
+ /**
297
+ * Validate a radio stream URL
298
+ */
299
+ export async function validateRadioStream(_client, args) {
300
+ const startTime = Date.now();
301
+ const errors = [];
302
+ const warnings = [];
303
+ // Parse and validate input
304
+ let params;
305
+ try {
306
+ params = ValidateStreamSchema.parse(args);
307
+ }
308
+ catch (error) {
309
+ if (error instanceof z.ZodError) {
310
+ return {
311
+ success: false,
312
+ url: String(args),
313
+ status: 'error',
314
+ streamingHeaders: {},
315
+ validation: {
316
+ httpAccessible: false,
317
+ hasAudioContentType: false,
318
+ hasStreamingHeaders: false,
319
+ audioDataDetected: false,
320
+ },
321
+ errors: [`Invalid parameters: ${error.issues.map((e) => e.message).join(', ')}`],
322
+ warnings: [],
323
+ recommendations: ['❌ Please provide a valid URL'],
324
+ testDuration: Date.now() - startTime,
325
+ };
326
+ }
327
+ throw error;
328
+ }
329
+ const context = {
330
+ url: params.url,
331
+ startTime,
332
+ timeout: params.timeout,
333
+ followRedirects: params.followRedirects,
334
+ };
335
+ // Initialize result
336
+ const result = {
337
+ success: false,
338
+ url: params.url,
339
+ status: 'invalid',
340
+ streamingHeaders: {},
341
+ validation: {
342
+ httpAccessible: false,
343
+ hasAudioContentType: false,
344
+ hasStreamingHeaders: false,
345
+ audioDataDetected: false,
346
+ },
347
+ errors,
348
+ warnings,
349
+ recommendations: [],
350
+ testDuration: 0,
351
+ };
352
+ // Add overall timeout protection
353
+ const overallController = new AbortController();
354
+ const overallTimeoutId = setTimeout(() => {
355
+ overallController.abort();
356
+ errors.push(`Validation timeout after ${params.timeout}ms`);
357
+ }, params.timeout);
358
+ let headResponse = null;
359
+ let headError = null;
360
+ let buffer = null;
361
+ let headers = null;
362
+ let sampleError = null;
363
+ try {
364
+ // Step 1: Try HEAD request first
365
+ const headResult = await validateWithHead(context);
366
+ headResponse = headResult.response;
367
+ headError = headResult.error;
368
+ if (headError) {
369
+ warnings.push(headError);
370
+ }
371
+ // Step 2: Check if HEAD response gives us enough info to determine validity
372
+ let skipAudioSampling = false;
373
+ if (headResponse) {
374
+ const contentType = headResponse.headers.get('content-type');
375
+ const streamHeaders = extractStreamingHeaders(headResponse.headers);
376
+ // If we have clear audio content-type OR streaming headers, we can skip audio sampling
377
+ const hasAudioContentType = contentType && isAudioContentType(contentType);
378
+ const hasStreamingHeaders = Object.keys(streamHeaders).length > 0;
379
+ if (hasAudioContentType || hasStreamingHeaders) {
380
+ skipAudioSampling = true;
381
+ // Create a fake successful result for audio detection based on content-type
382
+ buffer = new Uint8Array([0xFF, 0xFB]); // Minimal buffer to satisfy validation logic
383
+ headers = headResponse.headers;
384
+ sampleError = null;
385
+ }
386
+ }
387
+ // Step 3: Sample audio data only if headers were inconclusive
388
+ if (!skipAudioSampling) {
389
+ const elapsed = Date.now() - startTime;
390
+ const remainingTime = params.timeout - elapsed;
391
+ if (remainingTime > 1000 && !overallController.signal.aborted) {
392
+ const sampleResult = await sampleAudioData(params.url, remainingTime);
393
+ buffer = sampleResult.buffer;
394
+ headers = sampleResult.headers || headResponse?.headers || null;
395
+ sampleError = sampleResult.error;
396
+ }
397
+ else if (remainingTime <= 1000) {
398
+ sampleError = 'Insufficient time remaining for audio sampling';
399
+ }
400
+ }
401
+ }
402
+ catch (err) {
403
+ if (err instanceof Error && err.name === 'AbortError') {
404
+ errors.push('Validation aborted due to overall timeout');
405
+ }
406
+ else {
407
+ errors.push(`Validation failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
408
+ }
409
+ }
410
+ finally {
411
+ clearTimeout(overallTimeoutId);
412
+ }
413
+ if (sampleError && !headResponse) {
414
+ errors.push(sampleError);
415
+ result.status = 'error';
416
+ }
417
+ // Use whichever response we got
418
+ const finalResponse = headResponse || (headers ? { headers, ok: true, status: 200, url: params.url } : null);
419
+ if (finalResponse) {
420
+ result.httpStatus = finalResponse.status || 200;
421
+ result.validation.httpAccessible = true;
422
+ // Check for redirects
423
+ if (finalResponse.url && finalResponse.url !== params.url) {
424
+ result.finalUrl = finalResponse.url;
425
+ }
426
+ // Extract content type
427
+ const contentType = finalResponse.headers.get('content-type');
428
+ if (contentType) {
429
+ result.contentType = contentType;
430
+ result.validation.hasAudioContentType = isAudioContentType(contentType);
431
+ if (!result.validation.hasAudioContentType) {
432
+ errors.push(`Non-audio content type: ${contentType}`);
433
+ }
434
+ }
435
+ // Extract streaming headers
436
+ result.streamingHeaders = extractStreamingHeaders(finalResponse.headers);
437
+ result.validation.hasStreamingHeaders = Object.keys(result.streamingHeaders).length > 0;
438
+ }
439
+ // Step 3: Detect audio format if we got data
440
+ if (buffer && buffer.length > 0) {
441
+ const audioFormat = await detectAudioFormat(buffer);
442
+ result.audioFormat = audioFormat;
443
+ result.validation.audioDataDetected = audioFormat.detected;
444
+ if (!audioFormat.detected && result.validation.hasAudioContentType) {
445
+ warnings.push('Could not detect audio format from data sample');
446
+ }
447
+ }
448
+ else if (result.validation.httpAccessible) {
449
+ warnings.push('Could not sample audio data from stream');
450
+ }
451
+ // Determine overall success
452
+ result.success = result.validation.httpAccessible &&
453
+ (result.validation.hasAudioContentType ||
454
+ result.validation.audioDataDetected ||
455
+ result.validation.hasStreamingHeaders);
456
+ result.status = result.success ? 'valid' : (errors.length > 0 ? 'error' : 'invalid');
457
+ // Generate recommendations
458
+ result.recommendations = generateRecommendations(result);
459
+ // Set test duration
460
+ result.testDuration = Date.now() - startTime;
461
+ return result;
462
+ }
463
+ //# sourceMappingURL=radio-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-validation.js","sourceRoot":"","sources":["../../src/tools/radio-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { Config } from '../config.js';
2
+ import type { RadioStationDTO, CreateRadioStationResponse, DeleteRadioStationResponse, ListRadioStationsResponse, RadioPlaybackInfo } from '../types/index.js';
3
+ /**
4
+ * List all internet radio stations
5
+ */
6
+ export declare function listRadioStations(config: Config, args: unknown): Promise<ListRadioStationsResponse>;
7
+ /**
8
+ * Create a new radio station
9
+ */
10
+ export declare function createRadioStation(config: Config, args: unknown): Promise<CreateRadioStationResponse>;
11
+ /**
12
+ * Delete a radio station by ID
13
+ */
14
+ export declare function deleteRadioStation(config: Config, args: unknown): Promise<DeleteRadioStationResponse>;
15
+ /**
16
+ * Get a specific radio station by ID
17
+ */
18
+ export declare function getRadioStation(config: Config, args: unknown): Promise<RadioStationDTO>;
19
+ /**
20
+ * Play a radio station (sets it in the queue)
21
+ */
22
+ export declare function playRadioStation(config: Config, args: unknown): Promise<{
23
+ success: boolean;
24
+ message: string;
25
+ station?: RadioStationDTO;
26
+ }>;
27
+ /**
28
+ * Batch create multiple radio stations
29
+ */
30
+ export declare function batchCreateRadioStations(config: Config, args: unknown): Promise<{
31
+ results: CreateRadioStationResponse[];
32
+ summary: string;
33
+ }>;
34
+ /**
35
+ * Get current radio playback information
36
+ */
37
+ export declare function getCurrentRadioInfo(_config: Config, _args: unknown): Promise<RadioPlaybackInfo>;
38
+ //# sourceMappingURL=radio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../../src/tools/radio.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EACV,eAAe,EAEf,0BAA0B,EAC1B,0BAA0B,EAC1B,yBAAyB,EACzB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAyC3B;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,yBAAyB,CAAC,CAsDpC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAsFrC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAuCrC;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,eAAe,CAAC,CAwB1B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,CAAC,CA+B3E;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA4DrE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,CA2B5B"}