diff --git a/tidal/tidal.js b/tidal/tidal.js new file mode 100644 index 0000000..e99570e --- /dev/null +++ b/tidal/tidal.js @@ -0,0 +1,204 @@ +async function searchResults(keyword) { + const results = []; + try { + const response = await fetchv2("https://london.monochrome.tf/search/?s=" + encodeURIComponent(keyword)); + const data = await response.json(); + + if (data.items && Array.isArray(data.items)) { + for (const item of data.items) { + + let imageUrl = ""; + if (item.album && item.album.cover) { + const cover = item.album.cover.replace(/-/g, '/'); + imageUrl = `https://resources.tidal.com/images/${cover}/1280x1280.jpg`; + } + + results.push({ + title: item.title || "Unknown Title", + image: imageUrl, + href: item.id ? item.id.toString() : "" + }); + } + } + + return JSON.stringify(results); + } catch (err) { + console.error("Search error:", err); + return JSON.stringify([{ + title: "Error", + image: "Error", + href: "Error" + }]); + } +} + +async function extractDetails(ID) { + const endpoints = [ + "https://tidal.kinoplus.online/track/", + "https://katze.qqdl.site/track/", + "https://wolf.qqdl.site/track/", + "https://london.monochrome.tf/track/" + ]; + + const startTime = Date.now(); + let json = null; + + async function tryEndpoints() { + const promises = endpoints.map(async endpoint => { + try { + const response = await fetchv2(`${endpoint}?id=${encodeURIComponent(ID)}&quality=LOSSLESS`); + const data = await response.json(); + if (data.detail === "Too Many Requests") return null; + if (Array.isArray(data) && data.length > 0) return data; + return null; + } catch { + return null; + } + }); + + const results = await Promise.allSettled(promises); + for (const result of results) { + if (result.status === 'fulfilled' && result.value !== null) { + return result.value; + } + } + return null; + } + + while (Date.now() - startTime < 10000) { + json = await tryEndpoints(); + if (json) break; + await new Promise(resolve => setTimeout(resolve, 100)); + } + + if (!json) { + return JSON.stringify([{ + description: "Error loading track details", + aliases: "Error", + airdate: "Error" + }]); + } + + try { + let trackInfo = json.find(item => item.duration && item.title); + if (!trackInfo) throw new Error("Track info not found"); + + const artists = trackInfo.artists ? trackInfo.artists.map(a => a.name).join(", ") : "Unknown Artist"; + const album = trackInfo.album ? trackInfo.album.title : "Unknown Album"; + const duration = trackInfo.duration ? Math.floor(trackInfo.duration / 60) + ":" + String(trackInfo.duration % 60).padStart(2, '0') : "Unknown"; + const audioQuality = trackInfo.audioQuality || "Unknown"; + const audioModes = trackInfo.audioModes ? trackInfo.audioModes.join(", ") : "STEREO"; + const copyright = trackInfo.copyright || ""; + const bpm = trackInfo.bpm ? `${trackInfo.bpm} BPM` : ""; + const key = trackInfo.key && trackInfo.keyScale ? `${trackInfo.key} ${trackInfo.keyScale}` : ""; + const explicit = trackInfo.explicit ? "šŸ…“ Explicit" : ""; + + let description = `šŸŽµ ${trackInfo.title}\n`; + description += `šŸ‘¤ Artist: ${artists}\n`; + description += `šŸ’æ Album: ${album}\n`; + description += `ā±ļø Duration: ${duration}\n`; + description += `šŸŽ§ Quality: ${audioQuality} (${audioModes})\n`; + if (trackInfo.popularity) description += `šŸ“Š Popularity: ${trackInfo.popularity}%\n`; + if (bpm) { + description += `šŸŽ¼ ${bpm}`; + if (key) description += ` | Key: ${key}`; + description += `\n`; + } + if (explicit) description += `${explicit}\n`; + if (copyright) description += `\nĀ© ${copyright}`; + + const airdate = trackInfo.streamStartDate + ? new Date(trackInfo.streamStartDate).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }) + : "N/A"; + + const featuredArtists = trackInfo.artists + ? trackInfo.artists.filter(a => a.type === "FEATURED").map(a => a.name).join(", ") + : "N/A"; + + return JSON.stringify([{ + description: description.trim(), + aliases: featuredArtists || "N/A", + airdate: airdate + }]); + + } catch (err) { + console.error("Extract details error:", err); + return JSON.stringify([{ + description: "Error loading track details", + aliases: "Error", + airdate: "Error" + }]); + } +} + +async function extractEpisodes(id) { + const results = []; + try { + results.push({ + href: id, + number: 1 + }); + return JSON.stringify(results); + } catch (err) { + return JSON.stringify([{ + href: "Error", + number: "Error" + }]); + } +} + +async function extractStreamUrl(ID) { + try { + const endpoints = [ + "https://tidal.kinoplus.online/track/", + "https://katze.qqdl.site/track/", + "https://wolf.qqdl.site/track/", + "https://london.monochrome.tf/track/" + ]; + + const startTime = Date.now(); + let json = null; + + async function tryEndpoints() { + const promises = endpoints.map(async endpoint => { + try { + const response = await fetchv2(`${endpoint}?id=${encodeURIComponent(ID)}&quality=LOSSLESS`); + const data = await response.json(); + if (data.detail === "Too Many Requests") return null; + if (Array.isArray(data) && data.length > 0) return data; + return null; + } catch { + return null; + } + }); + + const results = await Promise.allSettled(promises); + for (const result of results) { + if (result.status === 'fulfilled' && result.value !== null) { + return result.value; + } + } + return null; + } + + while (Date.now() - startTime < 10000) { + json = await tryEndpoints(); + if (json) break; + await new Promise(resolve => setTimeout(resolve, 100)); + } + + if (!json) { + return "https://error.org/"; + } + + const streamObj = json.find(item => item.OriginalTrackUrl); + if (streamObj && streamObj.OriginalTrackUrl) { + return streamObj.OriginalTrackUrl; + } + + return "https://error.org/"; + + } catch (err) { + return "https://error.org/"; + } +}