UNPKG

badan-ser

Version:

external functions for zoe

321 lines (275 loc) 9.25 kB
const fs = require('fs'); const path = require('path'); const axios = require('axios'); const cheerio = require("cheerio"); const FormData = require('form-data'); const puppeteer = require('puppeteer'); function loadEnv(filePath = '.env') { const envPath = path.resolve(process.cwd(), filePath); if (!fs.existsSync(envPath)) { throw new Error(`Environment file not found: ${filePath}`); } const envContent = fs.readFileSync(envPath, 'utf-8'); const lines = envContent.split('\n'); lines.forEach((line) => { if (!line || line.startsWith('#')) return; const [rawKey, ...rawValue] = line.split('='); if (rawKey && rawValue.length > 0) { const key = rawKey.trim(); const value = rawValue.join('=').trim(); const trimmedValue = value.replace(/^["']|["']$/g, ''); process.env[key] = trimmedValue; } }); return process.env; }; async function ss({ url, output, type = 'viewport', region, selector, viewport = { width: 1280, height: 720 }, delay = 0 }) { if (!url) throw new Error('URL is required'); const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setViewport(viewport); await page.goto(url, { waitUntil: 'networkidle2' }); if (delay > 0) { console.log(`Waiting ${delay}ms...`); await new Promise(resolve => setTimeout(resolve, delay)); } try { let buffer; if (type === 'full') { buffer = await page.screenshot({ fullPage: true }); } else if (type === 'region') { if (!region) throw new Error('Region must be provided for region screenshot'); buffer = await page.screenshot({ clip: region }); } else if (type === 'element') { if (!selector) throw new Error('Selector must be provided for element screenshot'); const element = await page.$(selector); if (!element) throw new Error('Element not found'); buffer = await element.screenshot(); } else { buffer = await page.screenshot(); } if (output) { const screenshotPath = path.resolve(output); fs.writeFileSync(screenshotPath, buffer); console.log(`Screenshot saved to: ${screenshotPath}`); } return buffer; } catch (err) { console.error('Screenshot capture failed:', err); throw err; } finally { await browser.close(); } } async function yts(query) { try { const response = await axios.get("https://m.youtube.com/results?search_query=" + encodeURIComponent(query), { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", }, }); const html = response.data; const $ = cheerio.load(html); let ytInitialData; $("script").each((_, element) => { const scriptContent = $(element).html(); if (scriptContent && scriptContent.includes("var ytInitialData =")) { const jsonStr = scriptContent .replace(/^var ytInitialData = /, "") .replace(/;$/, ""); ytInitialData = JSON.parse(jsonStr); } }); if (!ytInitialData) { throw new Error("Failed to parse YouTube data."); } const results = []; const content = ytInitialData.contents?.twoColumnSearchResultsRenderer?.primaryContents?.sectionListRenderer?.contents || []; const items = content[0]?.itemSectionRenderer?.contents || []; items.forEach((item) => { const itemType = Object.keys(item)[0]; const data = item[itemType]; if (itemType === "videoRenderer") { results.push({ title: data.title?.runs[0]?.text, videoId: data.videoId, url: `https://youtu.be/${data.videoId}`, image: data.thumbnail?.thumbnails?.pop()?.url, thumbnail: data.thumbnail?.thumbnails?.pop()?.url, duration: data.lengthText?.simpleText, views: data.viewCountText?.simpleText, publishedTime: data.publishedTimeText?.simpleText || "N/A", author: data.ownerText?.runs[0]?.text, }); } }); return results; } catch (error) { console.error("Error in ytsearch:", error); return []; } } class Success { constructor(data) { this.success = true; this.data = data; } } class ErrorResponse { constructor(error) { this.success = false; this.error = error; } } const ytdls = { mp3: async (url) => { try { if (!url || !url.includes('youtube.com') && !url.includes('youtu.be')) { return new ErrorResponse({ message: "URL YouTube tidak valid!" }); } const ds = new FormData(); ds.append("url", url); const { data } = await axios.post( "https://www.youtubemp3.ltd/convert", ds, { headers: { ...ds.getHeaders(), 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }, timeout: 45000 } ); if (!data || !data.link) { return new ErrorResponse({ message: "Gagal mendapatkan link download" }); } return new Success({ title: data.filename || "Unknown Title", downloadUrl: data.link, type: "mp3" }); } catch (error) { if (error.code === 'ECONNABORTED') { return new ErrorResponse({ message: "Request timeout, coba lagi nanti" }); } return new ErrorResponse({ message: error.response?.data?.message || error.message || "Gagal convert YouTube ke MP3" }); } }, mp4: async (url, quality = "720") => { try { if (!url || !url.includes('youtube.com') && !url.includes('youtu.be')) { return new ErrorResponse({ message: "URL YouTube tidak valid!" }); } const validQuality = { "480": 480, "1080": 1080, "720": 720, "360": 360, "audio": "mp3", }; if (!Object.keys(validQuality).includes(quality)) { return new ErrorResponse({ message: "Quality tidak valid!", availableQuality: Object.keys(validQuality) }); } const qualitys = validQuality[quality]; const { data: firstRequest } = await axios.get( `https://p.oceansaver.in/ajax/download.php?button=1&start=1&end=1&format=${qualitys}&iframe_source=https://allinonetools.com/&url=${encodeURIComponent(url)}`, { timeout: 30000, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } } ); if (!firstRequest || !firstRequest.progress_url) { return new ErrorResponse({ message: "Gagal memulai proses download" }); } const { progress_url } = firstRequest; let metadata = { image: firstRequest.info?.image || "", title: firstRequest.info?.title || "Unknown Title", downloadUrl: "", quality: quality, type: quality === "audio" ? "mp3" : "mp4" }; let datas; let attempts = 0; const maxAttempts = 40; console.log("Memproses download, mohon tunggu..."); do { if (attempts >= maxAttempts) { return new ErrorResponse({ message: "Timeout: Proses download terlalu lama, coba lagi" }); } await new Promise(resolve => setTimeout(resolve, 3000)); try { const { data } = await axios.get(progress_url, { timeout: 15000, headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } }); datas = data; if (datas.progress && datas.progress < 100) { console.log(`Progress: ${datas.progress}%`); } } catch (pollError) { console.log(`Polling attempt ${attempts + 1} failed, retrying...`); } attempts++; } while (!datas?.download_url); if (!datas.download_url) { return new ErrorResponse({ message: "Gagal mendapatkan URL download" }); } metadata.downloadUrl = datas.download_url; console.log("Download siap!"); return new Success(metadata); } catch (error) { if (error.code === 'ECONNABORTED') { return new ErrorResponse({ message: "Request timeout, coba lagi nanti" }); } return new ErrorResponse({ message: error.response?.data?.message || error.message || "Gagal download video" }); } }, // Utility function untuk validasi URL YouTube isValidYouTubeUrl: (url) => { const youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/.+$/; return youtubeRegex.test(url); }, // Utility function untuk extract video ID extractVideoId: (url) => { const regex = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/; const match = url.match(regex); return match ? match[1] : null; } }; module.exports = { loadEnv, ss, yts, ytdls };