Spaces:
Paused
Paused
| 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 |