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.
- package/LICENSE +661 -0
- package/README.md +397 -0
- package/dist/capabilities.d.ts +20 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +25 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/client/auth-manager.d.ts +27 -0
- package/dist/client/auth-manager.d.ts.map +1 -0
- package/dist/client/auth-manager.js +54 -0
- package/dist/client/auth-manager.js.map +1 -0
- package/dist/client/navidrome-client.d.ts +28 -0
- package/dist/client/navidrome-client.d.ts.map +1 -0
- package/dist/client/navidrome-client.js +84 -0
- package/dist/client/navidrome-client.js.map +1 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +132 -0
- package/dist/config.js.map +1 -0
- package/dist/constants/defaults.d.ts +29 -0
- package/dist/constants/defaults.d.ts.map +1 -0
- package/dist/constants/defaults.js +37 -0
- package/dist/constants/defaults.js.map +1 -0
- package/dist/constants/timeouts.d.ts +66 -0
- package/dist/constants/timeouts.d.ts.map +1 -0
- package/dist/constants/timeouts.js +66 -0
- package/dist/constants/timeouts.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +21 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +83 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/schemas/common.d.ts +68 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +69 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/index.d.ts +21 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +24 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/pagination.d.ts +153 -0
- package/dist/schemas/pagination.d.ts.map +1 -0
- package/dist/schemas/pagination.js +93 -0
- package/dist/schemas/pagination.js.map +1 -0
- package/dist/schemas/validation.d.ts +147 -0
- package/dist/schemas/validation.d.ts.map +1 -0
- package/dist/schemas/validation.js +143 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/tools/handlers/lastfm-handlers.d.ts +5 -0
- package/dist/tools/handlers/lastfm-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lastfm-handlers.js +143 -0
- package/dist/tools/handlers/lastfm-handlers.js.map +1 -0
- package/dist/tools/handlers/lyrics-handlers.d.ts +5 -0
- package/dist/tools/handlers/lyrics-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/lyrics-handlers.js +51 -0
- package/dist/tools/handlers/lyrics-handlers.js.map +1 -0
- package/dist/tools/handlers/playlist-handlers.d.ts +5 -0
- package/dist/tools/handlers/playlist-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/playlist-handlers.js +316 -0
- package/dist/tools/handlers/playlist-handlers.js.map +1 -0
- package/dist/tools/handlers/queue-handlers.d.ts +5 -0
- package/dist/tools/handlers/queue-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/queue-handlers.js +135 -0
- package/dist/tools/handlers/queue-handlers.js.map +1 -0
- package/dist/tools/handlers/radio-handlers.d.ts +5 -0
- package/dist/tools/handlers/radio-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/radio-handlers.js +323 -0
- package/dist/tools/handlers/radio-handlers.js.map +1 -0
- package/dist/tools/handlers/registry.d.ts +26 -0
- package/dist/tools/handlers/registry.d.ts.map +1 -0
- package/dist/tools/handlers/registry.js +77 -0
- package/dist/tools/handlers/registry.js.map +1 -0
- package/dist/tools/handlers/search-handlers.d.ts +5 -0
- package/dist/tools/handlers/search-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/search-handlers.js +125 -0
- package/dist/tools/handlers/search-handlers.js.map +1 -0
- package/dist/tools/handlers/tag-handlers.d.ts +5 -0
- package/dist/tools/handlers/tag-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/tag-handlers.js +155 -0
- package/dist/tools/handlers/tag-handlers.js.map +1 -0
- package/dist/tools/handlers/user-preferences-handlers.d.ts +5 -0
- package/dist/tools/handlers/user-preferences-handlers.d.ts.map +1 -0
- package/dist/tools/handlers/user-preferences-handlers.js +155 -0
- package/dist/tools/handlers/user-preferences-handlers.js.map +1 -0
- package/dist/tools/index.d.ts +19 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lastfm-discovery.d.ts +107 -0
- package/dist/tools/lastfm-discovery.d.ts.map +1 -0
- package/dist/tools/lastfm-discovery.js +238 -0
- package/dist/tools/lastfm-discovery.js.map +1 -0
- package/dist/tools/library.d.ts +31 -0
- package/dist/tools/library.d.ts.map +1 -0
- package/dist/tools/library.js +272 -0
- package/dist/tools/library.js.map +1 -0
- package/dist/tools/listening-history.d.ts +51 -0
- package/dist/tools/listening-history.d.ts.map +1 -0
- package/dist/tools/listening-history.js +126 -0
- package/dist/tools/listening-history.js.map +1 -0
- package/dist/tools/lyrics.d.ts +35 -0
- package/dist/tools/lyrics.d.ts.map +1 -0
- package/dist/tools/lyrics.js +222 -0
- package/dist/tools/lyrics.js.map +1 -0
- package/dist/tools/media-library.d.ts +46 -0
- package/dist/tools/media-library.d.ts.map +1 -0
- package/dist/tools/media-library.js +179 -0
- package/dist/tools/media-library.js.map +1 -0
- package/dist/tools/playlist-management.d.ts +80 -0
- package/dist/tools/playlist-management.d.ts.map +1 -0
- package/dist/tools/playlist-management.js +384 -0
- package/dist/tools/playlist-management.js.map +1 -0
- package/dist/tools/queue-management.d.ts +48 -0
- package/dist/tools/queue-management.d.ts.map +1 -0
- package/dist/tools/queue-management.js +83 -0
- package/dist/tools/queue-management.js.map +1 -0
- package/dist/tools/radio-discovery.d.ts +95 -0
- package/dist/tools/radio-discovery.d.ts.map +1 -0
- package/dist/tools/radio-discovery.js +352 -0
- package/dist/tools/radio-discovery.js.map +1 -0
- package/dist/tools/radio-validation.d.ts +49 -0
- package/dist/tools/radio-validation.d.ts.map +1 -0
- package/dist/tools/radio-validation.js +463 -0
- package/dist/tools/radio-validation.js.map +1 -0
- package/dist/tools/radio.d.ts +38 -0
- package/dist/tools/radio.d.ts.map +1 -0
- package/dist/tools/radio.js +315 -0
- package/dist/tools/radio.js.map +1 -0
- package/dist/tools/search.d.ts +54 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +165 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/tags.d.ts +63 -0
- package/dist/tools/tags.d.ts.map +1 -0
- package/dist/tools/tags.js +260 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/test.d.ts +50 -0
- package/dist/tools/test.d.ts.map +1 -0
- package/dist/tools/test.js +121 -0
- package/dist/tools/test.js.map +1 -0
- package/dist/tools/user-preferences.d.ts +73 -0
- package/dist/tools/user-preferences.d.ts.map +1 -0
- package/dist/tools/user-preferences.js +231 -0
- package/dist/tools/user-preferences.js.map +1 -0
- package/dist/transformers/song-transformer.d.ts +122 -0
- package/dist/transformers/song-transformer.d.ts.map +1 -0
- package/dist/transformers/song-transformer.js +232 -0
- package/dist/transformers/song-transformer.js.map +1 -0
- package/dist/types/core.d.ts +147 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +19 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lyrics.d.ts +58 -0
- package/dist/types/lyrics.d.ts.map +1 -0
- package/dist/types/lyrics.js +19 -0
- package/dist/types/lyrics.js.map +1 -0
- package/dist/types/playlists.d.ts +150 -0
- package/dist/types/playlists.d.ts.map +1 -0
- package/dist/types/playlists.js +19 -0
- package/dist/types/playlists.js.map +1 -0
- package/dist/types/radio.d.ts +192 -0
- package/dist/types/radio.d.ts.map +1 -0
- package/dist/types/radio.js +19 -0
- package/dist/types/radio.js.map +1 -0
- package/dist/types/tags.d.ts +72 -0
- package/dist/types/tags.d.ts.map +1 -0
- package/dist/types/tags.js +19 -0
- package/dist/types/tags.js.map +1 -0
- package/dist/utils/cache.d.ts +32 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +84 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/error-formatter.d.ts +108 -0
- package/dist/utils/error-formatter.d.ts.map +1 -0
- package/dist/utils/error-formatter.js +161 -0
- package/dist/utils/error-formatter.js.map +1 -0
- package/dist/utils/logger.d.ts +33 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +52 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/message-manager.d.ts +74 -0
- package/dist/utils/message-manager.d.ts.map +1 -0
- package/dist/utils/message-manager.js +134 -0
- package/dist/utils/message-manager.js.map +1 -0
- package/dist/utils/version.d.ts +5 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +19 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import { logger } from '../utils/logger.js';
|
|
3
|
+
import { getMessageManager } from '../utils/message-manager.js';
|
|
4
|
+
import { BATCH_VALIDATION_TIMEOUT } from '../constants/timeouts.js';
|
|
5
|
+
import { ErrorFormatter } from '../utils/error-formatter.js';
|
|
6
|
+
function createSubsonicAuth(config) {
|
|
7
|
+
const salt = crypto.randomBytes(16).toString('hex');
|
|
8
|
+
const token = crypto.createHash('md5').update(config.navidromePassword + salt).digest('hex');
|
|
9
|
+
return new URLSearchParams({
|
|
10
|
+
u: config.navidromeUsername,
|
|
11
|
+
t: token,
|
|
12
|
+
s: salt,
|
|
13
|
+
v: '1.16.1',
|
|
14
|
+
c: 'NavidromeMCP',
|
|
15
|
+
f: 'json',
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* List all internet radio stations
|
|
20
|
+
*/
|
|
21
|
+
export async function listRadioStations(config, args) {
|
|
22
|
+
try {
|
|
23
|
+
logger.debug('Listing radio stations', args);
|
|
24
|
+
const authParams = createSubsonicAuth(config);
|
|
25
|
+
const httpResponse = await fetch(`${config.navidromeUrl}/rest/getInternetRadioStations?${authParams.toString()}`);
|
|
26
|
+
if (!httpResponse.ok) {
|
|
27
|
+
throw new Error(ErrorFormatter.subsonicApi(httpResponse));
|
|
28
|
+
}
|
|
29
|
+
const data = await httpResponse.json();
|
|
30
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
31
|
+
const errorMsg = data['subsonic-response'].error?.message || 'Unknown error';
|
|
32
|
+
throw new Error(ErrorFormatter.subsonicResponse(errorMsg));
|
|
33
|
+
}
|
|
34
|
+
const radioStations = data['subsonic-response'].internetRadioStations?.internetRadioStation || [];
|
|
35
|
+
const stations = radioStations.map(station => {
|
|
36
|
+
const stationDto = {
|
|
37
|
+
id: station.id,
|
|
38
|
+
name: station.name,
|
|
39
|
+
streamUrl: station.streamUrl,
|
|
40
|
+
createdAt: new Date().toISOString(), // Subsonic API doesn't provide timestamps
|
|
41
|
+
updatedAt: new Date().toISOString(),
|
|
42
|
+
};
|
|
43
|
+
if (station.homePageUrl) {
|
|
44
|
+
stationDto.homePageUrl = station.homePageUrl;
|
|
45
|
+
}
|
|
46
|
+
return stationDto;
|
|
47
|
+
});
|
|
48
|
+
// Get one-time message for radio list tip
|
|
49
|
+
const messageManager = getMessageManager();
|
|
50
|
+
const tip = messageManager.getMessage('radio.list_tip');
|
|
51
|
+
const apiResponse = {
|
|
52
|
+
stations,
|
|
53
|
+
total: stations.length,
|
|
54
|
+
};
|
|
55
|
+
// Add tip if this is the first time showing the list
|
|
56
|
+
if (tip) {
|
|
57
|
+
apiResponse.tip = tip;
|
|
58
|
+
}
|
|
59
|
+
return apiResponse;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
logger.error('Error listing radio stations:', error);
|
|
63
|
+
throw new Error(ErrorFormatter.toolExecution('listRadioStations', error));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create a new radio station
|
|
68
|
+
*/
|
|
69
|
+
export async function createRadioStation(config, args) {
|
|
70
|
+
try {
|
|
71
|
+
const params = args;
|
|
72
|
+
if (!params.name || !params.streamUrl) {
|
|
73
|
+
throw new Error('Name and streamUrl are required');
|
|
74
|
+
}
|
|
75
|
+
logger.debug('Creating radio station:', params);
|
|
76
|
+
// If validation is requested, validate the stream first
|
|
77
|
+
if (params.validateBeforeAdd) {
|
|
78
|
+
const { validateRadioStream } = await import('./radio-validation.js');
|
|
79
|
+
const { NavidromeClient } = await import('../client/navidrome-client.js');
|
|
80
|
+
const client = new NavidromeClient(config);
|
|
81
|
+
await client.initialize();
|
|
82
|
+
const validationResult = await validateRadioStream(client, {
|
|
83
|
+
url: params.streamUrl,
|
|
84
|
+
timeout: BATCH_VALIDATION_TIMEOUT
|
|
85
|
+
});
|
|
86
|
+
if (!validationResult.success) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: `Stream validation failed: ${validationResult.status}. Station was not added.`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const authParams = createSubsonicAuth(config);
|
|
94
|
+
authParams.set('streamUrl', params.streamUrl);
|
|
95
|
+
authParams.set('name', params.name);
|
|
96
|
+
if (params.homePageUrl) {
|
|
97
|
+
authParams.set('homePageUrl', params.homePageUrl);
|
|
98
|
+
}
|
|
99
|
+
const httpResponse = await fetch(`${config.navidromeUrl}/rest/createInternetRadioStation?${authParams.toString()}`, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
});
|
|
102
|
+
if (!httpResponse.ok) {
|
|
103
|
+
throw new Error(ErrorFormatter.subsonicApi(httpResponse));
|
|
104
|
+
}
|
|
105
|
+
const data = await httpResponse.json();
|
|
106
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
107
|
+
const errorMsg = data['subsonic-response'].error?.message || 'Unknown error';
|
|
108
|
+
throw new Error(ErrorFormatter.subsonicResponse(errorMsg));
|
|
109
|
+
}
|
|
110
|
+
const createdStation = {
|
|
111
|
+
id: 'created', // Subsonic API doesn't return the created station details
|
|
112
|
+
name: params.name,
|
|
113
|
+
streamUrl: params.streamUrl,
|
|
114
|
+
createdAt: new Date().toISOString(),
|
|
115
|
+
updatedAt: new Date().toISOString(),
|
|
116
|
+
};
|
|
117
|
+
if (params.homePageUrl) {
|
|
118
|
+
createdStation.homePageUrl = params.homePageUrl;
|
|
119
|
+
}
|
|
120
|
+
// Get one-time validation reminder message
|
|
121
|
+
const messageManager = getMessageManager();
|
|
122
|
+
const validationReminder = messageManager.getMessage('radio.validation_reminder');
|
|
123
|
+
const apiResponse = {
|
|
124
|
+
success: true,
|
|
125
|
+
station: createdStation,
|
|
126
|
+
};
|
|
127
|
+
// Add validation reminder if this is the first time creating a station
|
|
128
|
+
if (validationReminder) {
|
|
129
|
+
apiResponse.validation_reminder = validationReminder;
|
|
130
|
+
}
|
|
131
|
+
return apiResponse;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
logger.error('Error creating radio station:', error);
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Delete a radio station by ID
|
|
143
|
+
*/
|
|
144
|
+
export async function deleteRadioStation(config, args) {
|
|
145
|
+
try {
|
|
146
|
+
const params = args;
|
|
147
|
+
if (!params.id) {
|
|
148
|
+
throw new Error('Radio station ID is required');
|
|
149
|
+
}
|
|
150
|
+
logger.debug('Deleting radio station:', params.id);
|
|
151
|
+
const authParams = createSubsonicAuth(config);
|
|
152
|
+
authParams.set('id', params.id);
|
|
153
|
+
const httpResponse = await fetch(`${config.navidromeUrl}/rest/deleteInternetRadioStation?${authParams.toString()}`, {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
});
|
|
156
|
+
if (!httpResponse.ok) {
|
|
157
|
+
throw new Error(ErrorFormatter.subsonicApi(httpResponse));
|
|
158
|
+
}
|
|
159
|
+
const data = await httpResponse.json();
|
|
160
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
161
|
+
const errorMsg = data['subsonic-response'].error?.message || 'Unknown error';
|
|
162
|
+
throw new Error(ErrorFormatter.subsonicResponse(errorMsg));
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
success: true,
|
|
166
|
+
id: params.id,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
logger.error('Error deleting radio station:', error);
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get a specific radio station by ID
|
|
179
|
+
*/
|
|
180
|
+
export async function getRadioStation(config, args) {
|
|
181
|
+
try {
|
|
182
|
+
const params = args;
|
|
183
|
+
if (!params.id) {
|
|
184
|
+
throw new Error('Radio station ID is required');
|
|
185
|
+
}
|
|
186
|
+
logger.debug('Getting radio station:', params.id);
|
|
187
|
+
// Since Subsonic API doesn't have a get single station endpoint,
|
|
188
|
+
// we'll get all stations and filter by ID
|
|
189
|
+
const allStations = await listRadioStations(config, {});
|
|
190
|
+
const station = allStations.stations.find(s => s.id === params.id);
|
|
191
|
+
if (!station) {
|
|
192
|
+
throw new Error(`Radio station with ID ${params.id} not found`);
|
|
193
|
+
}
|
|
194
|
+
return station;
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
logger.error('Error getting radio station:', error);
|
|
198
|
+
throw new Error(ErrorFormatter.toolExecution('getRadioStation', error));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Play a radio station (sets it in the queue)
|
|
203
|
+
*/
|
|
204
|
+
export async function playRadioStation(config, args) {
|
|
205
|
+
try {
|
|
206
|
+
const params = args;
|
|
207
|
+
if (!params.id) {
|
|
208
|
+
throw new Error('Radio station ID is required');
|
|
209
|
+
}
|
|
210
|
+
logger.debug('Playing radio station:', params.id);
|
|
211
|
+
// First get the station details
|
|
212
|
+
const station = await getRadioStation(config, params);
|
|
213
|
+
// Note: The actual playback implementation would require additional Subsonic API calls
|
|
214
|
+
// to set up playback. For now, we'll return success with the station info.
|
|
215
|
+
// In a full implementation, this might involve:
|
|
216
|
+
// 1. Calling setQueue to set up radio playback
|
|
217
|
+
// 2. Using stream endpoint to start playing
|
|
218
|
+
return {
|
|
219
|
+
success: true,
|
|
220
|
+
message: `Radio station "${station.name}" is ready to play. Stream URL: ${station.streamUrl}`,
|
|
221
|
+
station,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
logger.error('Error playing radio station:', error);
|
|
226
|
+
return {
|
|
227
|
+
success: false,
|
|
228
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Batch create multiple radio stations
|
|
234
|
+
*/
|
|
235
|
+
export async function batchCreateRadioStations(config, args) {
|
|
236
|
+
const params = args;
|
|
237
|
+
if (!params.stations || !Array.isArray(params.stations)) {
|
|
238
|
+
throw new Error('Stations array is required');
|
|
239
|
+
}
|
|
240
|
+
if (params.stations.length === 0) {
|
|
241
|
+
throw new Error('At least one station must be provided');
|
|
242
|
+
}
|
|
243
|
+
logger.debug(`Batch creating ${params.stations.length} radio stations`);
|
|
244
|
+
const results = [];
|
|
245
|
+
let successCount = 0;
|
|
246
|
+
let failedCount = 0;
|
|
247
|
+
let validationFailedCount = 0;
|
|
248
|
+
for (const station of params.stations) {
|
|
249
|
+
try {
|
|
250
|
+
const result = await createRadioStation(config, {
|
|
251
|
+
...station,
|
|
252
|
+
validateBeforeAdd: params.validateBeforeAdd
|
|
253
|
+
});
|
|
254
|
+
results.push(result);
|
|
255
|
+
if (result.success) {
|
|
256
|
+
successCount++;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
failedCount++;
|
|
260
|
+
if (result.error?.includes('validation failed')) {
|
|
261
|
+
validationFailedCount++;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
results.push({
|
|
267
|
+
success: false,
|
|
268
|
+
error: `Failed to add ${station.name}: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
269
|
+
});
|
|
270
|
+
failedCount++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
let summary = `Added ${successCount} of ${params.stations.length} stations.`;
|
|
274
|
+
if (failedCount > 0) {
|
|
275
|
+
summary += ` ${failedCount} failed`;
|
|
276
|
+
if (validationFailedCount > 0) {
|
|
277
|
+
summary += ` (${validationFailedCount} due to validation)`;
|
|
278
|
+
}
|
|
279
|
+
summary += '.';
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
results,
|
|
283
|
+
summary
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Get current radio playback information
|
|
288
|
+
*/
|
|
289
|
+
export async function getCurrentRadioInfo(_config, _args) {
|
|
290
|
+
try {
|
|
291
|
+
logger.debug('Getting current radio info');
|
|
292
|
+
// Note: This implementation depends on Navidrome's current playback status API
|
|
293
|
+
// The Subsonic API has getNowPlaying but it's for regular tracks, not radio streams
|
|
294
|
+
// This is a placeholder implementation that would need to be adjusted based on
|
|
295
|
+
// the actual Navidrome radio status endpoints
|
|
296
|
+
// For now, we'll return a basic response indicating no radio is currently playing
|
|
297
|
+
// In a real implementation, this would query the current playback status
|
|
298
|
+
return {
|
|
299
|
+
playing: false,
|
|
300
|
+
metadata: {
|
|
301
|
+
description: 'Radio playback status not available - use getNowPlaying for regular track status',
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
logger.error('Error getting current radio info:', error);
|
|
307
|
+
return {
|
|
308
|
+
playing: false,
|
|
309
|
+
metadata: {
|
|
310
|
+
description: `Error getting radio info: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=radio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radio.js","sourceRoot":"","sources":["../../src/tools/radio.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Search Tools
|
|
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 type { Config } from '../config.js';
|
|
19
|
+
import type { SongDTO, AlbumDTO, ArtistDTO } from '../types/index.js';
|
|
20
|
+
/**
|
|
21
|
+
* Search across all content types (artists, albums, songs)
|
|
22
|
+
*/
|
|
23
|
+
export declare function searchAll(config: Config, args: unknown): Promise<{
|
|
24
|
+
artists: ArtistDTO[];
|
|
25
|
+
albums: AlbumDTO[];
|
|
26
|
+
songs: SongDTO[];
|
|
27
|
+
query: string;
|
|
28
|
+
totalResults: number;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Search for songs only
|
|
32
|
+
*/
|
|
33
|
+
export declare function searchSongs(config: Config, args: unknown): Promise<{
|
|
34
|
+
songs: SongDTO[];
|
|
35
|
+
query: string;
|
|
36
|
+
total: number;
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Search for albums only
|
|
40
|
+
*/
|
|
41
|
+
export declare function searchAlbums(config: Config, args: unknown): Promise<{
|
|
42
|
+
albums: AlbumDTO[];
|
|
43
|
+
query: string;
|
|
44
|
+
total: number;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Search for artists only
|
|
48
|
+
*/
|
|
49
|
+
export declare function searchArtists(config: Config, args: unknown): Promise<{
|
|
50
|
+
artists: ArtistDTO[];
|
|
51
|
+
query: string;
|
|
52
|
+
total: number;
|
|
53
|
+
}>;
|
|
54
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAuCtE;;GAEG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACtE,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAsCD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxE,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAmCD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACzE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAmCD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1E,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAmCD"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Search Tools
|
|
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 { transformSongsToDTO, transformAlbumsToDTO, transformArtistsToDTO } from '../transformers/song-transformer.js';
|
|
19
|
+
import crypto from 'crypto';
|
|
20
|
+
import { ErrorFormatter } from '../utils/error-formatter.js';
|
|
21
|
+
import { SearchAllSchema, SearchSongsSchema, SearchAlbumsSchema, SearchArtistsSchema, } from '../schemas/index.js';
|
|
22
|
+
/**
|
|
23
|
+
* Create Subsonic API authentication parameters
|
|
24
|
+
*/
|
|
25
|
+
function createSubsonicAuth(config) {
|
|
26
|
+
const salt = crypto.randomBytes(16).toString('hex');
|
|
27
|
+
const token = crypto.createHash('md5').update(config.navidromePassword + salt).digest('hex');
|
|
28
|
+
return new URLSearchParams({
|
|
29
|
+
u: config.navidromeUsername,
|
|
30
|
+
t: token,
|
|
31
|
+
s: salt,
|
|
32
|
+
v: '1.16.1',
|
|
33
|
+
c: 'NavidromeMCP',
|
|
34
|
+
f: 'json',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Search across all content types (artists, albums, songs)
|
|
39
|
+
*/
|
|
40
|
+
export async function searchAll(config, args) {
|
|
41
|
+
const params = SearchAllSchema.parse(args);
|
|
42
|
+
try {
|
|
43
|
+
const searchParams = createSubsonicAuth(config);
|
|
44
|
+
searchParams.set('query', params.query);
|
|
45
|
+
searchParams.set('artistCount', params.artistCount.toString());
|
|
46
|
+
searchParams.set('albumCount', params.albumCount.toString());
|
|
47
|
+
searchParams.set('songCount', params.songCount.toString());
|
|
48
|
+
const response = await fetch(`${config.navidromeUrl}/rest/search3?${searchParams.toString()}`);
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
throw new Error(ErrorFormatter.apiRequest('search', response));
|
|
51
|
+
}
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
54
|
+
throw new Error(ErrorFormatter.apiResponse('search'));
|
|
55
|
+
}
|
|
56
|
+
const searchResult = data['subsonic-response'].searchResult3 || {};
|
|
57
|
+
const artists = transformArtistsToDTO(searchResult.artist || []);
|
|
58
|
+
const albums = transformAlbumsToDTO(searchResult.album || []);
|
|
59
|
+
const songs = transformSongsToDTO(searchResult.song || []);
|
|
60
|
+
return {
|
|
61
|
+
artists,
|
|
62
|
+
albums,
|
|
63
|
+
songs,
|
|
64
|
+
query: params.query,
|
|
65
|
+
totalResults: artists.length + albums.length + songs.length,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new Error(ErrorFormatter.operationFailed('search', error));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Search for songs only
|
|
74
|
+
*/
|
|
75
|
+
export async function searchSongs(config, args) {
|
|
76
|
+
const params = SearchSongsSchema.parse(args);
|
|
77
|
+
try {
|
|
78
|
+
const searchParams = createSubsonicAuth(config);
|
|
79
|
+
searchParams.set('query', params.query);
|
|
80
|
+
searchParams.set('artistCount', '0');
|
|
81
|
+
searchParams.set('albumCount', '0');
|
|
82
|
+
searchParams.set('songCount', params.limit.toString());
|
|
83
|
+
const response = await fetch(`${config.navidromeUrl}/rest/search3?${searchParams.toString()}`);
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
throw new Error(ErrorFormatter.apiRequest('search', response));
|
|
86
|
+
}
|
|
87
|
+
const data = await response.json();
|
|
88
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
89
|
+
throw new Error(ErrorFormatter.apiResponse('search'));
|
|
90
|
+
}
|
|
91
|
+
const searchResult = data['subsonic-response'].searchResult3 || {};
|
|
92
|
+
const songs = transformSongsToDTO(searchResult.song || []);
|
|
93
|
+
return {
|
|
94
|
+
songs,
|
|
95
|
+
query: params.query,
|
|
96
|
+
total: songs.length,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
throw new Error(`Failed to search songs: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Search for albums only
|
|
105
|
+
*/
|
|
106
|
+
export async function searchAlbums(config, args) {
|
|
107
|
+
const params = SearchAlbumsSchema.parse(args);
|
|
108
|
+
try {
|
|
109
|
+
const searchParams = createSubsonicAuth(config);
|
|
110
|
+
searchParams.set('query', params.query);
|
|
111
|
+
searchParams.set('artistCount', '0');
|
|
112
|
+
searchParams.set('albumCount', params.limit.toString());
|
|
113
|
+
searchParams.set('songCount', '0');
|
|
114
|
+
const response = await fetch(`${config.navidromeUrl}/rest/search3?${searchParams.toString()}`);
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(ErrorFormatter.apiRequest('search', response));
|
|
117
|
+
}
|
|
118
|
+
const data = await response.json();
|
|
119
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
120
|
+
throw new Error(ErrorFormatter.apiResponse('search'));
|
|
121
|
+
}
|
|
122
|
+
const searchResult = data['subsonic-response'].searchResult3 || {};
|
|
123
|
+
const albums = transformAlbumsToDTO(searchResult.album || []);
|
|
124
|
+
return {
|
|
125
|
+
albums,
|
|
126
|
+
query: params.query,
|
|
127
|
+
total: albums.length,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new Error(`Failed to search albums: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Search for artists only
|
|
136
|
+
*/
|
|
137
|
+
export async function searchArtists(config, args) {
|
|
138
|
+
const params = SearchArtistsSchema.parse(args);
|
|
139
|
+
try {
|
|
140
|
+
const searchParams = createSubsonicAuth(config);
|
|
141
|
+
searchParams.set('query', params.query);
|
|
142
|
+
searchParams.set('artistCount', params.limit.toString());
|
|
143
|
+
searchParams.set('albumCount', '0');
|
|
144
|
+
searchParams.set('songCount', '0');
|
|
145
|
+
const response = await fetch(`${config.navidromeUrl}/rest/search3?${searchParams.toString()}`);
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
throw new Error(ErrorFormatter.apiRequest('search', response));
|
|
148
|
+
}
|
|
149
|
+
const data = await response.json();
|
|
150
|
+
if (data['subsonic-response'].status !== 'ok') {
|
|
151
|
+
throw new Error(ErrorFormatter.apiResponse('search'));
|
|
152
|
+
}
|
|
153
|
+
const searchResult = data['subsonic-response'].searchResult3 || {};
|
|
154
|
+
const artists = transformArtistsToDTO(searchResult.artist || []);
|
|
155
|
+
return {
|
|
156
|
+
artists,
|
|
157
|
+
query: params.query,
|
|
158
|
+
total: artists.length,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
throw new Error(`Failed to search artists: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Navidrome MCP Server - Tag Management Tools
|
|
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 type { NavidromeClient } from '../client/navidrome-client.js';
|
|
19
|
+
import type { TagDTO, ListTagsResponse, TagDistributionResponse } from '../types/index.js';
|
|
20
|
+
export type ListTagsResult = ListTagsResponse;
|
|
21
|
+
export interface GetTagResult {
|
|
22
|
+
tag: TagDTO;
|
|
23
|
+
}
|
|
24
|
+
export interface SearchByTagsResult {
|
|
25
|
+
tagName: string;
|
|
26
|
+
tagValue: string | undefined;
|
|
27
|
+
matches: TagDTO[];
|
|
28
|
+
total: number;
|
|
29
|
+
}
|
|
30
|
+
export type GetTagDistributionResult = TagDistributionResponse;
|
|
31
|
+
export interface ListUniqueTagsResult {
|
|
32
|
+
tagNames: Array<{
|
|
33
|
+
name: string;
|
|
34
|
+
totalValues: number;
|
|
35
|
+
totalSongs: number;
|
|
36
|
+
totalAlbums: number;
|
|
37
|
+
topValues: TagDTO[];
|
|
38
|
+
}>;
|
|
39
|
+
total: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* List all tags with optional filtering and pagination
|
|
43
|
+
* Note: API filtering is broken, so we use client-side filtering
|
|
44
|
+
*/
|
|
45
|
+
export declare function listTags(client: NavidromeClient, args: unknown): Promise<ListTagsResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Get a specific tag by ID
|
|
48
|
+
*/
|
|
49
|
+
export declare function getTag(client: NavidromeClient, args: unknown): Promise<GetTagResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Search for tags by tag name and optionally tag value
|
|
52
|
+
* Note: API filtering is broken, so we use client-side filtering
|
|
53
|
+
*/
|
|
54
|
+
export declare function searchByTags(client: NavidromeClient, args: unknown): Promise<SearchByTagsResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Get distribution analysis of tags, optionally filtered by tag names
|
|
57
|
+
*/
|
|
58
|
+
export declare function getTagDistribution(client: NavidromeClient, args: unknown): Promise<GetTagDistributionResult>;
|
|
59
|
+
/**
|
|
60
|
+
* List all unique tag names with statistics
|
|
61
|
+
*/
|
|
62
|
+
export declare function listUniqueTags(client: NavidromeClient, args: unknown): Promise<ListUniqueTagsResult>;
|
|
63
|
+
//# sourceMappingURL=tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EACV,MAAM,EACN,gBAAgB,EAChB,uBAAuB,EAExB,MAAM,mBAAmB,CAAC;AAS3B,MAAM,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,wBAAwB,GAAG,uBAAuB,CAAC;AAE/D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC,CAAC;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAgCD;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CA8D9F;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAa1F;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiCtG;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAgElH;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA2D1G"}
|