Merge pull request #362 from DanTheMan827/hifi-api

Fix API caching and enhance query handling for testing
This commit is contained in:
edidealt 2026-03-20 19:00:17 +02:00 committed by GitHub
commit 5d0d375242
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -21,7 +21,7 @@ import { isCustomFormat } from './ffmpegFormats.ts';
import { DownloadProgress } from './progressEvents.js'; import { DownloadProgress } from './progressEvents.js';
import { resolveDownloadTotalBytes } from './downloadProgressUtils.js'; import { resolveDownloadTotalBytes } from './downloadProgressUtils.js';
import { readableStreamIterator } from './readableStreamIterator.js'; import { readableStreamIterator } from './readableStreamIterator.js';
import { HiFiClient } from './HiFi.ts'; import { HiFiClient, TidalResponse } from './HiFi.ts';
export const DASH_MANIFEST_UNAVAILABLE_CODE = 'DASH_MANIFEST_UNAVAILABLE'; export const DASH_MANIFEST_UNAVAILABLE_CODE = 'DASH_MANIFEST_UNAVAILABLE';
export { resolveDownloadTotalBytes }; export { resolveDownloadTotalBytes };
@ -58,7 +58,7 @@ export class LosslessAPI {
const type = options.type || 'api'; const type = options.type || 'api';
const instanceRoutes = ['/track', '/album/similar', '/artist/similar', '/video']; const instanceRoutes = ['/track', '/album/similar', '/artist/similar', '/video'];
if (!instanceRoutes.some((route) => relativePath.startsWith(route))) { if (window.allTidal == true || !instanceRoutes.some((route) => relativePath.startsWith(route))) {
try { try {
console.log(relativePath); console.log(relativePath);
return await client.queryResponse(relativePath); return await client.queryResponse(relativePath);
@ -435,7 +435,9 @@ export class LosslessAPI {
items: preparedTracks, items: preparedTracks,
}; };
await this.cache.set('search_tracks', query, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('search_tracks', query, result);
}
return result; return result;
} catch (error) { } catch (error) {
if (error.name === 'AbortError') throw error; if (error.name === 'AbortError') throw error;
@ -457,7 +459,9 @@ export class LosslessAPI {
items: normalized.items.map((a) => this.prepareArtist(a)), items: normalized.items.map((a) => this.prepareArtist(a)),
}; };
await this.cache.set('search_artists', query, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('search_artists', query, result);
}
return result; return result;
} catch (error) { } catch (error) {
if (error.name === 'AbortError') throw error; if (error.name === 'AbortError') throw error;
@ -480,7 +484,9 @@ export class LosslessAPI {
items: this.deduplicateAlbums(preparedItems), items: this.deduplicateAlbums(preparedItems),
}; };
await this.cache.set('search_albums', query, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('search_albums', query, result);
}
return result; return result;
} catch (error) { } catch (error) {
if (error.name === 'AbortError') throw error; if (error.name === 'AbortError') throw error;
@ -502,7 +508,9 @@ export class LosslessAPI {
items: normalized.items.map((p) => this.preparePlaylist(p)), items: normalized.items.map((p) => this.preparePlaylist(p)),
}; };
await this.cache.set('search_playlists', query, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('search_playlists', query, result);
}
return result; return result;
} catch (error) { } catch (error) {
if (error.name === 'AbortError') throw error; if (error.name === 'AbortError') throw error;
@ -518,7 +526,6 @@ export class LosslessAPI {
try { try {
const response = await this.fetchWithRetry(`/search/?v=${encodeURIComponent(query)}`, { const response = await this.fetchWithRetry(`/search/?v=${encodeURIComponent(query)}`, {
...options, ...options,
allowedDomains: ['api.monochrome.tf', 'arran.monochrome.tf'],
}); });
const data = await response.json(); const data = await response.json();
const normalized = this.normalizeSearchResponse(data, 'videos'); const normalized = this.normalizeSearchResponse(data, 'videos');
@ -527,7 +534,9 @@ export class LosslessAPI {
items: normalized.items.map((v) => this.prepareVideo(v)), items: normalized.items.map((v) => this.prepareVideo(v)),
}; };
await this.cache.set('search_videos', query, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('search_videos', query, result);
}
return result; return result;
} catch (error) { } catch (error) {
if (error.name === 'AbortError') throw error; if (error.name === 'AbortError') throw error;
@ -554,7 +563,9 @@ export class LosslessAPI {
originalTrackUrl: data.OriginalTrackUrl || null, originalTrackUrl: data.OriginalTrackUrl || null,
}; };
await this.cache.set('video', id, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('video', id, result);
}
return result; return result;
} }
@ -683,7 +694,9 @@ export class LosslessAPI {
const result = { album, tracks }; const result = { album, tracks };
await this.cache.set('album', id, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('album', id, result);
}
return result; return result;
} }
@ -793,7 +806,9 @@ export class LosslessAPI {
const result = { playlist, tracks }; const result = { playlist, tracks };
await this.cache.set('playlist', id, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('playlist', id, result);
}
return result; return result;
} }
@ -827,7 +842,9 @@ export class LosslessAPI {
}; };
const result = { mix, tracks }; const result = { mix, tracks };
await this.cache.set('mix', id, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('mix', id, result);
}
return result; return result;
} }
@ -984,7 +1001,9 @@ export class LosslessAPI {
const result = { ...artist, albums, eps, tracks, videos }; const result = { ...artist, albums, eps, tracks, videos };
await this.cache.set('artist', cacheKey, result); if (!(primaryResponse instanceof TidalResponse) && !(contentResponse instanceof TidalResponse)) {
await this.cache.set('artist', cacheKey, result);
}
return result; return result;
} }
@ -1004,7 +1023,9 @@ export class LosslessAPI {
const result = items.map((artist) => this.prepareArtist(artist)); const result = items.map((artist) => this.prepareArtist(artist));
await this.cache.set('similar_artists', artistId, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('similar_artists', artistId, result);
}
return result; return result;
} catch (e) { } catch (e) {
console.warn('Failed to fetch similar artists:', e); console.warn('Failed to fetch similar artists:', e);
@ -1032,7 +1053,9 @@ export class LosslessAPI {
text: data.text, text: data.text,
source: data.source || 'Tidal', source: data.source || 'Tidal',
}; };
await this.cache.set('artist', cacheKey, bio); if (!(response instanceof TidalResponse)) {
await this.cache.set('artist', cacheKey, bio);
}
return bio; return bio;
} }
} }
@ -1057,7 +1080,9 @@ export class LosslessAPI {
const result = items.map((album) => this.prepareAlbum(album)); const result = items.map((album) => this.prepareAlbum(album));
await this.cache.set('similar_albums', albumId, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('similar_albums', albumId, result);
}
return result; return result;
} catch (e) { } catch (e) {
console.warn('Failed to fetch similar albums:', e); console.warn('Failed to fetch similar albums:', e);
@ -1197,7 +1222,9 @@ export class LosslessAPI {
if (found) { if (found) {
track = this.prepareTrack(found.item || found); track = this.prepareTrack(found.item || found);
await this.cache.set('track', cacheKey, track); if (!(response instanceof TidalResponse)) {
await this.cache.set('track', cacheKey, track);
}
return track; return track;
} }
@ -1219,7 +1246,9 @@ export class LosslessAPI {
const items = data.items || []; const items = data.items || [];
const tracks = items.map((item) => this.prepareTrack(item.track || item)); const tracks = items.map((item) => this.prepareTrack(item.track || item));
await this.cache.set('recommendations', id, tracks); if (!(response instanceof TidalResponse)) {
await this.cache.set('recommendations', id, tracks);
}
return tracks; return tracks;
} catch (error) { } catch (error) {
console.error('Failed to fetch recommendations:', error); console.error('Failed to fetch recommendations:', error);
@ -1236,7 +1265,9 @@ export class LosslessAPI {
const jsonResponse = await response.json(); const jsonResponse = await response.json();
const result = this.parseTrackLookup(this.normalizeTrackResponse(jsonResponse)); const result = this.parseTrackLookup(this.normalizeTrackResponse(jsonResponse));
await this.cache.set('track', cacheKey, result); if (!(response instanceof TidalResponse)) {
await this.cache.set('track', cacheKey, result);
}
return result; return result;
} }
@ -1259,7 +1290,9 @@ export class LosslessAPI {
} }
} }
this.streamCache.set(cacheKey, streamUrl); if (!(lookup instanceof TidalResponse)) {
this.streamCache.set(cacheKey, streamUrl);
}
return streamUrl; return streamUrl;
} }
@ -1304,7 +1337,9 @@ export class LosslessAPI {
throw new Error(`Could not resolve video stream URL for ID: ${id}`); throw new Error(`Could not resolve video stream URL for ID: ${id}`);
} }
this.streamCache.set(cacheKey, streamUrl); if (!(lookup instanceof TidalResponse)) {
this.streamCache.set(cacheKey, streamUrl);
}
return streamUrl; return streamUrl;
} }