Spaces:
Paused
Paused
| /* eslint-disable jsdoc/require-jsdoc */ | |
| const FormData = require("form-data"); | |
| const axios = require("axios"); | |
| const cheerio = require("cheerio"); | |
| 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; | |
| } | |
| } | |
| async function search(query) { | |
| try { | |
| const url = `https://m.soundcloud.com/search?q=${encodeURIComponent(query)}`; | |
| const response = await axios.get(url); | |
| const $ = await cheerio.load(response.data); | |
| const results = []; | |
| $(".List_VerticalList__2uQYU li").each((index, element) => { | |
| const title = $(element).find(".Information_CellTitle__2KitR").text(); | |
| const artist = $(element).find(".Information_CellSubtitle__1mXGx").text(); | |
| const thumbnail = $(element) | |
| .find(".Artwork_ArtworkImage__1Ws9-") | |
| .attr("src"); | |
| const link = $(element) | |
| .find(".Cell_CellLink__3yLVS") | |
| .attr("href"); | |
| results.push({ | |
| title, | |
| artist, | |
| thumbnail, | |
| link: `https://soundcloud.com${link}`, | |
| }); | |
| }); | |
| return results; | |
| } catch (error) { | |
| console.error(error); | |
| return []; | |
| } | |
| } | |
| async function download(url) { | |
| const form = new FormData(); | |
| form.append("formurl", url); | |
| const { | |
| data | |
| } = await axios.post("https://www.forhub.io/download.php", form, { | |
| headers: form.getHeaders(), | |
| }); | |
| const $ = cheerio.load(data); | |
| const fullTitleText = $("td.small-10.columns").text().trim(); | |
| // eslint-disable-next-line no-unused-vars | |
| const [title] = fullTitleText.split("320 KB/S").map((text) => text.trim()); | |
| const music = $("td a").attr("href"); | |
| // eslint-disable-next-line no-unused-vars | |
| const cover = $("td img").attr("src"); | |
| return music | |
| } | |
| async function metadata(url) { | |
| const parsedd = new URL(url) | |
| const scUri = [ | |
| "m.soundcloud.com" | |
| ] | |
| let Modif; | |
| if (scUri.includes(parsedd.hostname)) { | |
| Modif = url.replace(/(?:m\.)?soundcloud\.com/, "soundcloud.com"); | |
| } else { | |
| Modif = await getRedirectedURL(url); | |
| } | |
| const { data } = await axios.get(Modif); | |
| const $ = cheerio.load(data); | |
| let hydrationData; | |
| $("script").each(function() { | |
| const scr = $(this).html(); | |
| if (scr.includes("window.__sc_hydration")) { | |
| try { | |
| // Ambil JSON dari bagian setelah "window.__sc_hydration = " | |
| const jsonStr = scr.split("window.__sc_hydration = ")[1].trim().slice(0, -1); // Hapus titik koma terakhir | |
| hydrationData = JSON.parse(jsonStr); | |
| } catch (err) { | |
| console.error("Gagal parse JSON:", err); | |
| } | |
| } | |
| }); | |
| if (!hydrationData) { | |
| throw new Error("Metadata tidak ditemukan."); | |
| } | |
| const trackData = hydrationData.find(entry => entry.hydratable === "sound")?.data; | |
| if (!trackData) { | |
| throw new Error("Data track tidak ditemukan."); | |
| } | |
| return trackData; | |
| } | |
| async function soundcloud(query, type) { | |
| try { | |
| if(type === "search") { | |
| const search_result = await search(query) | |
| return search_result | |
| } else { | |
| const result_download = await download(query) | |
| const result_metadata = await metadata(query) | |
| const resd = { | |
| status: 200, | |
| title: result_metadata.title, | |
| thumbnail: result_metadata.artwork_url, | |
| music: [ | |
| { | |
| resolusi: "default", | |
| url: result_download | |
| } | |
| ] | |
| } | |
| console.log(resd) | |
| return resd | |
| } | |
| } catch (e) { | |
| return { status: 500, message: e.message} | |
| } | |
| } | |
| module.exports = { | |
| search, | |
| download, | |
| soundcloud, | |
| metadata | |
| } | |