Nexchan commited on
Commit
89934ed
·
verified ·
1 Parent(s): 1ac19fc

Upload index.js

Browse files
Files changed (1) hide show
  1. index.js +1379 -0
index.js ADDED
@@ -0,0 +1,1379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import express from 'express';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import PDFDocument from 'pdfkit';
5
+ import fs from 'fs';
6
+ import axios from 'axios';
7
+ import { promisify } from 'util';
8
+ import { createRequire } from 'module';
9
+ import { fileURLToPath } from 'url';
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ import puppeteer from "puppeteer"
12
+ import sharp from 'sharp';
13
+ import { fileTypeFromBuffer } from 'file-type';
14
+ const require = createRequire(import.meta.url);
15
+ const PORT = process.env.PORT || 7860;
16
+ const app = express();
17
+ const writeFileAsync = promisify(fs.writeFile);
18
+ const fss = fs.promises;
19
+ import sizeOf from 'image-size';
20
+ const { exec } = require('child_process');
21
+ const cheerio = require('cheerio');
22
+ app.use('/static', express.static(os.tmpdir()));
23
+ import AdmZip from "adm-zip";
24
+ const deleteFilesAfter = 2 * 60 * 1000; // 2 minutes
25
+ const execAsync = promisify(exec);
26
+ const tmpDir = os.tmpdir();
27
+ import crypto from 'crypto';
28
+
29
+
30
+ function getRandomUserAgent() {
31
+ const userAgents = [
32
+ '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;]',
33
+ '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)',
34
+ '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;]',
35
+ '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',
36
+ '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;]',
37
+ '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',
38
+ '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',
39
+ '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;]',
40
+ '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;]',
41
+ '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;]',
42
+ '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',
43
+ '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',
44
+ '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;]',
45
+ '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',
46
+ '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',
47
+ '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',
48
+ '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',
49
+ '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',
50
+ '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',
51
+ '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',
52
+ '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',
53
+ '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;]',
54
+ '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',
55
+ '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;]',
56
+ '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',
57
+ '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',
58
+ '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;]',
59
+ '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',
60
+ '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;]',
61
+ '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',
62
+ '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;]',
63
+ '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',
64
+ '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;]',
65
+ '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;]'
66
+ ];
67
+
68
+ const randomIndex = Math.floor(Math.random() * userAgents.length);
69
+ return userAgents[randomIndex];
70
+ }
71
+
72
+ app.get('/puppet', async (req, res) => {
73
+ const url = req.query.url;
74
+ if (!url) {
75
+ return res.status(400).send('URL query parameter is required');
76
+ }
77
+ try {
78
+ const browser = await puppeteer.launch();
79
+ /*({
80
+ headless: true,
81
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
82
+ });*/
83
+ const page = await browser.newPage();
84
+ await page.setUserAgent(
85
+ 'Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) ' +
86
+ 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 ' +
87
+ 'Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]'
88
+ );
89
+ await page.setExtraHTTPHeaders({
90
+ 'Accept-Language': 'en-US,en;q=0.9',
91
+ 'Accept-Encoding': 'gzip, deflate, br',
92
+ 'Connection': 'keep-alive'
93
+ });
94
+
95
+ await page.goto(url, {
96
+ waitUntil: 'domcontentloaded',
97
+ timeout: 60000 // Timeout untuk navigasi
98
+ });
99
+
100
+ await page.waitForNavigation({
101
+ waitUntil: 'networkidle0',
102
+ timeout: 60000 // Timeout untuk menunggu navigasi selesai
103
+ });
104
+
105
+ const htmlContent = await page.content();
106
+ await new Promise(resolve => setTimeout(resolve, 15000));
107
+ await browser.close();
108
+ res.send(htmlContent);
109
+ } catch (error) {
110
+ console.error('Error fetching HTML:', error);
111
+ res.status(500).send('Error fetching HTML content');
112
+ }
113
+ });
114
+
115
+ const generateRandomIP = () => {
116
+ const octet = () => Math.floor(Math.random() * 256);
117
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
118
+ };
119
+
120
+ function generateRandomID(length = 8) {
121
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
122
+ let result = '';
123
+ for (let i = 0; i < length; i++) {
124
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
125
+ }
126
+ return result;
127
+ }
128
+
129
+ /*******************************************/
130
+ async function toonCubus(url) {
131
+ const instanceID = generateRandomID();
132
+ const tempDir = path.join(os.tmpdir(), instanceID);
133
+ let browser;
134
+
135
+ try {
136
+ // Ensure tempDir creation
137
+ await fss.mkdir(tempDir, { recursive: true });
138
+
139
+ // Extract title safely
140
+ const title = url.split('/').pop().split('.')[0];
141
+
142
+ browser = await puppeteer.launch({
143
+ headless: true,
144
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
145
+ });
146
+
147
+ const page = await browser.newPage();
148
+ 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;]");
149
+ await page.goto(url, { waitUntil: 'networkidle2' });
150
+
151
+ const data = await page.evaluate(() => {
152
+ const elements = document.querySelectorAll("#Blog1 > div > div.check-box > center > a img");
153
+ return Array.from(elements).map(img => ({ path: img.src }));
154
+ });
155
+
156
+ const imagePaths = await downloadImages(data, tempDir, instanceID);
157
+ console.log(imagePaths)
158
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
159
+
160
+ return {
161
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
162
+ path: `/static/${instanceID}.pdf`,
163
+ title: title,
164
+ Pdf_path: pdfPath
165
+ };
166
+ } catch (error) {
167
+ console.error('Error in toonCubus:', error);
168
+ throw error;
169
+ } finally {
170
+ if (browser) {
171
+ await browser.close();
172
+ }
173
+ try {
174
+ await fss.rmdir(tempDir, { recursive: true, force: true });
175
+ } catch (cleanupError) {
176
+ console.error('Error cleaning up temp directory:', cleanupError);
177
+ }
178
+ }
179
+ }
180
+
181
+
182
+ app.get('/tooncubus', async (req, res) => {
183
+ const { url } = req.query;
184
+ if (!url) {
185
+ return res.status(400).send('URL is required');
186
+ }
187
+ try {
188
+ const result = await toonCubus(url);
189
+ exec(`ls ${os.tmpdir()}`, (err, stdout) => {
190
+ if (err) console.error(err);
191
+ else console.log(stdout);
192
+ });
193
+ res.json(result);
194
+ setTimeout(async () => {
195
+ try {
196
+ await fs.unlink(result.Pdf_path);
197
+ console.log(`File deleted: ${result.Pdf_path}`);
198
+ } catch (err) {
199
+ console.error(`Error deleting file: ${err.message}`);
200
+ }
201
+ }, 330000); // 5 minutes
202
+ } catch (error) {
203
+ res.status(500).send('Error processing request');
204
+ }
205
+ });
206
+ /********************************************/
207
+
208
+ /*******************************************/
209
+ function extractGalleryToken(url) {
210
+ const regex = /https:\/\/e-hentai\.org\/g\/(\d+)\/([\w-]+)\/?/;
211
+ const match = url.match(regex);
212
+ return match
213
+ ? { gallery_id: match[1], gallery_token: match[2], valid: true }
214
+ : { gallery_id: null, gallery_token: null, valid: false };
215
+ }
216
+
217
+ async function E_Hentai(url) {
218
+ const checkUrl = extractGalleryToken(url);
219
+ if (!checkUrl.valid) throw new Error('URL invalid');
220
+
221
+ const instanceID = generateRandomID();
222
+ const tempDir = path.join(os.tmpdir(), instanceID);
223
+
224
+ try {
225
+ // Ensure tempDir creation
226
+ await fss.mkdir(tempDir, { recursive: true });
227
+
228
+ const { data: metadata } = await axios.post('https://files.xianqiao.wang/https://api.e-hentai.org/api.php', {
229
+ method: "gdata",
230
+ gidlist: [
231
+ [Number(checkUrl.gallery_id), checkUrl.gallery_token]
232
+ ],
233
+ namespace: 1
234
+ }, {
235
+ headers: {
236
+ 'Content-Type': 'application/json'
237
+ }
238
+ });
239
+
240
+ const { data } = await axios.get(url, { headers: {
241
+ '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;]',
242
+ 'Referer': url,
243
+ }});
244
+
245
+ const $ = cheerio.load(data);
246
+
247
+ const imageList = [];
248
+ const tds = $('body > div:nth-child(10) > table > tbody > tr > td');
249
+ const noClassTds = tds.filter((i, td) => !$(td).attr('class')).length;
250
+
251
+ if (noClassTds > 0) {
252
+ // Jika ada td tanpa kelas, ambil gambar untuk setiap halaman
253
+ for (let i = 1; i <= noClassTds; i++) {
254
+ let newUrl = `${url}?p=${i - 1}`;
255
+ console.log(newUrl)
256
+ const response = await axios.get(newUrl, { headers: {
257
+ '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;]',
258
+ 'Referer': url,
259
+ }});
260
+
261
+ const $cada = cheerio.load(response.data);
262
+ let imageLinks = []
263
+ $cada('#gdt > div').each((_, element) => {
264
+ const link = $cada(element).find('div > a').attr('href');
265
+ if (link) {
266
+ imageLinks.push("https://files.xianqiao.wang/" + link);
267
+ }
268
+ });
269
+
270
+ await Promise.all(imageLinks.map(async (link) => {
271
+ try {
272
+ const { data: imgPageData } = await axios.get(link);
273
+ const $imgPage = cheerio.load(imgPageData);
274
+ const imageSrc = $imgPage('#img').attr('src');
275
+ if (imageSrc) {
276
+ imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
277
+ }
278
+ } catch (error) {
279
+ console.error(`Error fetching URL ${link}:`, error.message);
280
+ }
281
+ }));
282
+ }
283
+ } else {
284
+ // Jika tidak ada td tanpa kelas, ambil gambar dari halaman pertama
285
+ let imageLinks = []
286
+ $('#gdt > div').each((_, element) => {
287
+ const link = $(element).find('div > a').attr('href');
288
+ if (link) {
289
+ imageLinks.push("https://files.xianqiao.wang/" + link);
290
+ }
291
+ });
292
+
293
+ await Promise.all(imageLinks.map(async (link) => {
294
+ try {
295
+ const { data: imgPageData } = await axios.get(link);
296
+ const $imgPage = cheerio.load(imgPageData);
297
+ const imageSrc = $imgPage('#img').attr('src');
298
+ if (imageSrc) {
299
+ imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
300
+ }
301
+ } catch (error) {
302
+ console.error(`Error fetching URL ${link}:`, error.message);
303
+ }
304
+ }));
305
+ }
306
+
307
+ console.log(imageList)
308
+ console.log(imageList.length)
309
+
310
+ const imagePaths = await downloadImages(imageList, tempDir, instanceID);
311
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
312
+
313
+ return {
314
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
315
+ path: `/static/${instanceID}.pdf`,
316
+ metadata,
317
+ Pdf_path: pdfPath
318
+ };
319
+ } catch (error) {
320
+ console.error('Error in E_Hentai:', error);
321
+ throw error;
322
+ } finally {
323
+ try {
324
+ await fss.rmdir(tempDir, { recursive: true });
325
+ } catch (cleanupError) {
326
+ console.error('Error cleaning up temp directory:', cleanupError);
327
+ }
328
+ }
329
+ }
330
+
331
+ app.get('/ehentai', async (req, res) => {
332
+ const { url } = req.query;
333
+ if (!url) {
334
+ return res.status(400).send('URL is required');
335
+ }
336
+ try {
337
+ const result = await E_Hentai(url);
338
+ exec(`ls ${os.tmpdir()}`, (err, stdout) => {
339
+ if (err) console.error(err);
340
+ else console.log(stdout);
341
+ });
342
+ res.json(result);
343
+ setTimeout(async () => {
344
+ try {
345
+ await fs.unlink(result.Pdf_path);
346
+ console.log(`File deleted: ${result.Pdf_path}`);
347
+ } catch (err) {
348
+ console.error(`Error deleting file: ${err.message}`);
349
+ }
350
+ }, 330000); // 5 minutes
351
+ } catch (error) {
352
+ res.status(500).send('Error processing request');
353
+ }
354
+ });
355
+
356
+ /********************************************/
357
+
358
+
359
+
360
+ async function komiku_download(url) {
361
+ const instanceID = generateRandomID();
362
+ const tempDir = path.join(os.tmpdir(), instanceID);
363
+ await fss.mkdir(tempDir);
364
+
365
+ const title = url.split('/').filter(part => part).pop();
366
+
367
+ try {
368
+ const response = await axios.get(url, {
369
+ headers: {
370
+ '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;]',
371
+ 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
372
+ 'X-Forwarded-For': generateRandomIP()
373
+ }
374
+ });
375
+ const html = response.data;
376
+ const $ = cheerio.load(html);
377
+ const imgList = [];
378
+
379
+ $('#Baca_Komik img').each((index, element) => {
380
+ const src = $(element).attr('src');
381
+ imgList.push({ path: "https://files.xianqiao.wang/" + src });
382
+ });
383
+
384
+ const imagePaths = await downloadImages(imgList, tempDir, instanceID);
385
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
386
+
387
+ return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title, Pdf_path: pdfPath };
388
+ } catch (error) {
389
+ console.log(error);
390
+ throw error;
391
+ } finally {
392
+ await fss.rmdir(tempDir, { recursive: true });
393
+ }
394
+ }
395
+
396
+ async function downloadImage(image, tempDir, instanceID) {
397
+ try {
398
+ // Fetch the image data
399
+ const response = await axios.get(image.path, {
400
+ responseType: 'arraybuffer',
401
+ headers: {
402
+ '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;]',
403
+ 'Referer': image.path,
404
+ }
405
+ });
406
+ const buffer = Buffer.from(response.data, 'binary');
407
+ const mimesd = await fileTypeFromBuffer(buffer);
408
+ const ext = mimesd ? mimesd.ext : 'jpeg';
409
+ const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`;
410
+ await writeFileAsync(imagePath, buffer);
411
+ return imagePath;
412
+ } catch (error) {
413
+ console.error('Error downloading image:', error);
414
+ throw error;
415
+ }
416
+ }
417
+
418
+ async function downloadImages(imgList, tempDir, instanceID) {
419
+ const imagePaths = [];
420
+ for (const img of imgList) {
421
+ const imagePath = await downloadImage(img, tempDir, instanceID);
422
+ imagePaths.push(imagePath);
423
+ }
424
+ return imagePaths;
425
+ }
426
+
427
+ async function createPDF(imagePaths, instanceID, tempDir) {
428
+ const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
429
+ const doc = new PDFDocument({ autoFirstPage: false });
430
+
431
+ doc.pipe(fs.createWriteStream(pdfPath));
432
+
433
+ for (const imagePath of imagePaths) {
434
+ try {
435
+ // Check if image needs conversion
436
+ const imageExt = path.extname(imagePath).toLowerCase();
437
+ const supportedExtensions = ['.jpg', '.jpeg', '.png'];
438
+ let convertedImagePath = imagePath;
439
+
440
+ if (!fs.existsSync(imagePath) || fs.statSync(imagePath).size === 0) {
441
+ throw new Error(`Invalid or empty image file: ${imagePath}`);
442
+ }
443
+
444
+ if (!supportedExtensions.includes(imageExt)) {
445
+ convertedImagePath = await convertImage(imagePath);
446
+ }
447
+
448
+ const { width, height } = await getImageDimensions(convertedImagePath);
449
+ doc.addPage({ size: [width, height] });
450
+ doc.image(convertedImagePath, 0, 0, { width: width, height: height });
451
+
452
+ // Remove converted images if they were created
453
+ if (convertedImagePath !== imagePath) {
454
+ fs.unlinkSync(convertedImagePath);
455
+ }
456
+ } catch (error) {
457
+ console.error(`Error processing image ${imagePath}:`, error.message);
458
+ }
459
+ }
460
+
461
+ doc.end();
462
+
463
+ return pdfPath;
464
+ }
465
+
466
+ async function getImageDimensions(imagePath) {
467
+ const dimensions = await sizeOf(imagePath);
468
+ return dimensions;
469
+ }
470
+
471
+ async function convertImage(imagePath) {
472
+ return new Promise((resolve, reject) => {
473
+ const outputImagePath = imagePath.replace(/\.\w+$/, '.jpg');
474
+ exec(`convert "${imagePath}" "${outputImagePath}"`, (error, stdout, stderr) => {
475
+ if (error) {
476
+ console.error('ImageMagick Error:', stderr);
477
+ return reject(error);
478
+ }
479
+ resolve(outputImagePath);
480
+ });
481
+ });
482
+ }
483
+
484
+ app.get('/download', async (req, res) => {
485
+ const { url } = req.query;
486
+ if (!url) {
487
+ return res.status(400).send('URL is required');
488
+ }
489
+
490
+ try {
491
+ const result = await komiku_download(url);
492
+ res.json(result);
493
+ setTimeout(() => {
494
+ fs.unlink(result.Pdf_path, (err) => {
495
+ if (err) {
496
+ console.error(`Error deleting file: ${err.message}`);
497
+ } else {
498
+ console.log(`File deleted: ${result.Pdf_path}`);
499
+ }
500
+ });
501
+ }, 330000);
502
+ } catch (error) {
503
+ res.status(500).send('Error processing request');
504
+ }
505
+ });
506
+
507
+ async function nhentai(url) {
508
+ const instanceID = generateRandomID();
509
+ const tempDir = path.join(os.tmpdir(), instanceID);
510
+ await fs.promises.mkdir(tempDir, { recursive: true });
511
+
512
+ try {
513
+ const response = await axios.get(url, {
514
+ headers: {
515
+ 'User-Agent': 'Mozilla/5.0',
516
+ 'Referer': 'https://nhentai.net/'
517
+ }
518
+ });
519
+
520
+ const $ = cheerio.load(response.data);
521
+ const scriptContent = $('script')
522
+ .filter((i, el) => $(el).html().includes('window._gallery = JSON.parse'))
523
+ .html();
524
+
525
+ const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1];
526
+ const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\');
527
+ const jsonData = JSON.parse(decodedString);
528
+
529
+ const imgList = jsonData.images.pages.map((_, index) => ({
530
+ 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"}`
531
+ }));
532
+
533
+ const imagePaths = [];
534
+ for (const img of imgList) {
535
+ const downloadedImagePath = await downloadImageNh(img, tempDir, instanceID);
536
+ imagePaths.push(downloadedImagePath);
537
+ }
538
+
539
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
540
+ console.log(`PDF successfully created: ${pdfPath}`);
541
+ return {
542
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
543
+ path: pdfPath,
544
+ result: jsonData
545
+ };
546
+ } catch (error) {
547
+ console.error(error);
548
+ throw error;
549
+ } finally {
550
+ await fs.promises.rm(tempDir, { recursive: true });
551
+ }
552
+ }
553
+
554
+
555
+ // PERUBAHAN: Gunakan sharp untuk konversi gambar
556
+ async function convertImageV2(inputPath, outputPath) {
557
+ try {
558
+ await sharp(inputPath).toFormat('jpeg').toFile(outputPath);
559
+ console.log(`Converted ${inputPath} to ${outputPath}`);
560
+ return outputPath;
561
+ } catch (error) {
562
+ console.error(`Error converting image: ${error.message}`);
563
+ throw new Error(`Failed to convert image ${inputPath} to JPG.`);
564
+ }
565
+ }
566
+
567
+
568
+ async function convertImageToJPG(inputPath, outputPath) {
569
+ try {
570
+ await execAsync(`ffmpeg -i "${inputPath}" -q:v 1 "${outputPath}"`);
571
+ console.log(`Converted ${inputPath} to ${outputPath}`);
572
+ return outputPath;
573
+ } catch (error) {
574
+ console.error(`Error converting image: ${error.message}`);
575
+ throw new Error(`Failed to convert image ${inputPath} to JPG.`);
576
+ }
577
+ }
578
+
579
+ async function downloadImageNh(image, tempDir, instanceID) {
580
+ const servers = [
581
+ "https://i1.nhentai.net",
582
+ "https://i2.nhentai.net",
583
+ "https://i4.nhentai.net",
584
+ "https://i5.nhentai.net",
585
+ "https://i3.nhentai.net",
586
+ "https://i7.nhentai.net"
587
+ ];
588
+
589
+ for (const server of servers) {
590
+ try {
591
+ const imageUrl = `${server}/galleries/${image.path.split('galleries/')[1]}`;
592
+ console.log(`Downloading image from: ${imageUrl}`);
593
+
594
+ const response = await axios.get(imageUrl, {
595
+ responseType: 'arraybuffer',
596
+ headers: {
597
+ 'User-Agent': 'Mozilla/5.0',
598
+ 'Referer': 'https://nhentai.net/'
599
+ }
600
+ });
601
+
602
+ let imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.webp`;
603
+ await fs.promises.writeFile(imagePath, response.data);
604
+
605
+ const isWebp = path.extname(imagePath).toLowerCase() === '.webp';
606
+ if (isWebp) {
607
+ const convertedPath = imagePath.replace('.webp', '.jpg');
608
+ imagePath = await convertImageToJPG(imagePath, convertedPath);
609
+ fs.unlinkSync(imagePath.replace('.jpg', '.webp')); // Hapus file asli `webp`
610
+ }
611
+
612
+ return imagePath;
613
+ } catch (error) {
614
+ console.error(`Error downloading image from ${server}:`, error.message);
615
+ }
616
+ }
617
+
618
+ throw new Error('Failed to download image from all servers.');
619
+ }
620
+
621
+
622
+ async function downloadImageNhs(imgList, tempDir, instanceID) {
623
+ const imagePaths = [];
624
+ for (const img of imgList) {
625
+ const imagePath = await downloadImageNh(img, tempDir, instanceID);
626
+ imagePaths.push(imagePath);
627
+ }
628
+ return imagePaths;
629
+ }
630
+
631
+ app.get('/nhentai', async (req, res) => {
632
+ const { url } = req.query;
633
+ if (!url) {
634
+ return res.status(400).send('URL is required');
635
+ }
636
+ try {
637
+ const result = await nhentai(url);
638
+ res.json(result);
639
+ setTimeout(() => {
640
+ fs.unlink(result.path, (err) => {
641
+ if (err) {
642
+ console.error(`Error deleting file: ${err.message}`);
643
+ } else {
644
+ console.log(`File deleted: ${result.path}`);
645
+ }
646
+ });
647
+ }, 370000);
648
+ } catch (error) {
649
+ res.status(500).send('Error processing request');
650
+ }
651
+ });
652
+
653
+
654
+ async function downloadFromUrl(url, filePath, biskuit) {
655
+ const writer = fs.createWriteStream(filePath);
656
+
657
+ const response = await axios({
658
+ url,
659
+ method: 'GET',
660
+ responseType: 'stream',
661
+ headers: {
662
+ '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',
663
+ 'Referer': url,
664
+ 'Cookie': biskuit
665
+ }
666
+ });
667
+
668
+ response.data.pipe(writer);
669
+
670
+ return new Promise((resolve, reject) => {
671
+ writer.on('finish', resolve);
672
+ writer.on('error', reject);
673
+ });
674
+ }
675
+
676
+
677
+
678
+ async function Rules34Infonues(url_r34) {
679
+ try {
680
+ const browser = await puppeteer.launch();
681
+ const page = await browser.newPage();
682
+
683
+ await page.setExtraHTTPHeaders({
684
+ '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',
685
+ 'Referer': url_r34
686
+ });
687
+
688
+ await page.goto(url_r34, { referer: url_r34 });
689
+
690
+ const htmlContent = await page.content();
691
+ const $ = cheerio.load(htmlContent);
692
+
693
+ const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() ||
694
+ url_r34.match(/\/video\/\d+\/(.*)\//)?.[1];
695
+
696
+ const infoElements = $("#tab_video_info > div");
697
+ const result = {
698
+ title,
699
+ artist: [],
700
+ uploader: [],
701
+ tags: [],
702
+ download: [],
703
+ category: []
704
+ };
705
+
706
+ if (infoElements.length > 0) {
707
+ const [videoInfo, tags, download] = [
708
+ infoElements.eq(infoElements.length - 3),
709
+ infoElements.eq(infoElements.length - 2),
710
+ infoElements.eq(infoElements.length - 1)
711
+ ];
712
+
713
+ tags.find("div.wrap > a").each((_, element) => {
714
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
715
+ });
716
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
717
+
718
+ download.find("div.wrap > a").each((_, element) => {
719
+ result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
720
+ });
721
+
722
+ videoInfo.find("div.cols > div").each((_, col) => {
723
+ $(col).find("div.col:nth-child(1) > a").each((_, link) => {
724
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
725
+ });
726
+
727
+ $(col).find("div.col:nth-child(2) > a").each((_, link) => {
728
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
729
+ });
730
+
731
+ $(col).find("div.col:nth-child(3) > a").each((_, link) => {
732
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
733
+ });
734
+ });
735
+ }
736
+
737
+ await browser.close();
738
+ return result;
739
+ } catch (error) {
740
+ console.error('Error fetching data:', error);
741
+ throw error; // Lempar ulang error untuk ditangani di level atas
742
+ }
743
+ }
744
+
745
+
746
+
747
+ async function Rules34info(url_r34) {
748
+ try {
749
+ // Mengambil halaman HTML dengan Axios
750
+ const response = await axios.get(url_r34, {
751
+ headers: {
752
+ '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',
753
+ 'Referer': url_r34
754
+ }
755
+ });
756
+
757
+ const htmlContent = response.data;
758
+ const $ = cheerio.load(htmlContent);
759
+
760
+ 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];
761
+
762
+ const infoElements = $("#tab_video_info > div");
763
+ const result = {
764
+ title: title,
765
+ artist: [],
766
+ uploader: [],
767
+ tags: [],
768
+ category: []
769
+ };
770
+
771
+ if (infoElements.length > 0) {
772
+ const tags = infoElements.eq(infoElements.length - 2);
773
+ const videoInfo = infoElements.eq(infoElements.length - 3);
774
+
775
+ if (tags.length > 0) {
776
+ tags.find("div.wrap > a").each((index, element) => {
777
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
778
+ });
779
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
780
+ }
781
+
782
+ if (videoInfo.length > 0) {
783
+ videoInfo.find("div.cols > div").each((index, col) => {
784
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
785
+ categoryLinks.each((index, link) => {
786
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
787
+ });
788
+
789
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
790
+ artistLinks.each((index, link) => {
791
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
792
+ });
793
+
794
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
795
+ uploaderLinks.each((index, link) => {
796
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
797
+ });
798
+ });
799
+ }
800
+ }
801
+
802
+ return result;
803
+ } catch (error) {
804
+ console.error('Error fetching data:', error);
805
+ throw error; // Rethrow error to handle it upstream
806
+ }
807
+ }
808
+
809
+ async function Rules34(url_r34) {
810
+ try {
811
+ const browser = await puppeteer.launch();
812
+ const page = await browser.newPage();
813
+
814
+ await page.setExtraHTTPHeaders({
815
+ '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',
816
+ 'Referer': url_r34
817
+ });
818
+ await page.goto(url_r34, { referer: url_r34 });
819
+
820
+ const htmlContent = await page.content();
821
+ const $ = cheerio.load(htmlContent);
822
+
823
+ 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];
824
+
825
+ const infoElements = $("#tab_video_info > div");
826
+ const result = {
827
+ title: title,
828
+ artist: [],
829
+ uploader: [],
830
+ tags: [],
831
+ download: [],
832
+ category: []
833
+ };
834
+
835
+ if (infoElements.length > 0) {
836
+ const tags = infoElements.eq(infoElements.length - 2);
837
+ const download = infoElements.eq(infoElements.length - 1);
838
+ const videoInfo = infoElements.eq(infoElements.length - 3);
839
+
840
+ if (tags.length > 0) {
841
+ tags.find("div.wrap > a").each((index, element) => {
842
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
843
+ });
844
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
845
+ }
846
+
847
+ if (download.length > 0) {
848
+ download.find("div.wrap > a").each((index, element) => {
849
+ result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
850
+ });
851
+
852
+ // Mendownload dari URL terakhir di array download
853
+ const lastDownloadUrl = result.download[result.download.length - 1].url;
854
+ const downloadPath = path.resolve(os.tmpdir())
855
+ let filenem = `${Date.now()}_file.mp4`
856
+ const filePath = path.join(downloadPath, filenem)
857
+
858
+ const biskuit = await page.cookies();
859
+
860
+
861
+ await downloadFromUrl(lastDownloadUrl, filePath, biskuit);
862
+
863
+ result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result
864
+ result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result
865
+ }
866
+
867
+ if (videoInfo.length > 0) {
868
+ videoInfo.find("div.cols > div").each((index, col) => {
869
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
870
+ categoryLinks.each((index, link) => {
871
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
872
+ });
873
+
874
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
875
+ artistLinks.each((index, link) => {
876
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
877
+ });
878
+
879
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
880
+ uploaderLinks.each((index, link) => {
881
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
882
+ });
883
+ });
884
+ }
885
+ }
886
+
887
+ await browser.close();
888
+ return result;
889
+ } catch (error) {
890
+ console.error('Error fetching data:', error);
891
+ throw error; // Rethrow error to handle it upstream
892
+ }
893
+ }
894
+
895
+
896
+ app.get('/r34', async (req, res) => {
897
+ const { url } = req.query;
898
+ if (!url) {
899
+ return res.status(400).send('URL is required');
900
+ }
901
+ try {
902
+ const result = await Rules34(url);
903
+ res.json(result);
904
+ const filePath = result.downloadPath;
905
+ // Hapus file setelah 8 menit (480000 milidetik)
906
+ setTimeout(() => {
907
+ fs.unlink(filePath, (err) => {
908
+ if (err) {
909
+ console.error(`Error deleting file: ${err.message}`);
910
+ } else {
911
+ console.log(`File deleted: ${filePath}`);
912
+ }
913
+ });
914
+ }, 280000);
915
+ } catch (error) {
916
+ res.status(500).send('Error processing request');
917
+ }
918
+ });
919
+
920
+
921
+ app.get('/r34/download', async (req, res) => {
922
+ const { url, type = 'download' } = req.query;
923
+ if (!url) {
924
+ return res.status(400).send('URL is required');
925
+ }
926
+
927
+ try {
928
+ const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34
929
+ const filePath = result.downloadPath;
930
+
931
+ // Cek apakah file benar-benar ada sebelum mengirim
932
+ if (!fs.existsSync(filePath)) {
933
+ return res.status(404).send('File not found');
934
+ }
935
+
936
+ const fileName = path.basename(filePath);
937
+ const mimeType = 'video/mp4';
938
+
939
+ res.setHeader('Content-Type', mimeType);
940
+
941
+ if (type === 'stream') {
942
+ const range = req.headers.range;
943
+
944
+ if (range) {
945
+ const stat = fs.statSync(filePath);
946
+ const fileSize = stat.size;
947
+
948
+ const parts = range.replace(/bytes=/, "").split("-");
949
+ const start = parseInt(parts[0], 10);
950
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
951
+
952
+ const chunksize = (end - start) + 1;
953
+ const file = fs.createReadStream(filePath, { start, end });
954
+ const head = {
955
+ 'Content-Range': `bytes ${start}-${end}/${fileSize}`,
956
+ 'Accept-Ranges': 'bytes',
957
+ 'Content-Length': chunksize,
958
+ 'Content-Type': mimeType,
959
+ };
960
+
961
+ res.writeHead(206, head);
962
+ file.pipe(res);
963
+ } else {
964
+ res.setHeader('Content-Length', fileSize);
965
+ res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file
966
+ }
967
+ } else if (type === 'buffer') {
968
+ fs.readFile(filePath, (err, data) => {
969
+ if (err) {
970
+ console.error('Gagal membaca file:', err);
971
+ res.status(500).send('Gagal membaca file: \n' + err);
972
+ } else {
973
+ res.setHeader('Content-Length', data.length);
974
+ res.send(data);
975
+ }
976
+ });
977
+ } else { // Default to 'download'
978
+ res.download(filePath, fileName, (err) => {
979
+ if (err) {
980
+ console.error('Gagal mengirim file:', err);
981
+ res.status(500).send('Gagal mengirim file: \n' + err);
982
+ }
983
+ });
984
+ }
985
+ } catch (error) {
986
+ console.error('Error processing request:', error);
987
+ res.status(500).send('Error processing request');
988
+ }
989
+ });
990
+
991
+
992
+ app.get('/r34/info', async (req, res) => {
993
+ const { url } = req.query;
994
+ if (!url) {
995
+ return res.status(400).send('URL is required');
996
+ }
997
+ try {
998
+ const result = await Rules34Infonues(url);
999
+ res.json(result);
1000
+ } catch (error) {
1001
+ res.status(500).send('Error processing request');
1002
+ }
1003
+ });
1004
+
1005
+
1006
+ async function r34Cookie(url) {
1007
+ const browser = await puppeteer.launch({
1008
+ headless: true, // Non-headless untuk debugging
1009
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
1010
+ });
1011
+ const page = await browser.newPage();
1012
+ // Setel header User-Agent dan Referer
1013
+ await page.setExtraHTTPHeaders({
1014
+ 'User-Agent': getRandomUserAgent(),
1015
+ 'Referer': url,
1016
+ 'X-Forwarded-For': generateRandomIP()
1017
+ });
1018
+ await page.goto(url); // Buka URL yang diberikan
1019
+ const cookies = await page.cookies();
1020
+ await browser.close();
1021
+ return { cookies };
1022
+ }
1023
+
1024
+ app.get('/r34cookie', async (req, res) => {
1025
+ const { url } = req.query;
1026
+ if (!url) {
1027
+ return res.status(400).send('URL is required');
1028
+ }
1029
+ try {
1030
+ const result = await r34Cookie(url);
1031
+ res.json(result);
1032
+ } catch (error) {
1033
+ res.status(500).send('Error processing request');
1034
+ }
1035
+ });
1036
+
1037
+ 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';
1038
+
1039
+
1040
+ // Fungsi untuk mendapatkan data dari API Pixiv berdasarkan ID ilustrasi
1041
+ async function pixivGetData(illustId) {
1042
+ const headers = {
1043
+ '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',
1044
+ 'Referer': 'https://www.pixiv.net/',
1045
+ "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`,
1046
+ 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001",
1047
+ 'Cookie': kue
1048
+ };
1049
+
1050
+ try {
1051
+ const response = await axios.get(`https://www.pixiv.net/touch/ajax/illust/details?illust_id=${illustId}&lang=en`, { headers });
1052
+ return response.data;
1053
+ } catch (error) {
1054
+ console.error("Error fetching data from Pixiv:", error);
1055
+ throw error;
1056
+ }
1057
+ }
1058
+
1059
+ // Fungsi untuk mengunduh file zip dari URL dan mengekstraknya ke folder sementara
1060
+ async function downloadAndExtractZipFromPixivData(pixivData) {
1061
+ const pixivId = pixivData.body.illust_details.id;
1062
+ const zipUrl = pixivData.body.illust_details.ugoira_meta.src;
1063
+
1064
+ // Generate nama folder dengan karakter acak
1065
+ const randomFolderName = crypto.randomBytes(8).toString('hex');
1066
+ const outputDirectory = path.join(tmpDir, `${pixivId}_${randomFolderName}`);
1067
+
1068
+ try {
1069
+ const headers = {
1070
+ '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',
1071
+ 'Referer': 'https://www.pixiv.net/',
1072
+ "Sec-Ch-Ua": `"Not-A.Brand";v="99", "Chromium";v="124"`,
1073
+ 'Baggage': "sentry-environment=production,sentry-release=1ab9ad920c28fb6fd4598d3745c828c3e2facd3a,sentry-public_key=e0efdb023498416a827321504f31f009,sentry-trace_id=bc354f2c0c8a461eaab6764025f0b7e1,sentry-sample_rate=0.0001",
1074
+ 'Cookie': kue
1075
+ };
1076
+ const response = await axios.get(zipUrl, { responseType: 'arraybuffer', headers });
1077
+
1078
+ if (!fs.existsSync(outputDirectory)) {
1079
+ fs.mkdirSync(outputDirectory);
1080
+ }
1081
+
1082
+ const zipPath = path.join(outputDirectory, `${pixivId}_ugoira.zip`);
1083
+ fs.writeFileSync(zipPath, response.data);
1084
+
1085
+ const zip = new AdmZip(zipPath);
1086
+ zip.extractAllTo(outputDirectory, true);
1087
+ console.log(`File zip berhasil diekstrak ke ${outputDirectory}`);
1088
+
1089
+ return outputDirectory;
1090
+ } catch (error) {
1091
+ console.error("Error downloading or extracting zip:", error);
1092
+ throw error;
1093
+ }
1094
+ }
1095
+
1096
+
1097
+ // Fungsi untuk membuat video dari file image yang sudah diekstrak
1098
+ async function createVideoFromExtractedImages(pixivData, frameDir) {
1099
+ const pixivId = pixivData.body.illust_details.id;
1100
+ const frames = pixivData.body.illust_details.ugoira_meta.frames;
1101
+
1102
+ const frameListFile = path.join(frameDir, 'frames.txt');
1103
+ const frameListContent = frames
1104
+ .map(frame => {
1105
+ const framePath = path.join(frameDir, frame.file);
1106
+ return `file '${frame.file}'\nduration ${frame.delay / 1000}`;
1107
+ })
1108
+ .join('\n');
1109
+
1110
+ fs.writeFileSync(frameListFile, frameListContent);
1111
+ console.log(`File frame list berhasil disimpan di ${frameListFile}`);
1112
+
1113
+ const outputVideoPath = path.join(frameDir, `${pixivId}.mp4`);
1114
+
1115
+ if (fs.existsSync(frameListFile)) {
1116
+ //await execAsync(`ffmpeg -f concat -safe 0 -i "${frameListFile}" -vsync vfr -pix_fmt yuv420p "${outputVideoPath}"`);
1117
+ 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}"`);
1118
+
1119
+ console.log(`Video berhasil dibuat: ${outputVideoPath}`);
1120
+ return outputVideoPath;
1121
+ } else {
1122
+ throw new Error(`File frames.txt tidak ditemukan di ${frameListFile}`);
1123
+ }
1124
+ }
1125
+
1126
+ // Fungsi untuk menghapus folder setelah delay tertentu
1127
+ function scheduleFolderDeletion(directory) {
1128
+ setTimeout(() => {
1129
+ fs.rmSync(directory, { recursive: true, force: true });
1130
+ console.log(`Folder ${directory} dan isinya telah dihapus.`);
1131
+ }, deleteFilesAfter);
1132
+ }
1133
+
1134
+ // Endpoint untuk memproses permintaan dan mengirimkan URL video
1135
+ app.get("/process-pixiv/:illustId", async (req, res) => {
1136
+ const { illustId } = req.params;
1137
+
1138
+ try {
1139
+ const pixivData = await pixivGetData(illustId);
1140
+ const frameDir = await downloadAndExtractZipFromPixivData(pixivData);
1141
+ const videoPath = await createVideoFromExtractedImages(pixivData, frameDir);
1142
+
1143
+ // Buat URL untuk mengakses file mp4
1144
+ const videoUrl = `https://arashicode-komik.hf.space/static/${path.relative(tmpDir, videoPath)}`;
1145
+
1146
+ // Kirim URL file mp4 dalam format JSON
1147
+ res.json({ url: videoUrl });
1148
+
1149
+ // Jadwalkan penghapusan file setelah 2 menit
1150
+ scheduleFolderDeletion(frameDir);
1151
+ } catch (error) {
1152
+ console.error("Error processing Pixiv illustration:", error);
1153
+ res.status(500).send("Error processing illustration.");
1154
+ }
1155
+ });
1156
+
1157
+
1158
+ async function scrapeHAnime(query) {
1159
+ const baseUrl = "https://animeidhentai.com";
1160
+ const searchUrl = `${baseUrl}/?s=${encodeURIComponent(query)}`;
1161
+ const browser = await puppeteer.launch({
1162
+ headless: true,
1163
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
1164
+ });
1165
+ const page = await browser.newPage();
1166
+ await page.goto(searchUrl, { waitUntil: 'domcontentloaded' });
1167
+
1168
+ try {
1169
+ // Ambil data video
1170
+ const videos = await page.evaluate(() => {
1171
+ return [...document.querySelectorAll("body > main > section > div.anime-list.dg.gt2.gg1.mgt1.a-gtf.v-grid > article")].map(article => {
1172
+ const urlElement = article.querySelector("a");
1173
+ const titleElement = article.querySelector("header > div");
1174
+ const descElement = article.querySelector("div.description.dn > p");
1175
+ const thumbnailElement = article.querySelector("div.anime-tb.pctr.rad1.por > figure > img");
1176
+
1177
+ return {
1178
+ url: urlElement ? urlElement.href : null,
1179
+ title: titleElement ? titleElement.textContent.trim() : null,
1180
+ description: descElement ? descElement.textContent.trim() : null,
1181
+ thumbnail: thumbnailElement ? thumbnailElement.src : null
1182
+ };
1183
+ });
1184
+ });
1185
+
1186
+ // Hitung halaman berikutnya
1187
+ const nextPage = await page.evaluate(() => {
1188
+ const nextButton = document.querySelector("body > main > section > div.pagination-wrapper > a.next.page-numbers.ljoptimizer");
1189
+ if (nextButton) {
1190
+ const currentUrl = window.location.href;
1191
+ const currentPageMatch = currentUrl.match(/page\/(\d+)/);
1192
+ const currentPage = currentPageMatch ? parseInt(currentPageMatch[1], 10) : 1;
1193
+ return currentPage + 1;
1194
+ }
1195
+ return null;
1196
+ });
1197
+ console.log(videos)
1198
+
1199
+ const result = {
1200
+ next: nextPage ? `${baseUrl}/page/${nextPage}/?s=${encodeURIComponent(query)}` : null,
1201
+ videos
1202
+ };
1203
+
1204
+ await browser.close();
1205
+ return result;
1206
+
1207
+ } catch (error) {
1208
+ console.log("Error scraping data:", error);
1209
+ await browser.close();
1210
+ return { next: null, videos: [] };
1211
+ }
1212
+ }
1213
+
1214
+
1215
+ async function scrapeHAnimeDetails(url) {
1216
+ const browser = await puppeteer.launch({
1217
+ headless: true,
1218
+ args: ["--no-sandbox", "--disable-setuid-sandbox"],
1219
+ });
1220
+
1221
+ try {
1222
+ const page = await browser.newPage();
1223
+ await page.setUserAgent(
1224
+ "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;]"
1225
+ );
1226
+
1227
+ // Buka halaman utama
1228
+ await page.goto(url, { waitUntil: "domcontentloaded" });
1229
+
1230
+ // Ambil metadata
1231
+ const result = await page.evaluate(() => {
1232
+ const getText = (selector) => {
1233
+ const element = document.querySelector(selector);
1234
+ return element ? element.textContent.trim() : null;
1235
+ };
1236
+
1237
+ const getGenre = () => {
1238
+ return [...document.querySelectorAll("body > main > article > aside.anime-cn.clb > div.genres.mgt.df.fww.por > a")]
1239
+ .map((genre) => genre.textContent.trim());
1240
+ };
1241
+
1242
+ return {
1243
+ title: getText("body > main > article > aside.anime-cn.clb > header > h1"),
1244
+ tahunRilis: getText("body > main > article > aside.anime-cn.clb > header > div > p > a.mgr.mgb.fwb"),
1245
+ tahunUpload: getText("body > main > article > aside.anime-cn.clb > header > div > p > span:nth-child(9)"),
1246
+ subtitleLang: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(5)"),
1247
+ quality: getText("body > main > article > aside.anime-cn.clb > header > div > p > a:nth-child(3)"),
1248
+ description: getText("body > main > article > aside.anime-cn.clb > div.description.link-co.mgb2"),
1249
+ genre: getGenre(),
1250
+ };
1251
+ });
1252
+
1253
+ //console.log("Metadata:", result);
1254
+
1255
+ // Tunggu iframe muncul
1256
+ await page.waitForSelector(
1257
+ "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe",
1258
+ { timeout: 20000 }
1259
+ );
1260
+
1261
+ // Ambil URL iframe
1262
+ const iframeSrc = await page.evaluate(() => {
1263
+ const iframe = document.querySelector(
1264
+ "body > main > div.player.mgt.mgb2 > div.vdplbx.c-df > aside.vdpl.fg1 > div > iframe"
1265
+ );
1266
+ return iframe ? iframe.src : null;
1267
+ });
1268
+
1269
+ if (!iframeSrc) throw new Error("Iframe tidak ditemukan!");
1270
+
1271
+ console.log("Iframe Source:", iframeSrc);
1272
+
1273
+ // Gunakan API HTML untuk mengambil data iframe
1274
+ const responseA = await axios.get(`https://arashicode-api.hf.space/html?url=${iframeSrc}`);
1275
+ const iframeHTML = responseA.data;
1276
+ result.iframeHTML = iframeHTML;
1277
+
1278
+ // Ambil data-id dari HTML iframe
1279
+ const $ = cheerio.load(iframeHTML);
1280
+ const dataIdElement = $("div.servers > ul > li");
1281
+ const dataId = dataIdElement.length
1282
+ ? "https://nhplayer.com" + dataIdElement.attr("data-id")
1283
+ : null;
1284
+
1285
+ if (dataId) {
1286
+ console.log("Data-ID URL:", dataId);
1287
+
1288
+ // Ambil konten dari data-id
1289
+ const responseB = await axios.get(`https://arashicode-api.hf.space/html?url=${dataId}`);
1290
+ const newPageHTML = responseB.data;
1291
+ console.log("HTML Konten Data-ID:", newPageHTML);
1292
+
1293
+ // Ekstrak URL video langsung dari HTML
1294
+ const videoUrlRegex = /file:\s*"(https?:\/\/[^"]+\.mp4)"/;
1295
+ const match = newPageHTML.match(videoUrlRegex);
1296
+
1297
+ if (match && match[1]) {
1298
+ result.video = match[1];
1299
+ console.log("Video URL:", result.video);
1300
+ } else {
1301
+ console.log("Video URL tidak ditemukan dalam HTML!");
1302
+ }
1303
+ }
1304
+
1305
+
1306
+
1307
+ await browser.close();
1308
+ return result;
1309
+ } catch (error) {
1310
+ console.log("Error scraping details:", error);
1311
+
1312
+ // Tutup browser jika terjadi error
1313
+ await browser.close();
1314
+ return { error: error.message };
1315
+ }
1316
+ }
1317
+
1318
+
1319
+
1320
+
1321
+ app.get('/hanime/search', async (req, res) => {
1322
+ const { query } = req.query;
1323
+ if (!query) {
1324
+ return res.status(400).send('query is required');
1325
+ }
1326
+ try {
1327
+ const result = await scrapeHAnime(query);
1328
+ res.json(result);
1329
+ } catch (error) {
1330
+ res.status(500).send('Error processing request \n\n' + error);
1331
+ }
1332
+ });
1333
+
1334
+ app.get('/hanime/download', async (req, res) => {
1335
+ const { url } = req.query;
1336
+ if (!url) {
1337
+ return res.status(400).send('url is required');
1338
+ }
1339
+ try {
1340
+ const result = await scrapeHAnimeDetails(url);
1341
+ res.json(result);
1342
+ } catch (error) {
1343
+ res.status(500).send('Error processing request \n\n' + error);
1344
+ }
1345
+ });
1346
+
1347
+ function delay(ms) {
1348
+ return new Promise((resolve) => setTimeout(resolve, ms));
1349
+ }
1350
+
1351
+
1352
+
1353
+ // Fungsi untuk ping website
1354
+ async function pingWebsite() {
1355
+ const browser = await puppeteer.launch({
1356
+ headless: true,
1357
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
1358
+ });
1359
+ const page = await browser.newPage();
1360
+ 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;]");
1361
+ await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
1362
+ console.log("Ping");
1363
+ await browser.close();
1364
+ }
1365
+
1366
+ // Ping website setiap 5 jam
1367
+ async function pingEvery5Hours() {
1368
+ await pingWebsite();
1369
+ setInterval(async () => {
1370
+ await pingWebsite();
1371
+ }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
1372
+ }
1373
+
1374
+ // Mulai ping
1375
+ pingEvery5Hours();
1376
+
1377
+ app.listen(PORT, () => {
1378
+ console.log(`Server is running on port ${PORT}`);
1379
+ });