Files
sources/.archive/tidal/tidal.js
T
aka paul 597f279e49
Fetch and Save Remote Content / fetch (push) Successful in 39s
Sync Versions to index.json / sync-versions (push) Failing after 54s
update
2026-05-27 20:30:23 +02:00

164 lines
4.9 KiB
JavaScript

function calculateSimilarity(title, keyword) {
const titleLower = title.toLowerCase();
const keywordLower = keyword.toLowerCase();
if (titleLower === keywordLower) return 1000;
if (titleLower.startsWith(keywordLower)) return 800;
if (titleLower.includes(keywordLower)) return 600;
let matches = 0;
for (let i = 0; i < Math.min(titleLower.length, keywordLower.length); i++) {
if (titleLower[i] === keywordLower[i]) matches++;
else break;
}
return matches;
}
async function searchResults(keyword) {
const results = [];
try {
const response = await fetchv2("https://triton.squid.wtf/search/?s=" + encodeURIComponent(keyword));
const data = await response.json();
const items = data.data?.items || data.items || [];
if (Array.isArray(items)) {
for (const item of 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`;
}
const qualityDisplay = getQualityDisplay(item.audioQuality);
const title = `${item.title || "Unknown Title"}${qualityDisplay}`;
const href = `https://hund.qqdl.site/track/?id=${item.id}&quality=${item.audioQuality}`;
results.push({
title: title,
image: imageUrl,
href: href,
baseTitle: item.title || "Unknown Title",
similarity: calculateSimilarity(item.title || "Unknown Title", keyword)
});
}
}
results.sort((a, b) => b.similarity - a.similarity);
results.forEach(r => {
delete r.baseTitle;
delete r.similarity;
});
return JSON.stringify(results);
} catch (err) {
console.error("Search error:", err);
return JSON.stringify([{
title: "Error",
image: "Error",
href: "Error"
}]);
}
}
function getQualityDisplay(quality) {
const qualityMap = {
"LOSSLESS": "Hi-Res",
"HIRES_LOSSLESS": "Hi-Res Lossless",
"HIGH": "High",
"LOW": "Low",
"DOLBY_ATMOS": "Dolby Atmos"
};
return qualityMap[quality] || quality || "Unknown";
}
async function extractDetails(url) {
return JSON.stringify([{
description: "",
aliases: "",
airdate: ""
}]);
}
async function extractEpisodes(url) {
const results = [];
try {
results.push({
href: url,
number: 1
});
return JSON.stringify(results);
} catch (err) {
return JSON.stringify([{
href: "Error",
number: "Error"
}]);
}
}
function decodeBase64(str) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let result = '';
let i = 0;
str = str.replace(/=+$/, '');
while (i < str.length) {
const a = chars.indexOf(str.charAt(i++));
const b = chars.indexOf(str.charAt(i++));
const c = i < str.length ? chars.indexOf(str.charAt(i++)) : 0;
const d = i < str.length ? chars.indexOf(str.charAt(i++)) : 0;
const bitmap = (a << 18) | (b << 12) | (c << 6) | d;
result += String.fromCharCode((bitmap >> 16) & 255);
if (c != 64) result += String.fromCharCode((bitmap >> 8) & 255);
if (d != 64) result += String.fromCharCode(bitmap & 255);
}
return result;
}
async function extractStreamUrl(url) {
try {
const response = await fetchv2(url);
const data = await response.json();
if (!data.data) {
console.error("No data field in response");
return "https://error.org/";
}
if (!data.data.manifest) {
console.error("No manifest field in response");
return "https://error.org/";
}
try {
const manifestString = data.data.manifest.trim();
let decodedManifest = decodeBase64(manifestString);
decodedManifest = decodedManifest.replace(/\0/g, '').trim();
const manifestJson = JSON.parse(decodedManifest);
if (manifestJson.urls && manifestJson.urls.length > 0) {
return manifestJson.urls[0];
} else {
console.error("No URLs found in manifest");
}
} catch (err) {
console.error("Failed to decode/parse manifest:", err.message, err.stack);
}
return "https://error.org/";
} catch (err) {
console.error("Extract stream URL error:", err.message, err.stack);
return "https://error.org/";
}
}