164 lines
4.9 KiB
JavaScript
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/";
|
|
}
|
|
} |