diff --git "a/index.js" "b/index.js" --- "a/index.js" +++ "b/index.js" @@ -4,404 +4,353 @@ import os from 'os'; import PDFDocument from 'pdfkit'; import fs from 'fs'; import axios from 'axios'; -import { - promisify -} from 'util'; -import { - createRequire -} from 'module'; -import { - fileURLToPath -} from 'url'; +import { promisify } from 'util'; +import { createRequire } from 'module'; +import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); import puppeteer from "puppeteer" import sharp from 'sharp'; -import { - fileTypeFromBuffer -} from 'file-type'; +import { fileTypeFromBuffer } from 'file-type'; const require = createRequire(import.meta.url); const PORT = process.env.PORT || 7860; const app = express(); const writeFileAsync = promisify(fs.writeFile); const fss = fs.promises; const sizeOf = promisify(require('image-size')); -const { - exec -} = require('child_process'); +const { exec } = require('child_process'); const cheerio = require('cheerio'); app.use('/static', express.static(os.tmpdir())); import AdmZip from "adm-zip"; const deleteFilesAfter = 2 * 60 * 1000; // 2 minutes const execAsync = promisify(exec); const tmpDir = os.tmpdir(); -const crypto = require('crypto'); +import crypto from 'crypto'; function getRandomUserAgent() { - const userAgents = [ - 'Mozilla/5.0 (Linux; Android 12; SM-G991B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/363.0.0.30.112;]', - 'Mozilla/5.0 (Linux; Android 11; SM-G986N Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.163 Whale/1.0.0.0 Crosswalk/25.80.14.21 Mobile Safari/537.36 NAVER(inapp; search; 730; 10.32.5)', - 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.125 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/372.1.0.23.107;]', - 'Mozilla/5.0 (Linux; Android 12; Galaxy S21+) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.100 Mobile Safari/537.36 WhatsApp/1.2.3', - 'Mozilla/5.0 (Linux; Android 13; SM-S918W Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.67 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/405.0.0.23.72;]', - 'Mozilla/5.0 (Linux; Android 9; SM-A730F) AppleWebKit/537.36 (KHTML, like Gecko) coc_coc_browser/87.0.162 Mobile Chrome/81.0.4044.162 Mobile Safari/537.36 WhatsApp/1.2.3', - 'Mozilla/5.0 (Linux; Android 11; SM-M215G Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.101 Mobile Safari/537.36 GSA/13.5.13.23.arm64', - 'Mozilla/5.0 (Linux; Android 13; SM-M146B Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/421.0.0.33.47;]', - 'Mozilla/5.0 (Linux; Android 13; 2201123G Build/TKQ1.220807.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]', - 'Mozilla/5.0 (Linux; Android 12; 22081212UG Build/SKQ1.220303.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/400.0.0.11.90;]', - 'Mozilla/5.0 (Linux; U; Android 13; zh-cn; 2203121C Build/TKQ1.220829.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/17.5.120328 swan-mibrowser', - 'Mozilla/5.0 (Linux; U; Android 14; zh-cn; 2206122SC Build/UKQ1.231003.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.118 Mobile Safari/537.36 XiaoMi/MiuiBrowser/18.2.150419', - 'Mozilla/5.0 (Linux; Android 13; 2304FPN6DC Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/438.0.0.33.118;]', - 'Mozilla/5.0 (Linux; U; Android 14; zh-CN; 24053PY09C Build/UKQ1.240116.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 Quark/7.0.0.590 Mobile Safari/537.36', - 'Mozilla/5.0 (Linux; U; Android 12; zh-CN; M2007J1SC Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.8.2.221 Mobile Safari/537.36', - 'Mozilla/5.0 (Linux; Android 10; Redmi K30S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36 EdgA/88.0.705.53', - 'Mozilla/5.0 (Linux; U; Android 12; zh-cn; 22041211AC Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.102 MQQBrowser/13.5 Mobile Safari/537.36 COVC/046333', - 'Mozilla/5.0 (Linux; Android 13; 23078RKD5C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046279 Mobile Safari/537.36 StApp/m6/2.6.5/android', - 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.78 Mobile Safari/537.36 GSA/13.21.16.26.arm64', - 'Mozilla/5.0 (Linux; Android 12; 21091116I Build/SP1A.210812.016; ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.0.0 Mobile Safari/537.36 BingSapphire/25.3.410526302', - 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 WpsMoffice/16.4/arm64-v8a/1331', - 'Mozilla/5.0 (Linux; Android 12; 21091116I Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.136 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/378.0.0.25.106;]', - 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 GoogleApp/13.18.7.23.arm64', - 'Mozilla/5.0 (Linux; Android 14; Pixel Fold Build/UQ1A.231205.015.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.193 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/445.0.0.34.118;]', - 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UD1A.231105.004; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/119.0.6045.193 Mobile Safari/537.36 Brave/1.62.162', - 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UD1A.230803.041; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Mobile Safari/537.36 Puffin/10.0.0.51608AP', - 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/UD1A.230803.022.A5; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/441.1.0.39.109;]', - 'Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G) Build/RQ3A.210805.001.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.166 Mobile Safari/537.36 GoogleApp/12.34.17.29.arm64', - 'Mozilla/5.0 (Linux; Android 14; Infinix X6871 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.47 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/468.1.0.56.78;]', - 'Mozilla/5.0 (Linux; Android 13; Infinix X6739 Build/TP1A.220624.014; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Mobile Safari/537.36 Puffin/10.1.0.51631AP', - 'Mozilla/5.0 (Linux; Android 13; Infinix X6711 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/441.0.0.32.109;]', - 'Mozilla/5.0 (Linux; Android 13; Infinix X6710 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.60 Mobile Safari/537.36 YandexSearch/7.53 YandexSearchBrowser/7.53', - 'Mozilla/5.0 (Linux; Android 13; Infinix X6832 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.40 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/454.1.0.49.104;]', - 'Mozilla/5.0 (Linux; Android 12; Infinix X6820 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.101 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/411.1.0.29.112;]' - ]; - - const randomIndex = Math.floor(Math.random() * userAgents.length); - return userAgents[randomIndex]; + const userAgents = [ + 'Mozilla/5.0 (Linux; Android 12; SM-G991B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/363.0.0.30.112;]', + 'Mozilla/5.0 (Linux; Android 11; SM-G986N Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.163 Whale/1.0.0.0 Crosswalk/25.80.14.21 Mobile Safari/537.36 NAVER(inapp; search; 730; 10.32.5)', + 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.125 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/372.1.0.23.107;]', + 'Mozilla/5.0 (Linux; Android 12; Galaxy S21+) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.100 Mobile Safari/537.36 WhatsApp/1.2.3', + 'Mozilla/5.0 (Linux; Android 13; SM-S918W Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.67 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/405.0.0.23.72;]', + 'Mozilla/5.0 (Linux; Android 9; SM-A730F) AppleWebKit/537.36 (KHTML, like Gecko) coc_coc_browser/87.0.162 Mobile Chrome/81.0.4044.162 Mobile Safari/537.36 WhatsApp/1.2.3', + 'Mozilla/5.0 (Linux; Android 11; SM-M215G Build/RP1A.200720.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.101 Mobile Safari/537.36 GSA/13.5.13.23.arm64', + 'Mozilla/5.0 (Linux; Android 13; SM-M146B Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.196 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/421.0.0.33.47;]', + 'Mozilla/5.0 (Linux; Android 13; 2201123G Build/TKQ1.220807.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/418.0.0.33.69;]', + 'Mozilla/5.0 (Linux; Android 12; 22081212UG Build/SKQ1.220303.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/110.0.5481.153 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/400.0.0.11.90;]', + 'Mozilla/5.0 (Linux; U; Android 13; zh-cn; 2203121C Build/TKQ1.220829.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/17.5.120328 swan-mibrowser', + 'Mozilla/5.0 (Linux; U; Android 14; zh-cn; 2206122SC Build/UKQ1.231003.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.118 Mobile Safari/537.36 XiaoMi/MiuiBrowser/18.2.150419', + 'Mozilla/5.0 (Linux; Android 13; 2304FPN6DC Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/118.0.0.0 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/438.0.0.33.118;]', + 'Mozilla/5.0 (Linux; U; Android 14; zh-CN; 24053PY09C Build/UKQ1.240116.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.58 Quark/7.0.0.590 Mobile Safari/537.36', + 'Mozilla/5.0 (Linux; U; Android 12; zh-CN; M2007J1SC Build/SKQ1.211006.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Quark/5.8.2.221 Mobile Safari/537.36', + 'Mozilla/5.0 (Linux; Android 10; Redmi K30S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Mobile Safari/537.36 EdgA/88.0.705.53', + 'Mozilla/5.0 (Linux; U; Android 12; zh-cn; 22041211AC Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/98.0.4758.102 MQQBrowser/13.5 Mobile Safari/537.36 COVC/046333', + 'Mozilla/5.0 (Linux; Android 13; 23078RKD5C Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/89.0.4389.72 MQQBrowser/6.2 TBS/046279 Mobile Safari/537.36 StApp/m6/2.6.5/android', + 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/102.0.5005.78 Mobile Safari/537.36 GSA/13.21.16.26.arm64', + 'Mozilla/5.0 (Linux; Android 12; 21091116I Build/SP1A.210812.016; ) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.0.0 Mobile Safari/537.36 BingSapphire/25.3.410526302', + 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/103.0.5060.129 Mobile Safari/537.36 WpsMoffice/16.4/arm64-v8a/1331', + 'Mozilla/5.0 (Linux; Android 12; 21091116I Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/105.0.5195.136 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/378.0.0.25.106;]', + 'Mozilla/5.0 (Linux; Android 11; 21091116AI Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/101.0.4951.61 Mobile Safari/537.36 GoogleApp/13.18.7.23.arm64', + 'Mozilla/5.0 (Linux; Android 14; Pixel Fold Build/UQ1A.231205.015.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/120.0.6099.193 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/445.0.0.34.118;]', + 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UD1A.231105.004; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/119.0.6045.193 Mobile Safari/537.36 Brave/1.62.162', + 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UD1A.230803.041; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Mobile Safari/537.36 Puffin/10.0.0.51608AP', + 'Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/UD1A.230803.022.A5; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.61 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/441.1.0.39.109;]', + 'Mozilla/5.0 (Linux; Android 11; Pixel 4a (5G) Build/RQ3A.210805.001.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/92.0.4515.166 Mobile Safari/537.36 GoogleApp/12.34.17.29.arm64', + 'Mozilla/5.0 (Linux; Android 14; Infinix X6871 Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.47 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/468.1.0.56.78;]', + 'Mozilla/5.0 (Linux; Android 13; Infinix X6739 Build/TP1A.220624.014; en-us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Mobile Safari/537.36 Puffin/10.1.0.51631AP', + 'Mozilla/5.0 (Linux; Android 13; Infinix X6711 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/441.0.0.32.109;]', + 'Mozilla/5.0 (Linux; Android 13; Infinix X6710 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.60 Mobile Safari/537.36 YandexSearch/7.53 YandexSearchBrowser/7.53', + 'Mozilla/5.0 (Linux; Android 13; Infinix X6832 Build/TP1A.220624.014; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/123.0.6312.40 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/454.1.0.49.104;]', + 'Mozilla/5.0 (Linux; Android 12; Infinix X6820 Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/112.0.5615.101 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/411.1.0.29.112;]' + ]; + + const randomIndex = Math.floor(Math.random() * userAgents.length); + return userAgents[randomIndex]; } app.get('/puppet', async (req, res) => { - const url = req.query.url; - if (!url) { - return res.status(400).send('URL query parameter is required'); - } - try { - const browser = await puppeteer.launch(); - /*({ + const url = req.query.url; + if (!url) { + return res.status(400).send('URL query parameter is required'); + } + try { + const browser = await puppeteer.launch(); + /*({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });*/ - const page = await browser.newPage(); - await page.setUserAgent( - 'Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) ' + - 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 ' + - 'Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]' - ); - await page.setExtraHTTPHeaders({ - 'Accept-Language': 'en-US,en;q=0.9', - 'Accept-Encoding': 'gzip, deflate, br', - 'Connection': 'keep-alive' - }); - - await page.goto(url, { - waitUntil: 'domcontentloaded', - timeout: 60000 // Timeout untuk navigasi - }); - - await page.waitForNavigation({ - waitUntil: 'networkidle0', - timeout: 60000 // Timeout untuk menunggu navigasi selesai - }); - - const htmlContent = await page.content(); - await new Promise(resolve => setTimeout(resolve, 15000)); - await browser.close(); - res.send(htmlContent); - } catch (error) { - console.error('Error fetching HTML:', error); - res.status(500).send('Error fetching HTML content'); - } + const page = await browser.newPage(); + await page.setUserAgent( + 'Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) ' + + 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 ' + + 'Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]' + ); + await page.setExtraHTTPHeaders({ + 'Accept-Language': 'en-US,en;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + }); + + await page.goto(url, { + waitUntil: 'domcontentloaded', + timeout: 60000 // Timeout untuk navigasi + }); + + await page.waitForNavigation({ + waitUntil: 'networkidle0', + timeout: 60000 // Timeout untuk menunggu navigasi selesai + }); + + const htmlContent = await page.content(); + await new Promise(resolve => setTimeout(resolve, 15000)); + await browser.close(); + res.send(htmlContent); + } catch (error) { + console.error('Error fetching HTML:', error); + res.status(500).send('Error fetching HTML content'); + } }); const generateRandomIP = () => { - const octet = () => Math.floor(Math.random() * 256); - return `${octet()}.${octet()}.${octet()}.${octet()}`; + const octet = () => Math.floor(Math.random() * 256); + return `${octet()}.${octet()}.${octet()}.${octet()}`; }; function generateRandomID(length = 8) { - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - let result = ''; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * characters.length)); - } - return result; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; } /*******************************************/ async function toonCubus(url) { - const instanceID = generateRandomID(); - const tempDir = path.join(os.tmpdir(), instanceID); - let browser; - - try { - // Ensure tempDir creation - await fss.mkdir(tempDir, { - recursive: true - }); - - // Extract title safely - const title = url.split('/').pop().split('.')[0]; - - browser = await puppeteer.launch({ - headless: true, - args: ['--no-sandbox', '--disable-setuid-sandbox'] - }); - - const page = await browser.newPage(); - await page.setUserAgent("Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]"); - await page.goto(url, { - waitUntil: 'networkidle2' - }); - - const data = await page.evaluate(() => { - const elements = document.querySelectorAll("#Blog1 > div > div.check-box > center > a img"); - return Array.from(elements).map(img => ({ - path: img.src - })); - }); - - const imagePaths = await downloadImages(data, tempDir, instanceID); - console.log(imagePaths) - const pdfPath = await createPDF(imagePaths, instanceID, tempDir); - - return { - url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, - path: `/static/${instanceID}.pdf`, - title: title, - Pdf_path: pdfPath - }; - } catch (error) { - console.error('Error in toonCubus:', error); - throw error; - } finally { - if (browser) { - await browser.close(); - } - try { - await fss.rmdir(tempDir, { - recursive: true, - force: true - }); - } catch (cleanupError) { - console.error('Error cleaning up temp directory:', cleanupError); - } - } + const instanceID = generateRandomID(); + const tempDir = path.join(os.tmpdir(), instanceID); + let browser; + + try { + // Ensure tempDir creation + await fss.mkdir(tempDir, { recursive: true }); + + // Extract title safely + const title = url.split('/').pop().split('.')[0]; + + browser = await puppeteer.launch({ + headless: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent("Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]"); + await page.goto(url, { waitUntil: 'networkidle2' }); + + const data = await page.evaluate(() => { + const elements = document.querySelectorAll("#Blog1 > div > div.check-box > center > a img"); + return Array.from(elements).map(img => ({ path: img.src })); + }); + + const imagePaths = await downloadImages(data, tempDir, instanceID); + console.log(imagePaths) + const pdfPath = await createPDF(imagePaths, instanceID, tempDir); + + return { + url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, + path: `/static/${instanceID}.pdf`, + title: title, + Pdf_path: pdfPath + }; + } catch (error) { + console.error('Error in toonCubus:', error); + throw error; + } finally { + if (browser) { + await browser.close(); + } + try { + await fss.rmdir(tempDir, { recursive: true, force: true }); + } catch (cleanupError) { + console.error('Error cleaning up temp directory:', cleanupError); + } + } } app.get('/tooncubus', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await toonCubus(url); - exec(`ls ${os.tmpdir()}`, (err, stdout) => { - if (err) console.error(err); - else console.log(stdout); - }); - res.json(result); - setTimeout(async () => { - try { - await fs.unlink(result.Pdf_path); - console.log(`File deleted: ${result.Pdf_path}`); - } catch (err) { - console.error(`Error deleting file: ${err.message}`); - } - }, 330000); // 5 minutes - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await toonCubus(url); + exec(`ls ${os.tmpdir()}`, (err, stdout) => { + if (err) console.error(err); + else console.log(stdout); + }); + res.json(result); + setTimeout(async () => { + try { + await fs.unlink(result.Pdf_path); + console.log(`File deleted: ${result.Pdf_path}`); + } catch (err) { + console.error(`Error deleting file: ${err.message}`); + } + }, 330000); // 5 minutes + } catch (error) { + res.status(500).send('Error processing request'); + } }); /********************************************/ /*******************************************/ function extractGalleryToken(url) { - const regex = /https:\/\/e-hentai\.org\/g\/(\d+)\/([\w-]+)\/?/; - const match = url.match(regex); - return match ? - { - gallery_id: match[1], - gallery_token: match[2], - valid: true - } : - { - gallery_id: null, - gallery_token: null, - valid: false - }; + const regex = /https:\/\/e-hentai\.org\/g\/(\d+)\/([\w-]+)\/?/; + const match = url.match(regex); + return match + ? { gallery_id: match[1], gallery_token: match[2], valid: true } + : { gallery_id: null, gallery_token: null, valid: false }; } async function E_Hentai(url) { - const checkUrl = extractGalleryToken(url); - if (!checkUrl.valid) throw new Error('URL invalid'); - - const instanceID = generateRandomID(); - const tempDir = path.join(os.tmpdir(), instanceID); - - try { - // Ensure tempDir creation - await fss.mkdir(tempDir, { - recursive: true - }); - - const { - data: metadata - } = await axios.post('https://files.xianqiao.wang/https://api.e-hentai.org/api.php', { - method: "gdata", - gidlist: [ - [Number(checkUrl.gallery_id), checkUrl.gallery_token] - ], - namespace: 1 - }, { - headers: { - 'Content-Type': 'application/json' - } - }); - - const { - data - } = await axios.get(url, { - headers: { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', - 'Referer': url, - } - }); - - const $ = cheerio.load(data); - - const imageList = []; - const tds = $('body > div:nth-child(10) > table > tbody > tr > td'); - const noClassTds = tds.filter((i, td) => !$(td).attr('class')).length; - - if (noClassTds > 0) { - // Jika ada td tanpa kelas, ambil gambar untuk setiap halaman - for (let i = 1; i <= noClassTds; i++) { - let newUrl = `${url}?p=${i - 1}`; - console.log(newUrl) - const response = await axios.get(newUrl, { - headers: { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', - 'Referer': url, - } - }); - - const $cada = cheerio.load(response.data); - let imageLinks = [] - $cada('#gdt > div').each((_, element) => { - const link = $cada(element).find('div > a').attr('href'); - if (link) { - imageLinks.push("https://files.xianqiao.wang/" + link); - } - }); - - await Promise.all(imageLinks.map(async (link) => { - try { - const { - data: imgPageData - } = await axios.get(link); - const $imgPage = cheerio.load(imgPageData); - const imageSrc = $imgPage('#img').attr('src'); - if (imageSrc) { - imageList.push({ - path: "https://files.xianqiao.wang/" + imageSrc - }); - } - } catch (error) { - console.error(`Error fetching URL ${link}:`, error.message); - } - })); - } - } else { - // Jika tidak ada td tanpa kelas, ambil gambar dari halaman pertama - let imageLinks = [] - $('#gdt > div').each((_, element) => { - const link = $(element).find('div > a').attr('href'); - if (link) { - imageLinks.push("https://files.xianqiao.wang/" + link); - } - }); - - await Promise.all(imageLinks.map(async (link) => { - try { - const { - data: imgPageData - } = await axios.get(link); - const $imgPage = cheerio.load(imgPageData); - const imageSrc = $imgPage('#img').attr('src'); - if (imageSrc) { - imageList.push({ - path: "https://files.xianqiao.wang/" + imageSrc - }); - } - } catch (error) { - console.error(`Error fetching URL ${link}:`, error.message); - } - })); - } - - console.log(imageList) - console.log(imageList.length) - - const imagePaths = await downloadImages(imageList, tempDir, instanceID); - const pdfPath = await createPDF(imagePaths, instanceID, tempDir); - - return { - url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, - path: `/static/${instanceID}.pdf`, - metadata, - Pdf_path: pdfPath - }; - } catch (error) { - console.error('Error in E_Hentai:', error); - throw error; - } finally { - try { - await fss.rmdir(tempDir, { - recursive: true - }); - } catch (cleanupError) { - console.error('Error cleaning up temp directory:', cleanupError); - } - } + const checkUrl = extractGalleryToken(url); + if (!checkUrl.valid) throw new Error('URL invalid'); + + const instanceID = generateRandomID(); + const tempDir = path.join(os.tmpdir(), instanceID); + + try { + // Ensure tempDir creation + await fss.mkdir(tempDir, { recursive: true }); + + const { data: metadata } = await axios.post('https://files.xianqiao.wang/https://api.e-hentai.org/api.php', { + method: "gdata", + gidlist: [ + [Number(checkUrl.gallery_id), checkUrl.gallery_token] + ], + namespace: 1 + }, { + headers: { + 'Content-Type': 'application/json' + } + }); + + const { data } = await axios.get(url, { headers: { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', + 'Referer': url, + }}); + + const $ = cheerio.load(data); + + const imageList = []; + const tds = $('body > div:nth-child(10) > table > tbody > tr > td'); + const noClassTds = tds.filter((i, td) => !$(td).attr('class')).length; + + if (noClassTds > 0) { + // Jika ada td tanpa kelas, ambil gambar untuk setiap halaman + for (let i = 1; i <= noClassTds; i++) { + let newUrl = `${url}?p=${i - 1}`; + console.log(newUrl) + const response = await axios.get(newUrl, { headers: { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', + 'Referer': url, + }}); + + const $cada = cheerio.load(response.data); + let imageLinks = [] + $cada('#gdt > div').each((_, element) => { + const link = $cada(element).find('div > a').attr('href'); + if (link) { + imageLinks.push("https://files.xianqiao.wang/" + link); + } + }); + + await Promise.all(imageLinks.map(async (link) => { + try { + const { data: imgPageData } = await axios.get(link); + const $imgPage = cheerio.load(imgPageData); + const imageSrc = $imgPage('#img').attr('src'); + if (imageSrc) { + imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc }); + } + } catch (error) { + console.error(`Error fetching URL ${link}:`, error.message); + } + })); + } + } else { + // Jika tidak ada td tanpa kelas, ambil gambar dari halaman pertama + let imageLinks = [] + $('#gdt > div').each((_, element) => { + const link = $(element).find('div > a').attr('href'); + if (link) { + imageLinks.push("https://files.xianqiao.wang/" + link); + } + }); + + await Promise.all(imageLinks.map(async (link) => { + try { + const { data: imgPageData } = await axios.get(link); + const $imgPage = cheerio.load(imgPageData); + const imageSrc = $imgPage('#img').attr('src'); + if (imageSrc) { + imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc }); + } + } catch (error) { + console.error(`Error fetching URL ${link}:`, error.message); + } + })); + } + + console.log(imageList) + console.log(imageList.length) + + const imagePaths = await downloadImages(imageList, tempDir, instanceID); + const pdfPath = await createPDF(imagePaths, instanceID, tempDir); + + return { + url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, + path: `/static/${instanceID}.pdf`, + metadata, + Pdf_path: pdfPath + }; + } catch (error) { + console.error('Error in E_Hentai:', error); + throw error; + } finally { + try { + await fss.rmdir(tempDir, { recursive: true }); + } catch (cleanupError) { + console.error('Error cleaning up temp directory:', cleanupError); + } + } } app.get('/ehentai', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await E_Hentai(url); - exec(`ls ${os.tmpdir()}`, (err, stdout) => { - if (err) console.error(err); - else console.log(stdout); - }); - res.json(result); - setTimeout(async () => { - try { - await fs.unlink(result.Pdf_path); - console.log(`File deleted: ${result.Pdf_path}`); - } catch (err) { - console.error(`Error deleting file: ${err.message}`); - } - }, 330000); // 5 minutes - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await E_Hentai(url); + exec(`ls ${os.tmpdir()}`, (err, stdout) => { + if (err) console.error(err); + else console.log(stdout); + }); + res.json(result); + setTimeout(async () => { + try { + await fs.unlink(result.Pdf_path); + console.log(`File deleted: ${result.Pdf_path}`); + } catch (err) { + console.error(`Error deleting file: ${err.message}`); + } + }, 330000); // 5 minutes + } catch (error) { + res.status(500).send('Error processing request'); + } }); /********************************************/ @@ -409,767 +358,680 @@ app.get('/ehentai', async (req, res) => { async function komiku_download(url) { - const instanceID = generateRandomID(); - const tempDir = path.join(os.tmpdir(), instanceID); - await fss.mkdir(tempDir); - - const title = url.split('/').filter(part => part).pop(); - - try { - const response = await axios.get(url, { - headers: { - 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', - 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/', - 'X-Forwarded-For': generateRandomIP() - } - }); - const html = response.data; - const $ = cheerio.load(html); - const imgList = []; - - $('#Baca_Komik img').each((index, element) => { - const src = $(element).attr('src'); - imgList.push({ - path: "https://files.xianqiao.wang/" + src - }); - }); - - const imagePaths = await downloadImages(imgList, tempDir, instanceID); - const pdfPath = await createPDF(imagePaths, instanceID, tempDir); - - return { - url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", - path: `/static/${instanceID}.pdf`, - title: title, - Pdf_path: pdfPath - }; - } catch (error) { - console.log(error); - throw error; - } finally { - await fss.rmdir(tempDir, { - recursive: true - }); - } + const instanceID = generateRandomID(); + const tempDir = path.join(os.tmpdir(), instanceID); + await fss.mkdir(tempDir); + + const title = url.split('/').filter(part => part).pop(); + + try { + const response = await axios.get(url, { + headers: { + 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', + 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/', + 'X-Forwarded-For': generateRandomIP() + } + }); + const html = response.data; + const $ = cheerio.load(html); + const imgList = []; + + $('#Baca_Komik img').each((index, element) => { + const src = $(element).attr('src'); + imgList.push({ path: "https://files.xianqiao.wang/" + src }); + }); + + const imagePaths = await downloadImages(imgList, tempDir, instanceID); + const pdfPath = await createPDF(imagePaths, instanceID, tempDir); + + return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title, Pdf_path: pdfPath }; + } catch (error) { + console.log(error); + throw error; + } finally { + await fss.rmdir(tempDir, { recursive: true }); + } } async function downloadImage(image, tempDir, instanceID) { - try { - // Fetch the image data - const response = await axios.get(image.path, { - responseType: 'arraybuffer', - headers: { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', - 'Referer': image.path, - } - }); - const buffer = Buffer.from(response.data, 'binary'); - const mimesd = await fileTypeFromBuffer(buffer); - const ext = mimesd ? mimesd.ext : 'jpeg'; - const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`; - await writeFileAsync(imagePath, buffer); - return imagePath; - } catch (error) { - console.error('Error downloading image:', error); - throw error; - } + try { + // Fetch the image data + const response = await axios.get(image.path, { + responseType: 'arraybuffer', + headers: { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0.1; SM-N916S Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/106.0.5249.126 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/389.0.0.42.111;]', + 'Referer': image.path, + } + }); + const buffer = Buffer.from(response.data, 'binary'); + const mimesd = await fileTypeFromBuffer(buffer); + const ext = mimesd ? mimesd.ext : 'jpeg'; + const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`; + await writeFileAsync(imagePath, buffer); + return imagePath; + } catch (error) { + console.error('Error downloading image:', error); + throw error; + } } async function downloadImages(imgList, tempDir, instanceID) { - const imagePaths = []; - for (const img of imgList) { - const imagePath = await downloadImage(img, tempDir, instanceID); - imagePaths.push(imagePath); - } - return imagePaths; + const imagePaths = []; + for (const img of imgList) { + const imagePath = await downloadImage(img, tempDir, instanceID); + imagePaths.push(imagePath); + } + return imagePaths; } async function createPDF(imagePaths, instanceID, tempDir) { - const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`); - const doc = new PDFDocument({ - autoFirstPage: false - }); - - doc.pipe(fs.createWriteStream(pdfPath)); - - for (const imagePath of imagePaths) { - try { - // Check if image needs conversion - const imageExt = path.extname(imagePath).toLowerCase(); - const supportedExtensions = ['.jpg', '.jpeg', '.png']; - let convertedImagePath = imagePath; - - if (!fs.existsSync(imagePath) || fs.statSync(imagePath).size === 0) { - throw new Error(`Invalid or empty image file: ${imagePath}`); - } - - if (!supportedExtensions.includes(imageExt)) { - convertedImagePath = await convertImage(imagePath); - } - - const { - width, - height - } = await getImageDimensions(convertedImagePath); - doc.addPage({ - size: [width, height] - }); - doc.image(convertedImagePath, 0, 0, { - width: width, - height: height - }); - - // Remove converted images if they were created - if (convertedImagePath !== imagePath) { - fs.unlinkSync(convertedImagePath); - } - } catch (error) { - console.error(`Error processing image ${imagePath}:`, error.message); - } - } - - doc.end(); - - return pdfPath; + const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`); + const doc = new PDFDocument({ autoFirstPage: false }); + + doc.pipe(fs.createWriteStream(pdfPath)); + + for (const imagePath of imagePaths) { + try { + // Check if image needs conversion + const imageExt = path.extname(imagePath).toLowerCase(); + const supportedExtensions = ['.jpg', '.jpeg', '.png']; + let convertedImagePath = imagePath; + + if (!fs.existsSync(imagePath) || fs.statSync(imagePath).size === 0) { + throw new Error(`Invalid or empty image file: ${imagePath}`); + } + + if (!supportedExtensions.includes(imageExt)) { + convertedImagePath = await convertImage(imagePath); + } + + const { width, height } = await getImageDimensions(convertedImagePath); + doc.addPage({ size: [width, height] }); + doc.image(convertedImagePath, 0, 0, { width: width, height: height }); + + // Remove converted images if they were created + if (convertedImagePath !== imagePath) { + fs.unlinkSync(convertedImagePath); + } + } catch (error) { + console.error(`Error processing image ${imagePath}:`, error.message); + } + } + + doc.end(); + + return pdfPath; } async function getImageDimensions(imagePath) { - const dimensions = await sizeOf(imagePath); - return dimensions; + const dimensions = await sizeOf(imagePath); + return dimensions; } async function convertImage(imagePath) { - return new Promise((resolve, reject) => { - const outputImagePath = imagePath.replace(/\.\w+$/, '.jpg'); - exec(`convert "${imagePath}" "${outputImagePath}"`, (error, stdout, stderr) => { - if (error) { - console.error('ImageMagick Error:', stderr); - return reject(error); - } - resolve(outputImagePath); - }); - }); + return new Promise((resolve, reject) => { + const outputImagePath = imagePath.replace(/\.\w+$/, '.jpg'); + exec(`convert "${imagePath}" "${outputImagePath}"`, (error, stdout, stderr) => { + if (error) { + console.error('ImageMagick Error:', stderr); + return reject(error); + } + resolve(outputImagePath); + }); + }); } app.get('/download', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - - try { - const result = await komiku_download(url); - res.json(result); - setTimeout(() => { - fs.unlink(result.Pdf_path, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } else { - console.log(`File deleted: ${result.Pdf_path}`); - } - }); - }, 330000); - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + + try { + const result = await komiku_download(url); + res.json(result); + setTimeout(() => { + fs.unlink(result.Pdf_path, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } else { + console.log(`File deleted: ${result.Pdf_path}`); + } + }); + }, 330000); + } catch (error) { + res.status(500).send('Error processing request'); + } }); async function nhentai(url) { - const instanceID = generateRandomID(); - const tempDir = path.join(os.tmpdir(), instanceID); - await fs.promises.mkdir(tempDir, { - recursive: true - }); - - try { - const response = await axios.get(url, { - headers: { - 'User-Agent': 'Mozilla/5.0', - 'Referer': 'https://nhentai.net/' - } - }); - - const $ = cheerio.load(response.data); - const scriptContent = $('script') - .filter((i, el) => $(el).html().includes('window._gallery = JSON.parse')) - .html(); - - const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1]; - const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\'); - const jsonData = JSON.parse(decodedString); - - const imgList = jsonData.images.pages.map((_, index) => ({ - path: `https://i5.nhentai.net/galleries/${jsonData.media_id}/${index + 1}.${jsonData.images.pages[index].t === "w" ? "webp" : jsonData.images.pages[index].t === "p" ? "png" : "jpg"}` - })); - - const imagePaths = []; - for (const img of imgList) { - const downloadedImagePath = await downloadImageNh(img, tempDir, instanceID); - imagePaths.push(downloadedImagePath); - } - - const pdfPath = await createPDF(imagePaths, instanceID, tempDir); - console.log(`PDF successfully created: ${pdfPath}`); - return { - url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, - path: pdfPath, - result: jsonData - }; - } catch (error) { - console.error(error); - throw error; - } finally { - await fs.promises.rm(tempDir, { - recursive: true - }); - } + const instanceID = generateRandomID(); + const tempDir = path.join(os.tmpdir(), instanceID); + await fs.promises.mkdir(tempDir, { recursive: true }); + + try { + const response = await axios.get(url, { + headers: { + 'User-Agent': 'Mozilla/5.0', + 'Referer': 'https://nhentai.net/' + } + }); + + const $ = cheerio.load(response.data); + const scriptContent = $('script') + .filter((i, el) => $(el).html().includes('window._gallery = JSON.parse')) + .html(); + + const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1]; + const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\'); + const jsonData = JSON.parse(decodedString); + + const imgList = jsonData.images.pages.map((_, index) => ({ + path: `https://i5.nhentai.net/galleries/${jsonData.media_id}/${index + 1}.${jsonData.images.pages[index].t === "w" ? "webp" : jsonData.images.pages[index].t === "p" ? "png" : "jpg"}` + })); + + const imagePaths = []; + for (const img of imgList) { + const downloadedImagePath = await downloadImageNh(img, tempDir, instanceID); + imagePaths.push(downloadedImagePath); + } + + const pdfPath = await createPDF(imagePaths, instanceID, tempDir); + console.log(`PDF successfully created: ${pdfPath}`); + return { + url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`, + path: pdfPath, + result: jsonData + }; + } catch (error) { + console.error(error); + throw error; + } finally { + await fs.promises.rm(tempDir, { recursive: true }); + } } // PERUBAHAN: Gunakan sharp untuk konversi gambar async function convertImageV2(inputPath, outputPath) { - try { - await sharp(inputPath).toFormat('jpeg').toFile(outputPath); - console.log(`Converted ${inputPath} to ${outputPath}`); - return outputPath; - } catch (error) { - console.error(`Error converting image: ${error.message}`); - throw new Error(`Failed to convert image ${inputPath} to JPG.`); - } + try { + await sharp(inputPath).toFormat('jpeg').toFile(outputPath); + console.log(`Converted ${inputPath} to ${outputPath}`); + return outputPath; + } catch (error) { + console.error(`Error converting image: ${error.message}`); + throw new Error(`Failed to convert image ${inputPath} to JPG.`); + } } async function convertImageToJPG(inputPath, outputPath) { - try { - await execAsync(`ffmpeg -i "${inputPath}" -q:v 1 "${outputPath}"`); - console.log(`Converted ${inputPath} to ${outputPath}`); - return outputPath; - } catch (error) { - console.error(`Error converting image: ${error.message}`); - throw new Error(`Failed to convert image ${inputPath} to JPG.`); - } + try { + await execAsync(`ffmpeg -i "${inputPath}" -q:v 1 "${outputPath}"`); + console.log(`Converted ${inputPath} to ${outputPath}`); + return outputPath; + } catch (error) { + console.error(`Error converting image: ${error.message}`); + throw new Error(`Failed to convert image ${inputPath} to JPG.`); + } } async function downloadImageNh(image, tempDir, instanceID) { - const servers = [ - "https://i1.nhentai.net", - "https://i2.nhentai.net", - "https://i4.nhentai.net", - "https://i5.nhentai.net", - "https://i3.nhentai.net", - "https://i7.nhentai.net" - ]; - - for (const server of servers) { - try { - const imageUrl = `${server}/galleries/${image.path.split('galleries/')[1]}`; - console.log(`Downloading image from: ${imageUrl}`); - - const response = await axios.get(imageUrl, { - responseType: 'arraybuffer', - headers: { - 'User-Agent': 'Mozilla/5.0', - 'Referer': 'https://nhentai.net/' - } - }); - - let imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.webp`; - await fs.promises.writeFile(imagePath, response.data); - - const isWebp = path.extname(imagePath).toLowerCase() === '.webp'; - if (isWebp) { - const convertedPath = imagePath.replace('.webp', '.jpg'); - imagePath = await convertImageToJPG(imagePath, convertedPath); - fs.unlinkSync(imagePath.replace('.jpg', '.webp')); // Hapus file asli `webp` - } - - return imagePath; - } catch (error) { - console.error(`Error downloading image from ${server}:`, error.message); - } - } - - throw new Error('Failed to download image from all servers.'); + const servers = [ + "https://i1.nhentai.net", + "https://i2.nhentai.net", + "https://i4.nhentai.net", + "https://i5.nhentai.net", + "https://i3.nhentai.net", + "https://i7.nhentai.net" + ]; + + for (const server of servers) { + try { + const imageUrl = `${server}/galleries/${image.path.split('galleries/')[1]}`; + console.log(`Downloading image from: ${imageUrl}`); + + const response = await axios.get(imageUrl, { + responseType: 'arraybuffer', + headers: { + 'User-Agent': 'Mozilla/5.0', + 'Referer': 'https://nhentai.net/' + } + }); + + let imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.webp`; + await fs.promises.writeFile(imagePath, response.data); + + const isWebp = path.extname(imagePath).toLowerCase() === '.webp'; + if (isWebp) { + const convertedPath = imagePath.replace('.webp', '.jpg'); + imagePath = await convertImageToJPG(imagePath, convertedPath); + fs.unlinkSync(imagePath.replace('.jpg', '.webp')); // Hapus file asli `webp` + } + + return imagePath; + } catch (error) { + console.error(`Error downloading image from ${server}:`, error.message); + } + } + + throw new Error('Failed to download image from all servers.'); } async function downloadImageNhs(imgList, tempDir, instanceID) { - const imagePaths = []; - for (const img of imgList) { - const imagePath = await downloadImageNh(img, tempDir, instanceID); - imagePaths.push(imagePath); - } - return imagePaths; + const imagePaths = []; + for (const img of imgList) { + const imagePath = await downloadImageNh(img, tempDir, instanceID); + imagePaths.push(imagePath); + } + return imagePaths; } app.get('/nhentai', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await nhentai(url); - res.json(result); - setTimeout(() => { - fs.unlink(result.path, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } else { - console.log(`File deleted: ${result.path}`); - } - }); - }, 370000); - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await nhentai(url); + res.json(result); + setTimeout(() => { + fs.unlink(result.path, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } else { + console.log(`File deleted: ${result.path}`); + } + }); + }, 370000); + } catch (error) { + res.status(500).send('Error processing request'); + } }); async function downloadFromUrl(url, filePath, biskuit) { - const writer = fs.createWriteStream(filePath); - - const response = await axios({ - url, - method: 'GET', - responseType: 'stream', - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', - 'Referer': url, - 'Cookie': biskuit - } - }); - - response.data.pipe(writer); - - return new Promise((resolve, reject) => { - writer.on('finish', resolve); - writer.on('error', reject); - }); + const writer = fs.createWriteStream(filePath); + + const response = await axios({ + url, + method: 'GET', + responseType: 'stream', + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Referer': url, + 'Cookie': biskuit + } + }); + + response.data.pipe(writer); + + return new Promise((resolve, reject) => { + writer.on('finish', resolve); + writer.on('error', reject); + }); } async function Rules34Infonues(url_r34) { - try { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); - - await page.setExtraHTTPHeaders({ - 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', - 'Referer': url_r34 - }); - - await page.goto(url_r34, { - referer: url_r34 - }); - - const htmlContent = await page.content(); - const $ = cheerio.load(htmlContent); - - const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || - url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; - - const infoElements = $("#tab_video_info > div"); - const result = { - title, - artist: [], - uploader: [], - tags: [], - download: [], - category: [] - }; - - if (infoElements.length > 0) { - const [videoInfo, tags, download] = [ - infoElements.eq(infoElements.length - 3), - infoElements.eq(infoElements.length - 2), - infoElements.eq(infoElements.length - 1) - ]; - - tags.find("div.wrap > a").each((_, element) => { - result.tags.push({ - title: $(element).text().trim(), - url: $(element).attr('href') - }); - }); - result.tags.pop(); // Menghapus elemen terakhir dari tags - - download.find("div.wrap > a").each((_, element) => { - result.download.push({ - quality: $(element).text().trim(), - url: $(element).attr('href') - }); - }); - - videoInfo.find("div.cols > div").each((_, col) => { - $(col).find("div.col:nth-child(1) > a").each((_, link) => { - result.category.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - $(col).find("div.col:nth-child(2) > a").each((_, link) => { - result.artist.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - $(col).find("div.col:nth-child(3) > a").each((_, link) => { - result.uploader.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - }); - } - - await browser.close(); - return result; - } catch (error) { - console.error('Error fetching data:', error); - throw error; // Lempar ulang error untuk ditangani di level atas - } + try { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + + await page.setExtraHTTPHeaders({ + 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Referer': url_r34 + }); + + await page.goto(url_r34, { referer: url_r34 }); + + const htmlContent = await page.content(); + const $ = cheerio.load(htmlContent); + + const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || + url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; + + const infoElements = $("#tab_video_info > div"); + const result = { + title, + artist: [], + uploader: [], + tags: [], + download: [], + category: [] + }; + + if (infoElements.length > 0) { + const [videoInfo, tags, download] = [ + infoElements.eq(infoElements.length - 3), + infoElements.eq(infoElements.length - 2), + infoElements.eq(infoElements.length - 1) + ]; + + tags.find("div.wrap > a").each((_, element) => { + result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') }); + }); + result.tags.pop(); // Menghapus elemen terakhir dari tags + + download.find("div.wrap > a").each((_, element) => { + result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') }); + }); + + videoInfo.find("div.cols > div").each((_, col) => { + $(col).find("div.col:nth-child(1) > a").each((_, link) => { + result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + $(col).find("div.col:nth-child(2) > a").each((_, link) => { + result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + $(col).find("div.col:nth-child(3) > a").each((_, link) => { + result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + }); + } + + await browser.close(); + return result; + } catch (error) { + console.error('Error fetching data:', error); + throw error; // Lempar ulang error untuk ditangani di level atas + } } async function Rules34info(url_r34) { - try { - // Mengambil halaman HTML dengan Axios - const response = await axios.get(url_r34, { - headers: { - 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', - 'Referer': url_r34 - } - }); - - const htmlContent = response.data; - const $ = cheerio.load(htmlContent); - - const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; - - const infoElements = $("#tab_video_info > div"); - const result = { - title: title, - artist: [], - uploader: [], - tags: [], - category: [] - }; - - if (infoElements.length > 0) { - const tags = infoElements.eq(infoElements.length - 2); - const videoInfo = infoElements.eq(infoElements.length - 3); - - if (tags.length > 0) { - tags.find("div.wrap > a").each((index, element) => { - result.tags.push({ - title: $(element).text().trim(), - url: $(element).attr('href') - }); - }); - result.tags.pop(); // Menghapus elemen terakhir dari tags - } - - if (videoInfo.length > 0) { - videoInfo.find("div.cols > div").each((index, col) => { - const categoryLinks = $(col).find("div.col:nth-child(1) > a"); - categoryLinks.each((index, link) => { - result.category.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - const artistLinks = $(col).find("div.col:nth-child(2) > a"); - artistLinks.each((index, link) => { - result.artist.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - const uploaderLinks = $(col).find("div.col:nth-child(3) > a"); - uploaderLinks.each((index, link) => { - result.uploader.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - }); - } - } - - return result; - } catch (error) { - console.error('Error fetching data:', error); - throw error; // Rethrow error to handle it upstream - } + try { + // Mengambil halaman HTML dengan Axios + const response = await axios.get(url_r34, { + headers: { + 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Referer': url_r34 + } + }); + + const htmlContent = response.data; + const $ = cheerio.load(htmlContent); + + const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; + + const infoElements = $("#tab_video_info > div"); + const result = { + title: title, + artist: [], + uploader: [], + tags: [], + category: [] + }; + + if (infoElements.length > 0) { + const tags = infoElements.eq(infoElements.length - 2); + const videoInfo = infoElements.eq(infoElements.length - 3); + + if (tags.length > 0) { + tags.find("div.wrap > a").each((index, element) => { + result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') }); + }); + result.tags.pop(); // Menghapus elemen terakhir dari tags + } + + if (videoInfo.length > 0) { + videoInfo.find("div.cols > div").each((index, col) => { + const categoryLinks = $(col).find("div.col:nth-child(1) > a"); + categoryLinks.each((index, link) => { + result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + const artistLinks = $(col).find("div.col:nth-child(2) > a"); + artistLinks.each((index, link) => { + result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + const uploaderLinks = $(col).find("div.col:nth-child(3) > a"); + uploaderLinks.each((index, link) => { + result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + }); + } + } + + return result; + } catch (error) { + console.error('Error fetching data:', error); + throw error; // Rethrow error to handle it upstream + } } async function Rules34(url_r34) { - try { - const browser = await puppeteer.launch(); - const page = await browser.newPage(); + try { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); - await page.setExtraHTTPHeaders({ + await page.setExtraHTTPHeaders({ 'User-Agent': getRandomUserAgent() || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Referer': url_r34 - }); - await page.goto(url_r34, { - referer: url_r34 - }); - - const htmlContent = await page.content(); - const $ = cheerio.load(htmlContent); - - const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; - - const infoElements = $("#tab_video_info > div"); - const result = { - title: title, - artist: [], - uploader: [], - tags: [], - download: [], - category: [] - }; - - if (infoElements.length > 0) { - const tags = infoElements.eq(infoElements.length - 2); - const download = infoElements.eq(infoElements.length - 1); - const videoInfo = infoElements.eq(infoElements.length - 3); - - if (tags.length > 0) { - tags.find("div.wrap > a").each((index, element) => { - result.tags.push({ - title: $(element).text().trim(), - url: $(element).attr('href') - }); - }); - result.tags.pop(); // Menghapus elemen terakhir dari tags - } - - if (download.length > 0) { - download.find("div.wrap > a").each((index, element) => { - result.download.push({ - quality: $(element).text().trim(), - url: $(element).attr('href') - }); - }); - - // Mendownload dari URL terakhir di array download - const lastDownloadUrl = result.download[result.download.length - 1].url; - const downloadPath = path.resolve(os.tmpdir()) - let filenem = `${Date.now()}_file.mp4` - const filePath = path.join(downloadPath, filenem) - - const biskuit = await page.cookies(); - - - await downloadFromUrl(lastDownloadUrl, filePath, biskuit); - - result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result - result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result - } - - if (videoInfo.length > 0) { - videoInfo.find("div.cols > div").each((index, col) => { - const categoryLinks = $(col).find("div.col:nth-child(1) > a"); - categoryLinks.each((index, link) => { - result.category.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - const artistLinks = $(col).find("div.col:nth-child(2) > a"); - artistLinks.each((index, link) => { - result.artist.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - - const uploaderLinks = $(col).find("div.col:nth-child(3) > a"); - uploaderLinks.each((index, link) => { - result.uploader.push({ - title: $(link).text().trim(), - url: $(link).attr('href') - }); - }); - }); - } - } - - await browser.close(); - return result; - } catch (error) { - console.error('Error fetching data:', error); - throw error; // Rethrow error to handle it upstream - } + }); + await page.goto(url_r34, { referer: url_r34 }); + + const htmlContent = await page.content(); + const $ = cheerio.load(htmlContent); + + const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() || url_r34.match(/\/video\/\d+\/(.*)\//)?.[1]; + + const infoElements = $("#tab_video_info > div"); + const result = { + title: title, + artist: [], + uploader: [], + tags: [], + download: [], + category: [] + }; + + if (infoElements.length > 0) { + const tags = infoElements.eq(infoElements.length - 2); + const download = infoElements.eq(infoElements.length - 1); + const videoInfo = infoElements.eq(infoElements.length - 3); + + if (tags.length > 0) { + tags.find("div.wrap > a").each((index, element) => { + result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') }); + }); + result.tags.pop(); // Menghapus elemen terakhir dari tags + } + + if (download.length > 0) { + download.find("div.wrap > a").each((index, element) => { + result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') }); + }); + + // Mendownload dari URL terakhir di array download + const lastDownloadUrl = result.download[result.download.length - 1].url; + const downloadPath = path.resolve(os.tmpdir()) + let filenem = `${Date.now()}_file.mp4` + const filePath = path.join(downloadPath, filenem) + + const biskuit = await page.cookies(); + + + await downloadFromUrl(lastDownloadUrl, filePath, biskuit); + + result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result + result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result + } + + if (videoInfo.length > 0) { + videoInfo.find("div.cols > div").each((index, col) => { + const categoryLinks = $(col).find("div.col:nth-child(1) > a"); + categoryLinks.each((index, link) => { + result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + const artistLinks = $(col).find("div.col:nth-child(2) > a"); + artistLinks.each((index, link) => { + result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + + const uploaderLinks = $(col).find("div.col:nth-child(3) > a"); + uploaderLinks.each((index, link) => { + result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') }); + }); + }); + } + } + + await browser.close(); + return result; + } catch (error) { + console.error('Error fetching data:', error); + throw error; // Rethrow error to handle it upstream + } } app.get('/r34', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await Rules34(url); - res.json(result); - const filePath = result.downloadPath; - // Hapus file setelah 8 menit (480000 milidetik) - setTimeout(() => { - fs.unlink(filePath, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } else { - console.log(`File deleted: ${filePath}`); - } - }); - }, 280000); - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await Rules34(url); + res.json(result); + const filePath = result.downloadPath; + // Hapus file setelah 8 menit (480000 milidetik) + setTimeout(() => { + fs.unlink(filePath, (err) => { + if (err) { + console.error(`Error deleting file: ${err.message}`); + } else { + console.log(`File deleted: ${filePath}`); + } + }); + }, 280000); + } catch (error) { + res.status(500).send('Error processing request'); + } }); app.get('/r34/download', async (req, res) => { - const { - url, - type = 'download' - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - - try { - const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34 - const filePath = result.downloadPath; - - // Cek apakah file benar-benar ada sebelum mengirim - if (!fs.existsSync(filePath)) { - return res.status(404).send('File not found'); - } - - const fileName = path.basename(filePath); - const mimeType = 'video/mp4'; - - res.setHeader('Content-Type', mimeType); - - if (type === 'stream') { - const range = req.headers.range; - - if (range) { - const stat = fs.statSync(filePath); - const fileSize = stat.size; - - const parts = range.replace(/bytes=/, "").split("-"); - const start = parseInt(parts[0], 10); - const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; - - const chunksize = (end - start) + 1; - const file = fs.createReadStream(filePath, { - start, - end - }); - const head = { - 'Content-Range': `bytes ${start}-${end}/${fileSize}`, - 'Accept-Ranges': 'bytes', - 'Content-Length': chunksize, - 'Content-Type': mimeType, - }; - - res.writeHead(206, head); - file.pipe(res); - } else { - res.setHeader('Content-Length', fileSize); - res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file - } - } else if (type === 'buffer') { - fs.readFile(filePath, (err, data) => { - if (err) { - console.error('Gagal membaca file:', err); - res.status(500).send('Gagal membaca file: \n' + err); - } else { - res.setHeader('Content-Length', data.length); - res.send(data); - } - }); - } else { // Default to 'download' - res.download(filePath, fileName, (err) => { - if (err) { - console.error('Gagal mengirim file:', err); - res.status(500).send('Gagal mengirim file: \n' + err); - } - }); - } - } catch (error) { - console.error('Error processing request:', error); - res.status(500).send('Error processing request'); - } + const { url, type = 'download' } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + + try { + const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34 + const filePath = result.downloadPath; + + // Cek apakah file benar-benar ada sebelum mengirim + if (!fs.existsSync(filePath)) { + return res.status(404).send('File not found'); + } + + const fileName = path.basename(filePath); + const mimeType = 'video/mp4'; + + res.setHeader('Content-Type', mimeType); + + if (type === 'stream') { + const range = req.headers.range; + + if (range) { + const stat = fs.statSync(filePath); + const fileSize = stat.size; + + const parts = range.replace(/bytes=/, "").split("-"); + const start = parseInt(parts[0], 10); + const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; + + const chunksize = (end - start) + 1; + const file = fs.createReadStream(filePath, { start, end }); + const head = { + 'Content-Range': `bytes ${start}-${end}/${fileSize}`, + 'Accept-Ranges': 'bytes', + 'Content-Length': chunksize, + 'Content-Type': mimeType, + }; + + res.writeHead(206, head); + file.pipe(res); + } else { + res.setHeader('Content-Length', fileSize); + res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file + } + } else if (type === 'buffer') { + fs.readFile(filePath, (err, data) => { + if (err) { + console.error('Gagal membaca file:', err); + res.status(500).send('Gagal membaca file: \n' + err); + } else { + res.setHeader('Content-Length', data.length); + res.send(data); + } + }); + } else { // Default to 'download' + res.download(filePath, fileName, (err) => { + if (err) { + console.error('Gagal mengirim file:', err); + res.status(500).send('Gagal mengirim file: \n' + err); + } + }); + } + } catch (error) { + console.error('Error processing request:', error); + res.status(500).send('Error processing request'); + } }); app.get('/r34/info', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await Rules34Infonues(url); - res.json(result); - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await Rules34Infonues(url); + res.json(result); + } catch (error) { + res.status(500).send('Error processing request'); + } }); async function r34Cookie(url) { - const browser = await puppeteer.launch({ - headless: true, // Non-headless untuk debugging - args: ['--no-sandbox', '--disable-setuid-sandbox'] - }); - const page = await browser.newPage(); - // Setel header User-Agent dan Referer - await page.setExtraHTTPHeaders({ - 'User-Agent': getRandomUserAgent(), - 'Referer': url, - 'X-Forwarded-For': generateRandomIP() - }); - await page.goto(url); // Buka URL yang diberikan - const cookies = await page.cookies(); - await browser.close(); - return { - cookies - }; + const browser = await puppeteer.launch({ + headless: true, // Non-headless untuk debugging + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + const page = await browser.newPage(); + // Setel header User-Agent dan Referer + await page.setExtraHTTPHeaders({ + 'User-Agent': getRandomUserAgent(), + 'Referer': url, + 'X-Forwarded-For': generateRandomIP() + }); + await page.goto(url); // Buka URL yang diberikan + const cookies = await page.cookies(); + await browser.close(); + return { cookies }; } app.get('/r34cookie', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('URL is required'); - } - try { - const result = await r34Cookie(url); - res.json(result); - } catch (error) { - res.status(500).send('Error processing request'); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('URL is required'); + } + try { + const result = await r34Cookie(url); + res.json(result); + } catch (error) { + res.status(500).send('Error processing request'); + } }); let kue = 'p_ab_id=5; p_ab_id_2=4; p_ab_d_id=1131020051; PHPSESSID=98423123_ooWiGNZmn10FSApJ6AE7tfFStuzzSPvS; device_token=204de0e72a664d1b93d4d9bf1913c6cf; privacy_policy_agreement=7; webp_available=1; c_type=19; privacy_policy_notification=0; a_type=0; b_type=2; yuid_b=I0QxAZA; first_visit_datetime=2024-10-23%2016%3A18%3A55; __cf_bm=AF3_34pfnlX3j.z9HgTHRXT_VPiboGN1xCtpGEIAl6g-1729667935-1.0.1.1-i8bf6DbM4hqEBcXVI8PtrjFt4pgvg.SNNkr9y1wwhnilldAD6qQYltFmwlFJgVgug3zR41_1NO43zA4kdLe0MvRYRu3SkoiyaH8_bf7S4Rw; cf_clearance=myv1GHmvbUejqJyyBWI.VKf26uxBSPf_TIslXxb1t74-1729667943-1.2.1.1-pbZD7QZA95M9OqhnIuUreLC4aGuTLgXpm8DN7eRAb_XmjwLv53uYqq3vVTF06MMKOxQmVER9aZIUU7vw2zT3sGK_3nrDLHCSJ4CeAezc7yjS69guPqtmkqn.tMIuxt399W82C.9zagzJ.Eo0vs91tllX1yVBNPIZ8rV2BunLinWWIcHR8lqiVyXUgRh1VEk_juC0_Tsezh1OcZ39LswLY8da0Vf5g6z5REZRgw1X18LwBNARVetsNojdIiUasWn7jLbPCGYezaHrMsg7Eqy.sfb8T6xlGGS4hDjr_dD9sTIp7RcU6geIAl5KiY4dXjhTY3Kn1B8MugIzpSjNzBvMqkTI9fEVuil7iaPXfw_O8Dc8TPc7z2q.wk0ofJVSn.7O'; @@ -1177,367 +1039,341 @@ let kue = 'p_ab_id=5; p_ab_id_2=4; p_ab_d_id=1131020051; PHPSESSID=98423123_ooWi // Fungsi untuk mendapatkan data dari API Pixiv berdasarkan ID ilustrasi async function pixivGetData(illustId) { - const headers = { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 WhatsApp/1.2.3', - 'Referer': 'https://www.pixiv.net/', - "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`, - 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001", - 'Cookie': kue - }; - - try { - const response = await axios.get(`https://www.pixiv.net/touch/ajax/illust/details?illust_id=${illustId}&lang=en`, { - headers - }); - return response.data; - } catch (error) { - console.error("Error fetching data from Pixiv:", error); - throw error; - } + const headers = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 WhatsApp/1.2.3', + 'Referer': 'https://www.pixiv.net/', + "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`, + 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001", + 'Cookie': kue + }; + + try { + const response = await axios.get(`https://www.pixiv.net/touch/ajax/illust/details?illust_id=${illustId}&lang=en`, { headers }); + return response.data; + } catch (error) { + console.error("Error fetching data from Pixiv:", error); + throw error; + } } // Fungsi untuk mengunduh file zip dari URL dan mengekstraknya ke folder sementara async function downloadAndExtractZipFromPixivData(pixivData) { - const pixivId = pixivData.body.illust_details.id; - const zipUrl = pixivData.body.illust_details.ugoira_meta.src; - - // Generate nama folder dengan karakter acak - const randomFolderName = crypto.randomBytes(8).toString('hex'); - const outputDirectory = path.join(tmpDir, `${pixivId}_${randomFolderName}`); - - try { - const headers = { - 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 WhatsApp/1.2.3', - 'Referer': 'https://www.pixiv.net/', - "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`, - 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001", - 'Cookie': kue - }; - const response = await axios.get(zipUrl, { - responseType: 'arraybuffer', - headers - }); - - if (!fs.existsSync(outputDirectory)) { - fs.mkdirSync(outputDirectory); - } - - const zipPath = path.join(outputDirectory, `${pixivId}_ugoira.zip`); - fs.writeFileSync(zipPath, response.data); - - const zip = new AdmZip(zipPath); - zip.extractAllTo(outputDirectory, true); - console.log(`File zip berhasil diekstrak ke ${outputDirectory}`); - - return outputDirectory; - } catch (error) { - console.error("Error downloading or extracting zip:", error); - throw error; - } + const pixivId = pixivData.body.illust_details.id; + const zipUrl = pixivData.body.illust_details.ugoira_meta.src; + + // Generate nama folder dengan karakter acak + const randomFolderName = crypto.randomBytes(8).toString('hex'); + const outputDirectory = path.join(tmpDir, `${pixivId}_${randomFolderName}`); + + try { + const headers = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 12; SM-G998B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 WhatsApp/1.2.3', + 'Referer': 'https://www.pixiv.net/', + "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`, + 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001", + 'Cookie': kue + }; + const response = await axios.get(zipUrl, { responseType: 'arraybuffer', headers }); + + if (!fs.existsSync(outputDirectory)) { + fs.mkdirSync(outputDirectory); + } + + const zipPath = path.join(outputDirectory, `${pixivId}_ugoira.zip`); + fs.writeFileSync(zipPath, response.data); + + const zip = new AdmZip(zipPath); + zip.extractAllTo(outputDirectory, true); + console.log(`File zip berhasil diekstrak ke ${outputDirectory}`); + + return outputDirectory; + } catch (error) { + console.error("Error downloading or extracting zip:", error); + throw error; + } } // Fungsi untuk membuat video dari file image yang sudah diekstrak async function createVideoFromExtractedImages(pixivData, frameDir) { - const pixivId = pixivData.body.illust_details.id; - const frames = pixivData.body.illust_details.ugoira_meta.frames; - - const frameListFile = path.join(frameDir, 'frames.txt'); - const frameListContent = frames - .map(frame => { - const framePath = path.join(frameDir, frame.file); - return `file '${frame.file}'\nduration ${frame.delay / 1000}`; - }) - .join('\n'); - - fs.writeFileSync(frameListFile, frameListContent); - console.log(`File frame list berhasil disimpan di ${frameListFile}`); - - const outputVideoPath = path.join(frameDir, `${pixivId}.mp4`); - - if (fs.existsSync(frameListFile)) { - //await execAsync(`ffmpeg -f concat -safe 0 -i "${frameListFile}" -vsync vfr -pix_fmt yuv420p "${outputVideoPath}"`); - await execAsync(`ffmpeg -f concat -safe 0 -i "${frameListFile}" -vf "format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2" -fps_mode vfr -pix_fmt yuv420p "${outputVideoPath}"`); - - console.log(`Video berhasil dibuat: ${outputVideoPath}`); - return outputVideoPath; - } else { - throw new Error(`File frames.txt tidak ditemukan di ${frameListFile}`); - } + const pixivId = pixivData.body.illust_details.id; + const frames = pixivData.body.illust_details.ugoira_meta.frames; + + const frameListFile = path.join(frameDir, 'frames.txt'); + const frameListContent = frames + .map(frame => { + const framePath = path.join(frameDir, frame.file); + return `file '${frame.file}'\nduration ${frame.delay / 1000}`; + }) + .join('\n'); + + fs.writeFileSync(frameListFile, frameListContent); + console.log(`File frame list berhasil disimpan di ${frameListFile}`); + + const outputVideoPath = path.join(frameDir, `${pixivId}.mp4`); + + if (fs.existsSync(frameListFile)) { + //await execAsync(`ffmpeg -f concat -safe 0 -i "${frameListFile}" -vsync vfr -pix_fmt yuv420p "${outputVideoPath}"`); + await execAsync(`ffmpeg -f concat -safe 0 -i "${frameListFile}" -vf "format=yuv420p,scale=trunc(iw/2)*2:trunc(ih/2)*2" -fps_mode vfr -pix_fmt yuv420p "${outputVideoPath}"`); + + console.log(`Video berhasil dibuat: ${outputVideoPath}`); + return outputVideoPath; + } else { + throw new Error(`File frames.txt tidak ditemukan di ${frameListFile}`); + } } // Fungsi untuk menghapus folder setelah delay tertentu function scheduleFolderDeletion(directory) { - setTimeout(() => { - fs.rmSync(directory, { - recursive: true, - force: true - }); - console.log(`Folder ${directory} dan isinya telah dihapus.`); - }, deleteFilesAfter); + setTimeout(() => { + fs.rmSync(directory, { recursive: true, force: true }); + console.log(`Folder ${directory} dan isinya telah dihapus.`); + }, deleteFilesAfter); } // Endpoint untuk memproses permintaan dan mengirimkan URL video app.get("/process-pixiv/:illustId", async (req, res) => { - const { - illustId - } = req.params; - - try { - const pixivData = await pixivGetData(illustId); - const frameDir = await downloadAndExtractZipFromPixivData(pixivData); - const videoPath = await createVideoFromExtractedImages(pixivData, frameDir); - - // Buat URL untuk mengakses file mp4 - const videoUrl = `https://arashicode-komik.hf.space/static/${path.relative(tmpDir, videoPath)}`; - - // Kirim URL file mp4 dalam format JSON - res.json({ - url: videoUrl - }); - - // Jadwalkan penghapusan file setelah 2 menit - scheduleFolderDeletion(frameDir); - } catch (error) { - console.error("Error processing Pixiv illustration:", error); - res.status(500).send("Error processing illustration."); - } + const { illustId } = req.params; + + try { + const pixivData = await pixivGetData(illustId); + const frameDir = await downloadAndExtractZipFromPixivData(pixivData); + const videoPath = await createVideoFromExtractedImages(pixivData, frameDir); + + // Buat URL untuk mengakses file mp4 + const videoUrl = `https://arashicode-komik.hf.space/static/${path.relative(tmpDir, videoPath)}`; + + // Kirim URL file mp4 dalam format JSON + res.json({ url: videoUrl }); + + // Jadwalkan penghapusan file setelah 2 menit + scheduleFolderDeletion(frameDir); + } catch (error) { + console.error("Error processing Pixiv illustration:", error); + res.status(500).send("Error processing illustration."); + } }); async function scrapeHAnime(query) { - const baseUrl = "https://animeidhentai.com"; - const searchUrl = `${baseUrl}/?s=${encodeURIComponent(query)}`; - const browser = await puppeteer.launch({ - headless: true, - args: ['--no-sandbox', '--disable-setuid-sandbox'] - }); - const page = await browser.newPage(); - await page.goto(searchUrl, { - waitUntil: 'domcontentloaded' - }); - - try { - // Ambil data video - const videos = await page.evaluate(() => { - return [...document.querySelectorAll("body > main > section > div.anime-list.dg.gt2.gg1.mgt1.a-gtf.v-grid > article")].map(article => { - const urlElement = article.querySelector("a"); - const titleElement = article.querySelector("header > div"); - const descElement = article.querySelector("div.description.dn > p"); - const thumbnailElement = article.querySelector("div.anime-tb.pctr.rad1.por > figure > img"); - - return { - url: urlElement ? urlElement.href : null, - title: titleElement ? titleElement.textContent.trim() : null, - description: descElement ? descElement.textContent.trim() : null, - thumbnail: thumbnailElement ? thumbnailElement.src : null - }; - }); - }); - - // Hitung halaman berikutnya - const nextPage = await page.evaluate(() => { - const nextButton = document.querySelector("body > main > section > div.pagination-wrapper > a.next.page-numbers.ljoptimizer"); - if (nextButton) { - const currentUrl = window.location.href; - const currentPageMatch = currentUrl.match(/page\/(\d+)/); - const currentPage = currentPageMatch ? parseInt(currentPageMatch[1], 10) : 1; - return currentPage + 1; - } - return null; - }); - console.log(videos) - - const result = { - next: nextPage ? `${baseUrl}/page/${nextPage}/?s=${encodeURIComponent(query)}` : null, - videos - }; - - await browser.close(); - return result; - - } catch (error) { - console.log("Error scraping data:", error); - await browser.close(); - return { - next: null, - videos: [] - }; - } + const baseUrl = "https://animeidhentai.com"; + const searchUrl = `${baseUrl}/?s=${encodeURIComponent(query)}`; + const browser = await puppeteer.launch({ + headless: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + const page = await browser.newPage(); + await page.goto(searchUrl, { waitUntil: 'domcontentloaded' }); + + try { + // Ambil data video + const videos = await page.evaluate(() => { + return [...document.querySelectorAll("body > main > section > div.anime-list.dg.gt2.gg1.mgt1.a-gtf.v-grid > article")].map(article => { + const urlElement = article.querySelector("a"); + const titleElement = article.querySelector("header > div"); + const descElement = article.querySelector("div.description.dn > p"); + const thumbnailElement = article.querySelector("div.anime-tb.pctr.rad1.por > figure > img"); + + return { + url: urlElement ? urlElement.href : null, + title: titleElement ? titleElement.textContent.trim() : null, + description: descElement ? descElement.textContent.trim() : null, + thumbnail: thumbnailElement ? thumbnailElement.src : null + }; + }); + }); + + // Hitung halaman berikutnya + const nextPage = await page.evaluate(() => { + const nextButton = document.querySelector("body > main > section > div.pagination-wrapper > a.next.page-numbers.ljoptimizer"); + if (nextButton) { + const currentUrl = window.location.href; + const currentPageMatch = currentUrl.match(/page\/(\d+)/); + const currentPage = currentPageMatch ? parseInt(currentPageMatch[1], 10) : 1; + return currentPage + 1; + } + return null; + }); + console.log(videos) + + const result = { + next: nextPage ? `${baseUrl}/page/${nextPage}/?s=${encodeURIComponent(query)}` : null, + videos + }; + + await browser.close(); + return result; + + } catch (error) { + console.log("Error scraping data:", error); + await browser.close(); + return { next: null, videos: [] }; + } } async function scrapeHAnimeDetails(url) { - const browser = await puppeteer.launch({ - headless: true, - args: ["--no-sandbox", "--disable-setuid-sandbox"], - }); - - try { - const page = await browser.newPage(); - await page.setUserAgent( - "Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]" - ); - - // Buka halaman utama - await page.goto(url, { - waitUntil: "domcontentloaded" - }); - - // Ambil metadata - const result = await page.evaluate(() => { - const getText = (selector) => { - const element = document.querySelector(selector); - return element ? element.textContent.trim() : null; - }; - - const getGenre = () => { - return [...document.querySelectorAll("body > main > article > aside.anime-cn.clb > div.genres.mgt.df.fww.por > a")] - .map((genre) => genre.textContent.trim()); - }; - - return { - title: getText("body > main > article > aside.anime-cn.clb > header > h1"), - tahunRilis: getText("body > main > article > aside.anime-cn.clb > header > div > p > a.mgr.mgb.fwb"), - tahunUpload: getText("body > main > article > aside.anime-cn.clb > header > div > p > span:nth-child(9)"), - subtitleLang: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(5)"), - quality: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(3)"), - description: getText("body > main > article > aside.anime-cn.clb > div.description.link-co.mgb2"), - genre: getGenre(), - }; - }); - - //console.log("Metadata:", result); - - // Tunggu iframe muncul - await page.waitForSelector( - "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe", { - timeout: 20000 - } - ); - - // Ambil URL iframe - const iframeSrc = await page.evaluate(() => { - const iframe = document.querySelector( - "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe" - ); - return iframe ? iframe.src : null; - }); - - if (!iframeSrc) throw new Error("Iframe tidak ditemukan!"); - - console.log("Iframe Source:", iframeSrc); - - // Gunakan API HTML untuk mengambil data iframe - const responseA = await axios.get(`https://arashicode-api.hf.space/html?url=${iframeSrc}`); - const iframeHTML = responseA.data; - result.iframeHTML = iframeHTML; - - // Ambil data-id dari HTML iframe - const $ = cheerio.load(iframeHTML); - const dataIdElement = $("div.servers > ul > li"); - const dataId = dataIdElement.length ? - "https://nhplayer.com" + dataIdElement.attr("data-id") : - null; - - if (dataId) { - console.log("Data-ID URL:", dataId); - - // Ambil konten dari data-id - const responseB = await axios.get(`https://arashicode-api.hf.space/html?url=${dataId}`); - const newPageHTML = responseB.data; - console.log("HTML Konten Data-ID:", newPageHTML); - - // Ekstrak URL video langsung dari HTML - const videoUrlRegex = /file:\s*"(https?:\/\/[^"]+\.mp4)"/; - const match = newPageHTML.match(videoUrlRegex); - - if (match && match[1]) { - result.video = match[1]; - console.log("Video URL:", result.video); - } else { - console.log("Video URL tidak ditemukan dalam HTML!"); - } + const browser = await puppeteer.launch({ + headless: true, + args: ["--no-sandbox", "--disable-setuid-sandbox"], + }); + + try { + const page = await browser.newPage(); + await page.setUserAgent( + "Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]" + ); + + // Buka halaman utama + await page.goto(url, { waitUntil: "domcontentloaded" }); + + // Ambil metadata + const result = await page.evaluate(() => { + const getText = (selector) => { + const element = document.querySelector(selector); + return element ? element.textContent.trim() : null; + }; + + const getGenre = () => { + return [...document.querySelectorAll("body > main > article > aside.anime-cn.clb > div.genres.mgt.df.fww.por > a")] + .map((genre) => genre.textContent.trim()); + }; + + return { + title: getText("body > main > article > aside.anime-cn.clb > header > h1"), + tahunRilis: getText("body > main > article > aside.anime-cn.clb > header > div > p > a.mgr.mgb.fwb"), + tahunUpload: getText("body > main > article > aside.anime-cn.clb > header > div > p > span:nth-child(9)"), + subtitleLang: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(5)"), + quality: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(3)"), + description: getText("body > main > article > aside.anime-cn.clb > div.description.link-co.mgb2"), + genre: getGenre(), + }; + }); + + //console.log("Metadata:", result); + + // Tunggu iframe muncul + await page.waitForSelector( + "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe", + { timeout: 20000 } + ); + + // Ambil URL iframe + const iframeSrc = await page.evaluate(() => { + const iframe = document.querySelector( + "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe" + ); + return iframe ? iframe.src : null; + }); + + if (!iframeSrc) throw new Error("Iframe tidak ditemukan!"); + + console.log("Iframe Source:", iframeSrc); + + // Gunakan API HTML untuk mengambil data iframe + const responseA = await axios.get(`https://arashicode-api.hf.space/html?url=${iframeSrc}`); + const iframeHTML = responseA.data; + result.iframeHTML = iframeHTML; + + // Ambil data-id dari HTML iframe + const $ = cheerio.load(iframeHTML); + const dataIdElement = $("div.servers > ul > li"); + const dataId = dataIdElement.length + ? "https://nhplayer.com" + dataIdElement.attr("data-id") + : null; + + if (dataId) { + console.log("Data-ID URL:", dataId); + + // Ambil konten dari data-id + const responseB = await axios.get(`https://arashicode-api.hf.space/html?url=${dataId}`); + const newPageHTML = responseB.data; + console.log("HTML Konten Data-ID:", newPageHTML); + + // Ekstrak URL video langsung dari HTML + const videoUrlRegex = /file:\s*"(https?:\/\/[^"]+\.mp4)"/; + const match = newPageHTML.match(videoUrlRegex); + + if (match && match[1]) { + result.video = match[1]; + console.log("Video URL:", result.video); + } else { + console.log("Video URL tidak ditemukan dalam HTML!"); + } } - await browser.close(); - return result; - } catch (error) { - console.log("Error scraping details:", error); + await browser.close(); + return result; + } catch (error) { + console.log("Error scraping details:", error); - // Tutup browser jika terjadi error - await browser.close(); - return { - error: error.message - }; - } + // Tutup browser jika terjadi error + await browser.close(); + return { error: error.message }; + } } app.get('/hanime/search', async (req, res) => { - const { - query - } = req.query; - if (!query) { - return res.status(400).send('query is required'); - } - try { - const result = await scrapeHAnime(query); - res.json(result); - } catch (error) { - res.status(500).send('Error processing request \n\n' + error); - } + const { query } = req.query; + if (!query) { + return res.status(400).send('query is required'); + } + try { + const result = await scrapeHAnime(query); + res.json(result); + } catch (error) { + res.status(500).send('Error processing request \n\n' + error); + } }); app.get('/hanime/download', async (req, res) => { - const { - url - } = req.query; - if (!url) { - return res.status(400).send('url is required'); - } - try { - const result = await scrapeHAnimeDetails(url); - res.json(result); - } catch (error) { - res.status(500).send('Error processing request \n\n' + error); - } + const { url } = req.query; + if (!url) { + return res.status(400).send('url is required'); + } + try { + const result = await scrapeHAnimeDetails(url); + res.json(result); + } catch (error) { + res.status(500).send('Error processing request \n\n' + error); + } }); function delay(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } // Fungsi untuk ping website async function pingWebsite() { - const browser = await puppeteer.launch({ - headless: true, - args: ['--no-sandbox', '--disable-setuid-sandbox'] - }); - const page = await browser.newPage(); - await page.setUserAgent("Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]"); - await page.goto('https://huggingface.co/spaces/ArashiCode/komik/'); - console.log("Ping"); - await browser.close(); + const browser = await puppeteer.launch({ + headless: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + const page = await browser.newPage(); + await page.setUserAgent("Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]"); + await page.goto('https://huggingface.co/spaces/ArashiCode/komik/'); + console.log("Ping"); + await browser.close(); } // Ping website setiap 5 jam async function pingEvery5Hours() { - await pingWebsite(); - setInterval(async () => { - await pingWebsite(); - }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds + await pingWebsite(); + setInterval(async () => { + await pingWebsite(); + }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds } // Mulai ping pingEvery5Hours(); app.listen(PORT, () => { - console.log(`Server is running on port ${PORT}`); + console.log(`Server is running on port ${PORT}`); }); \ No newline at end of file