|
|
import express from 'express'; |
|
|
import path from 'path'; |
|
|
import os from 'os'; |
|
|
import PDFDocument from 'pdfkit'; |
|
|
import fs from 'fs'; |
|
|
import axios from 'axios'; |
|
|
import cheerio from 'cheerio'; |
|
|
import { promisify } from 'util'; |
|
|
import { createRequire } from 'module'; |
|
|
import { fileURLToPath } from 'url'; |
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url)); |
|
|
|
|
|
const require = createRequire(import.meta.url); |
|
|
const puppeteer = require('puppeteer'); |
|
|
const PORT = process.env.PORT || 7860; |
|
|
const app = express(); |
|
|
const writeFileAsync = promisify(fs.writeFile); |
|
|
const fss = fs.promises; |
|
|
|
|
|
|
|
|
app.use('/static', express.static(os.tmpdir())); |
|
|
|
|
|
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 generateRandomIP = () => { |
|
|
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; |
|
|
} |
|
|
|
|
|
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: 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 }; |
|
|
} catch (error) { |
|
|
console.log(error); |
|
|
throw error; |
|
|
} finally { |
|
|
await fss.rmdir(tempDir, { recursive: true }); |
|
|
} |
|
|
} |
|
|
|
|
|
async function downloadImage(image, tempDir, instanceID) { |
|
|
const response = await axios.get(image.path, { |
|
|
responseType: 'arraybuffer', |
|
|
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 imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`); |
|
|
await writeFileAsync(imagePath, response.data); |
|
|
|
|
|
return imagePath; |
|
|
} |
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
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) { |
|
|
const { width, height } = await getImageDimensions(imagePath); |
|
|
doc.addPage({ size: [width, height] }); |
|
|
doc.image(imagePath, 0, 0, { width: width, height: height }); |
|
|
} |
|
|
|
|
|
doc.end(); |
|
|
|
|
|
return pdfPath; |
|
|
} |
|
|
|
|
|
async function getImageDimensions(imagePath) { |
|
|
const sizeOf = promisify(require('image-size')); |
|
|
const dimensions = await sizeOf(imagePath); |
|
|
return dimensions; |
|
|
} |
|
|
|
|
|
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); |
|
|
} catch (error) { |
|
|
res.status(500).send('Error processing request'); |
|
|
} |
|
|
}); |
|
|
|
|
|
async function nhentai(url) { |
|
|
const instanceID = generateRandomID(); |
|
|
const tempDir = `./${instanceID}`; |
|
|
await fss.mkdir(tempDir); |
|
|
const title = url.split('g/').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://nhentai.net/', |
|
|
'X-Forwarded-For': generateRandomIP() |
|
|
} |
|
|
}) |
|
|
const $ = cheerio.load(response.data); |
|
|
const scriptContent = $('script').filter((i, el) => { |
|
|
return $(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); |
|
|
console.log(jsonData) |
|
|
|
|
|
const imgList = []; |
|
|
for (let i = 0; i < jsonData.images.pages.length; i++) { |
|
|
imgList.push({ path: `https://external-content.duckduckgo.com/iu/?u=https://i5.nhentai.net/galleries/${jsonData.media_id}/${i + 1}.jpg&f=1&nofb=1` }); |
|
|
} |
|
|
|
|
|
const imagePaths = await downloadImageNhs(imgList, tempDir, instanceID); |
|
|
const pdfPath = await createPDF(imagePaths, instanceID, tempDir); |
|
|
|
|
|
console.log(`PDF berhasil dibuat: ${pdfPath}`); |
|
|
return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: pdfPath, result: jsonData }; |
|
|
} catch (error) { |
|
|
console.log(error); |
|
|
throw error; |
|
|
} finally { |
|
|
await fss.rmdir(tempDir, { recursive: true }); |
|
|
} |
|
|
} |
|
|
|
|
|
async function downloadImageNh(image, tempDir, instanceID) { |
|
|
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': 'https://nhentai.net/' |
|
|
} |
|
|
}); |
|
|
|
|
|
const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`; |
|
|
await writeFileAsync(imagePath, response.data); |
|
|
|
|
|
return imagePath; |
|
|
} |
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
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); |
|
|
} catch (error) { |
|
|
res.status(500).send('Error processing request'); |
|
|
} |
|
|
}); |
|
|
|
|
|
async function r34(url) { |
|
|
const browser = await puppeteer.launch({ |
|
|
headless: false, |
|
|
args: ['--no-sandbox', '--disable-setuid-sandbox'] |
|
|
}); |
|
|
|
|
|
const page = await browser.newPage(); |
|
|
|
|
|
|
|
|
await page.setExtraHTTPHeaders({ |
|
|
'User-Agent': getRandomUserAgent(), |
|
|
'Referer': url, |
|
|
'X-Forwarded-For': generateRandomIP() |
|
|
}); |
|
|
|
|
|
|
|
|
const downloadPath = fs.mkdtempSync(path.join(os.tmpdir(), 'r34')); |
|
|
|
|
|
await page._client.send('Page.setDownloadBehavior', { |
|
|
behavior: 'allow', |
|
|
downloadPath: downloadPath |
|
|
}); |
|
|
|
|
|
await page.goto(url); |
|
|
|
|
|
|
|
|
await page.click("#tab_video_info > div:nth-child(4) > div > a:nth-child(5)"); |
|
|
|
|
|
|
|
|
let filename = ''; |
|
|
while (filename === '') { |
|
|
const files = fs.readdirSync(downloadPath); |
|
|
if (files.length > 0) { |
|
|
filename = files[0]; |
|
|
} else { |
|
|
await new Promise(resolve => setTimeout(resolve, 100)); |
|
|
} |
|
|
} |
|
|
|
|
|
await browser.close(); |
|
|
|
|
|
return { path: path.join(downloadPath, filename), url: url }; |
|
|
} |
|
|
|
|
|
app.get('/r34', async (req, res) => { |
|
|
const { url } = req.query; |
|
|
if (!url) { |
|
|
return res.status(400).send('URL is required'); |
|
|
} |
|
|
try { |
|
|
const result = await r34(url); |
|
|
res.json(result); |
|
|
} catch (error) { |
|
|
res.status(500).send('Error processing request'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
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(); |
|
|
} |
|
|
|
|
|
|
|
|
async function pingEvery5Hours() { |
|
|
await pingWebsite(); |
|
|
setInterval(async () => { |
|
|
await pingWebsite(); |
|
|
}, 5 * 60 * 60 * 1000); |
|
|
} |
|
|
|
|
|
|
|
|
pingEvery5Hours(); |
|
|
|
|
|
app.listen(PORT, () => { |
|
|
console.log(`Server is running on port ${PORT}`); |
|
|
}); |