const { exec } = require("child_process"); const path = require("path"); const fs = require("fs"); const axios = require("axios"); const COOKIES_PATH = path.join(__dirname, "./cookies/qq.txt"); const ytdlp = path.join(__dirname, "./yt-dlp") async function getRedirectedURL(url) { try { const response = await axios.get(url, { maxRedirects: 0, validateStatus: (status) => status >= 300 && status < 400, }); return response.headers.location || null; } catch (error) { console.error("Error mendapatkan URL redirect:", error.message); return null; } } function convertToSongDetailURL(url) { try { const urlObj = new URL(url); const songmid = urlObj.searchParams.get("songmid"); if (songmid) { return `https://y.qq.com/n/ryqq/songDetail/${songmid}`; } } catch (error) { console.error("Error parsing URL:", error.message); } return null; } async function processQQMusicURL(url) { try { if (url.includes("y.qq.com/n/ryqq/songDetail/")) { return url; } else if (url.includes("c6.y.qq.com/base/fcgi-bin/u?")) { const redirectedURL = await getRedirectedURL(url); if (redirectedURL) { return convertToSongDetailURL(redirectedURL); } } else if (url.includes("i.y.qq.com/v8/playsong.html")) { return convertToSongDetailURL(url); } } catch (error) { console.error("Error processing URL:", error.message); } return null; } async function getInfo(url) { return new Promise(async(resolve, reject) => { const thumbnail = await getQQMusicCover(url); exec(`${ytdlp} -j --cookies ${COOKIES_PATH} "${await processQQMusicURL(url)}"`, (error, stdout, stderr) => { if (error) { return reject(`Error: ${stderr || error.message}`); } try { const info = JSON.parse(stdout); resolve({ status: 200, title: info.title, artist: info.creators[0], duration: info.duration, thumbnail, music: info.formats.map(f => ({ format_id: f.format_id, ext: f.ext, filesize: f.size, url: f.url })) }); } catch (e) { reject({ status: 500, message: e.message}); } }); }); } async function getQQMusicCover(songURL) { try { const response = await axios.get(await getRedirectedURL(songURL)); const html = response.data; const match = html.match(/window\.__ssrFirstPageData__\s*=\s*(\{.*?\})<\/script>/s); if (match) { const jsonData = JSON.parse(match[1]); const coverURL = jsonData?.metaData?.image; return coverURL; } else { throw new Error("Data JSON tidak ditemukan dalam HTML."); } } catch (error) { console.error("Error mendapatkan cover:", error.message); return null; } } module.exports = getInfo