// pindown.js — bundle standalone. npm deps: axios, cheerio, node:url /** * Scraper: pindown.js * Source : kyioapi/pindown.js * * Input : Function parameters / CLI args (e.g. query: string, url: string, options: object) * Output : Promise (JSON formatted scraping response / stream URL / media metadata) * * CLI Run: * node kyioapi/pindown.js [functionName] [args...] * node cli.js kyioapi/pindown.js [functionName] [args...] */ import * as __ns_283 from 'axios' const axios = __ns_283.default import * as __ns_284 from 'cheerio' const cheerio = __ns_284 import * as __ns_285 from 'node:url' const pathToFileURL = __ns_285.pathToFileURL class PinDownAPI { constructor() { this.baseURL = "https://pindown.io"; } async getDynamicToken() { const response = await axios.get(`${this.baseURL}/en1`, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36' } }); const $ = cheerio.load(response.data); let tokenName = ''; let tokenValue = ''; $('form input').each((i, el) => { const name = $(el).attr('name'); if (name && name !== 'url' && name !== 'lang') { tokenName = name; tokenValue = $(el).attr('value') || ''; } }); const rawCookies = response.headers['set-cookie'] || []; const cookieString = rawCookies.map(c => c.split(';')[0]).join('; '); return { tokenName, tokenValue, cookieString }; } async download(url, lang = "en") { const { tokenName, tokenValue, cookieString } = await this.getDynamicToken(); if (!tokenName) throw new Error("Gagal mengekstrak Anti-Bot Key dinamis dari halaman utama."); const formData = new URLSearchParams(); formData.append("url", url); formData.append(tokenName, tokenValue); formData.append("lang", lang); const response = await axios({ method: "POST", url: `${this.baseURL}/action`, headers: { "accept": "*/*", "accept-language": "en-US,en;q=0.9", "cookie": cookieString, "origin": this.baseURL, "referer": `${this.baseURL}/en1`, "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36", "Content-Type": "application/x-www-form-urlencoded" }, data: formData.toString(), }); return response.data; } parseDownloadLinks(html) { const $ = cheerio.load(html); const links = []; $('table tbody tr').each((i, el) => { const quality = $(el).find('td.video-quality').text().trim(); const downloadUrl = $(el).find('a').attr('href'); if (downloadUrl && quality) { links.push({ quality: quality, url: downloadUrl }); } }); return links; } async getDownloadLinks(url, lang = "en") { try { const result = await this.download(url, lang); if (result.success && result.html) { const links = this.parseDownloadLinks(result.html); return { status: true, result: links }; } return { status: false, creator: "ONLym-Api", message: result.message || "Gagal mendapatkan data" }; } catch (error) { return { status: false, creator: "ONLym-Api", message: error.message }; } } } const pindown = new PinDownAPI(); // ───────────────────────────────────────────────────────────────────── // Self-test: jalankan langsung dengan `node pindown.js [args...]` // ───────────────────────────────────────────────────────────────────── if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { const __exports = { pindown: pindown } const __fns = Object.fromEntries(Object.entries(__exports).filter(([, v]) => typeof v === 'function')) const __names = Object.keys(__fns) if (__names.length === 0) { console.log('Tidak ada fungsi yang bisa di-demo. Import modul ini dari kode lain.') } else { const __search = __names.find((n) => /search|cari/i.test(n)) const __name = __search || __names[0] const __fn = __fns[__name] const __isClass = /^class\s/.test(Function.prototype.toString.call(__fn)) let __args = process.argv.slice(2).map((a) => { try { return JSON.parse(a) } catch { return a } }) if (__args.length === 0 && __search) __args.push('naruto') if (__args.length === 0 && !__search && !__isClass && __fn.length > 0) { console.log('Fungsi: ' + __names.join(', ')) console.log('Contoh: node ' + "pindown.js" + ' ' + __name + ' ') } else { ;(async () => { try { const r = __isClass ? new __fn(...__args) : await __fn(...__args) console.log(JSON.stringify(r, null, 2)) } catch (e) { console.error('Error: ' + (e && e.message ? e.message : e)) process.exitCode = 1 } })() } } }