Nexchan commited on
Commit
fa36655
·
verified ·
1 Parent(s): 349c03b

Upload index.js

Browse files
Files changed (1) hide show
  1. index.js +1010 -986
index.js CHANGED
@@ -1,987 +1,1011 @@
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 cheerio from 'cheerio';
8
- import { promisify } from 'util';
9
- import { createRequire } from 'module';
10
- import { fileURLToPath } from 'url';
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
- import puppeteer from "puppeteer"
13
- import sharp from 'sharp';
14
- import { fileTypeFromBuffer } from 'file-type';
15
- const require = createRequire(import.meta.url);
16
- const PORT = process.env.PORT || 7860;
17
- const app = express();
18
- const writeFileAsync = promisify(fs.writeFile);
19
- const fss = fs.promises;
20
- const sizeOf = promisify(require('image-size'));
21
- const { exec } = require('child_process');
22
-
23
- app.use('/static', express.static(os.tmpdir()));
24
-
25
- function getRandomUserAgent() {
26
- const userAgents = [
27
- '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;]',
28
- '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)',
29
- '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;]',
30
- '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',
31
- '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;]',
32
- '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',
33
- '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',
34
- '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;]',
35
- '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;]',
36
- '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;]',
37
- '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',
38
- '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',
39
- '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;]',
40
- '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',
41
- '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',
42
- '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',
43
- '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',
44
- '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',
45
- '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',
46
- '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',
47
- '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',
48
- '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;]',
49
- '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',
50
- '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;]',
51
- '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',
52
- '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',
53
- '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;]',
54
- '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',
55
- '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;]',
56
- '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',
57
- '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;]',
58
- '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',
59
- '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;]',
60
- '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;]'
61
- ];
62
-
63
- const randomIndex = Math.floor(Math.random() * userAgents.length);
64
- return userAgents[randomIndex];
65
- }
66
-
67
- app.get('/puppet', async (req, res) => {
68
- const url = req.query.url;
69
- if (!url) {
70
- return res.status(400).send('URL query parameter is required');
71
- }
72
- try {
73
- const browser = await puppeteer.launch();
74
- /*({
75
- headless: true,
76
- args: ['--no-sandbox', '--disable-setuid-sandbox']
77
- });*/
78
- const page = await browser.newPage();
79
- await page.setUserAgent(
80
- 'Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) ' +
81
- 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 ' +
82
- 'Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]'
83
- );
84
- await page.setExtraHTTPHeaders({
85
- 'Accept-Language': 'en-US,en;q=0.9',
86
- 'Accept-Encoding': 'gzip, deflate, br',
87
- 'Connection': 'keep-alive'
88
- });
89
-
90
- await page.goto(url, {
91
- waitUntil: 'domcontentloaded',
92
- timeout: 60000 // Timeout untuk navigasi
93
- });
94
-
95
- await page.waitForNavigation({
96
- waitUntil: 'networkidle0',
97
- timeout: 60000 // Timeout untuk menunggu navigasi selesai
98
- });
99
-
100
- const htmlContent = await page.content();
101
- await new Promise(resolve => setTimeout(resolve, 15000));
102
- await browser.close();
103
- res.send(htmlContent);
104
- } catch (error) {
105
- console.error('Error fetching HTML:', error);
106
- res.status(500).send('Error fetching HTML content');
107
- }
108
- });
109
-
110
- const generateRandomIP = () => {
111
- const octet = () => Math.floor(Math.random() * 256);
112
- return `${octet()}.${octet()}.${octet()}.${octet()}`;
113
- };
114
-
115
- function generateRandomID(length = 8) {
116
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
117
- let result = '';
118
- for (let i = 0; i < length; i++) {
119
- result += characters.charAt(Math.floor(Math.random() * characters.length));
120
- }
121
- return result;
122
- }
123
-
124
- /*******************************************/
125
- async function toonCubus(url) {
126
- const instanceID = generateRandomID();
127
- const tempDir = path.join(os.tmpdir(), instanceID);
128
- let browser;
129
-
130
- try {
131
- // Ensure tempDir creation
132
- await fss.mkdir(tempDir, { recursive: true });
133
-
134
- // Extract title safely
135
- const title = url.split('/').pop().split('.')[0];
136
-
137
- browser = await puppeteer.launch({
138
- headless: true,
139
- args: ['--no-sandbox', '--disable-setuid-sandbox']
140
- });
141
-
142
- const page = await browser.newPage();
143
- 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;]");
144
- await page.goto(url, { waitUntil: 'networkidle2' });
145
-
146
- const data = await page.evaluate(() => {
147
- const elements = document.querySelectorAll("#Blog1 > div > div.check-box > center > a img");
148
- return Array.from(elements).map(img => ({ path: img.src }));
149
- });
150
-
151
- const imagePaths = await downloadImages(data, tempDir, instanceID);
152
- console.log(imagePaths)
153
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
154
-
155
- return {
156
- url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
157
- path: `/static/${instanceID}.pdf`,
158
- title: title,
159
- Pdf_path: pdfPath
160
- };
161
- } catch (error) {
162
- console.error('Error in toonCubus:', error);
163
- throw error;
164
- } finally {
165
- if (browser) {
166
- await browser.close();
167
- }
168
- try {
169
- await fss.rmdir(tempDir, { recursive: true, force: true });
170
- } catch (cleanupError) {
171
- console.error('Error cleaning up temp directory:', cleanupError);
172
- }
173
- }
174
- }
175
-
176
-
177
- app.get('/tooncubus', async (req, res) => {
178
- const { url } = req.query;
179
- if (!url) {
180
- return res.status(400).send('URL is required');
181
- }
182
- try {
183
- const result = await toonCubus(url);
184
- exec(`ls ${os.tmpdir()}`, (err, stdout) => {
185
- if (err) console.error(err);
186
- else console.log(stdout);
187
- });
188
- res.json(result);
189
- setTimeout(async () => {
190
- try {
191
- await fs.unlink(result.Pdf_path);
192
- console.log(`File deleted: ${result.Pdf_path}`);
193
- } catch (err) {
194
- console.error(`Error deleting file: ${err.message}`);
195
- }
196
- }, 330000); // 5 minutes
197
- } catch (error) {
198
- res.status(500).send('Error processing request');
199
- }
200
- });
201
- /********************************************/
202
-
203
- /*******************************************/
204
- function extractGalleryToken(url) {
205
- const regex = /https:\/\/e-hentai\.org\/g\/(\d+)\/([\w-]+)\/?/;
206
- const match = url.match(regex);
207
- return match
208
- ? { gallery_id: match[1], gallery_token: match[2], valid: true }
209
- : { gallery_id: null, gallery_token: null, valid: false };
210
- }
211
-
212
- async function E_Hentai(url) {
213
- const checkUrl = extractGalleryToken(url);
214
- if (!checkUrl.valid) throw new Error('URL invalid');
215
-
216
- const instanceID = generateRandomID();
217
- const tempDir = path.join(os.tmpdir(), instanceID);
218
-
219
- try {
220
- // Ensure tempDir creation
221
- await fss.mkdir(tempDir, { recursive: true });
222
-
223
- const { data: metadata } = await axios.post('https://files.xianqiao.wang/https://api.e-hentai.org/api.php', {
224
- method: "gdata",
225
- gidlist: [
226
- [Number(checkUrl.gallery_id), checkUrl.gallery_token]
227
- ],
228
- namespace: 1
229
- }, {
230
- headers: {
231
- 'Content-Type': 'application/json'
232
- }
233
- });
234
-
235
- const { data } = await axios.get(url, { headers: {
236
- '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;]',
237
- 'Referer': url,
238
- }});
239
-
240
- const $ = cheerio.load(data);
241
-
242
- const imageList = [];
243
- const tds = $('body > div:nth-child(10) > table > tbody > tr > td');
244
- const noClassTds = tds.filter((i, td) => !$(td).attr('class')).length;
245
-
246
- if (noClassTds > 0) {
247
- // Jika ada td tanpa kelas, ambil gambar untuk setiap halaman
248
- for (let i = 1; i <= noClassTds; i++) {
249
- let newUrl = `${url}?p=${i - 1}`;
250
- console.log(newUrl)
251
- const response = await axios.get(newUrl, { headers: {
252
- '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;]',
253
- 'Referer': url,
254
- }});
255
-
256
- const $cada = cheerio.load(response.data);
257
- let imageLinks = []
258
- $cada('#gdt > div').each((_, element) => {
259
- const link = $cada(element).find('div > a').attr('href');
260
- if (link) {
261
- imageLinks.push("https://files.xianqiao.wang/" + link);
262
- }
263
- });
264
-
265
- await Promise.all(imageLinks.map(async (link) => {
266
- try {
267
- const { data: imgPageData } = await axios.get(link);
268
- const $imgPage = cheerio.load(imgPageData);
269
- const imageSrc = $imgPage('#img').attr('src');
270
- if (imageSrc) {
271
- imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
272
- }
273
- } catch (error) {
274
- console.error(`Error fetching URL ${link}:`, error.message);
275
- }
276
- }));
277
- }
278
- } else {
279
- // Jika tidak ada td tanpa kelas, ambil gambar dari halaman pertama
280
- let imageLinks = []
281
- $('#gdt > div').each((_, element) => {
282
- const link = $(element).find('div > a').attr('href');
283
- if (link) {
284
- imageLinks.push("https://files.xianqiao.wang/" + link);
285
- }
286
- });
287
-
288
- await Promise.all(imageLinks.map(async (link) => {
289
- try {
290
- const { data: imgPageData } = await axios.get(link);
291
- const $imgPage = cheerio.load(imgPageData);
292
- const imageSrc = $imgPage('#img').attr('src');
293
- if (imageSrc) {
294
- imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
295
- }
296
- } catch (error) {
297
- console.error(`Error fetching URL ${link}:`, error.message);
298
- }
299
- }));
300
- }
301
-
302
- console.log(imageList)
303
- console.log(imageList.length)
304
-
305
- const imagePaths = await downloadImages(imageList, tempDir, instanceID);
306
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
307
-
308
- return {
309
- url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
310
- path: `/static/${instanceID}.pdf`,
311
- metadata,
312
- Pdf_path: pdfPath
313
- };
314
- } catch (error) {
315
- console.error('Error in E_Hentai:', error);
316
- throw error;
317
- } finally {
318
- try {
319
- await fss.rmdir(tempDir, { recursive: true });
320
- } catch (cleanupError) {
321
- console.error('Error cleaning up temp directory:', cleanupError);
322
- }
323
- }
324
- }
325
-
326
- app.get('/ehentai', async (req, res) => {
327
- const { url } = req.query;
328
- if (!url) {
329
- return res.status(400).send('URL is required');
330
- }
331
- try {
332
- const result = await E_Hentai(url);
333
- exec(`ls ${os.tmpdir()}`, (err, stdout) => {
334
- if (err) console.error(err);
335
- else console.log(stdout);
336
- });
337
- res.json(result);
338
- setTimeout(async () => {
339
- try {
340
- await fs.unlink(result.Pdf_path);
341
- console.log(`File deleted: ${result.Pdf_path}`);
342
- } catch (err) {
343
- console.error(`Error deleting file: ${err.message}`);
344
- }
345
- }, 330000); // 5 minutes
346
- } catch (error) {
347
- res.status(500).send('Error processing request');
348
- }
349
- });
350
-
351
- /********************************************/
352
-
353
-
354
-
355
- async function komiku_download(url) {
356
- const instanceID = generateRandomID();
357
- const tempDir = path.join(os.tmpdir(), instanceID);
358
- await fss.mkdir(tempDir);
359
-
360
- const title = url.split('/').filter(part => part).pop();
361
-
362
- try {
363
- const response = await axios.get(url, {
364
- headers: {
365
- '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;]',
366
- 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
367
- 'X-Forwarded-For': generateRandomIP()
368
- }
369
- });
370
- const html = response.data;
371
- const $ = cheerio.load(html);
372
- const imgList = [];
373
-
374
- $('#Baca_Komik img').each((index, element) => {
375
- const src = $(element).attr('src');
376
- imgList.push({ path: "https://files.xianqiao.wang/" + src });
377
- });
378
-
379
- const imagePaths = await downloadImages(imgList, tempDir, instanceID);
380
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
381
-
382
- return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title, Pdf_path: pdfPath };
383
- } catch (error) {
384
- console.log(error);
385
- throw error;
386
- } finally {
387
- await fss.rmdir(tempDir, { recursive: true });
388
- }
389
- }
390
-
391
- async function downloadImage(image, tempDir, instanceID) {
392
- try {
393
- // Fetch the image data
394
- const response = await axios.get(image.path, {
395
- responseType: 'arraybuffer',
396
- headers: {
397
- '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;]',
398
- 'Referer': image.path,
399
- }
400
- });
401
- const buffer = Buffer.from(response.data, 'binary');
402
- const mimesd = await fileTypeFromBuffer(buffer);
403
- const ext = mimesd ? mimesd.ext : 'jpeg';
404
- const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`;
405
- await writeFileAsync(imagePath, buffer);
406
- return imagePath;
407
- } catch (error) {
408
- console.error('Error downloading image:', error);
409
- throw error;
410
- }
411
- }
412
-
413
- async function downloadImages(imgList, tempDir, instanceID) {
414
- const imagePaths = [];
415
- for (const img of imgList) {
416
- const imagePath = await downloadImage(img, tempDir, instanceID);
417
- imagePaths.push(imagePath);
418
- }
419
- return imagePaths;
420
- }
421
-
422
- async function createPDF(imagePaths, instanceID, tempDir) {
423
- const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
424
- const doc = new PDFDocument({ autoFirstPage: false });
425
-
426
- doc.pipe(fs.createWriteStream(pdfPath));
427
-
428
- for (const imagePath of imagePaths) {
429
- try {
430
- // Check if image needs conversion
431
- const imageExt = path.extname(imagePath).toLowerCase();
432
- const supportedExtensions = ['.jpg', '.jpeg', '.png'];
433
- let convertedImagePath = imagePath;
434
-
435
- if (!supportedExtensions.includes(imageExt)) {
436
- convertedImagePath = await convertImage(imagePath);
437
- }
438
-
439
- const { width, height } = await getImageDimensions(convertedImagePath);
440
- doc.addPage({ size: [width, height] });
441
- doc.image(convertedImagePath, 0, 0, { width: width, height: height });
442
-
443
- // Remove converted images if they were created
444
- if (convertedImagePath !== imagePath) {
445
- fs.unlinkSync(convertedImagePath);
446
- }
447
- } catch (error) {
448
- console.error(`Error processing image ${imagePath}:`, error.message);
449
- }
450
- }
451
-
452
- doc.end();
453
-
454
- return pdfPath;
455
- }
456
-
457
- async function getImageDimensions(imagePath) {
458
- const dimensions = await sizeOf(imagePath);
459
- return dimensions;
460
- }
461
-
462
- async function convertImage(imagePath) {
463
- return new Promise((resolve, reject) => {
464
- const outputImagePath = imagePath.replace(/\.\w+$/, '.jpg');
465
- exec(`convert "${imagePath}" "${outputImagePath}"`, (error, stdout, stderr) => {
466
- if (error) {
467
- console.error('ImageMagick Error:', stderr);
468
- return reject(error);
469
- }
470
- resolve(outputImagePath);
471
- });
472
- });
473
- }
474
-
475
- app.get('/download', async (req, res) => {
476
- const { url } = req.query;
477
- if (!url) {
478
- return res.status(400).send('URL is required');
479
- }
480
-
481
- try {
482
- const result = await komiku_download(url);
483
- res.json(result);
484
- setTimeout(() => {
485
- fs.unlink(result.Pdf_path, (err) => {
486
- if (err) {
487
- console.error(`Error deleting file: ${err.message}`);
488
- } else {
489
- console.log(`File deleted: ${result.Pdf_path}`);
490
- }
491
- });
492
- }, 330000);
493
- } catch (error) {
494
- res.status(500).send('Error processing request');
495
- }
496
- });
497
-
498
- async function nhentai(url) {
499
- const instanceID = generateRandomID();
500
- const tempDir = `./${instanceID}`;
501
- await fss.mkdir(tempDir);
502
- const title = url.split('g/').filter(part => part).pop();
503
- try {
504
- const response = await axios.get(url, {
505
- headers: {
506
- '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;]',
507
- 'Referer': 'https://nhentai.net/',
508
- 'X-Forwarded-For': generateRandomIP()
509
- }
510
- })
511
- const $ = cheerio.load(response.data);
512
- const scriptContent = $('script').filter((i, el) => {
513
- return $(el).html().includes('window._gallery = JSON.parse');
514
- }).html();
515
-
516
- const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1];
517
- const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\');
518
- const jsonData = JSON.parse(decodedString);
519
- console.log(jsonData)
520
-
521
- const imgList = [];
522
- for (let i = 0; i < jsonData.images.pages.length; i++) {
523
- 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` });
524
- }
525
-
526
- const imagePaths = await downloadImageNhs(imgList, tempDir, instanceID);
527
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
528
-
529
- console.log(`PDF berhasil dibuat: ${pdfPath}`);
530
- return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: pdfPath, result: jsonData };
531
- } catch (error) {
532
- console.log(error);
533
- throw error;
534
- } finally {
535
- await fss.rmdir(tempDir, { recursive: true });
536
- }
537
- }
538
-
539
- async function downloadImageNh(image, tempDir, instanceID) {
540
- const response = await axios.get(image.path, {
541
- responseType: 'arraybuffer',
542
- headers: {
543
- '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;]',
544
- 'Referer': 'https://nhentai.net/'
545
- }
546
- });
547
-
548
- const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`;
549
- await writeFileAsync(imagePath, response.data);
550
-
551
- return imagePath;
552
- }
553
-
554
- async function downloadImageNhs(imgList, tempDir, instanceID) {
555
- const imagePaths = [];
556
- for (const img of imgList) {
557
- const imagePath = await downloadImageNh(img, tempDir, instanceID);
558
- imagePaths.push(imagePath);
559
- }
560
- return imagePaths;
561
- }
562
-
563
- app.get('/nhentai', async (req, res) => {
564
- const { url } = req.query;
565
- if (!url) {
566
- return res.status(400).send('URL is required');
567
- }
568
- try {
569
- const result = await nhentai(url);
570
- res.json(result);
571
- setTimeout(() => {
572
- fs.unlink(result.path, (err) => {
573
- if (err) {
574
- console.error(`Error deleting file: ${err.message}`);
575
- } else {
576
- console.log(`File deleted: ${result.path}`);
577
- }
578
- });
579
- }, 370000);
580
- } catch (error) {
581
- res.status(500).send('Error processing request');
582
- }
583
- });
584
-
585
-
586
- async function downloadFromUrl(url, filePath) {
587
- const writer = fs.createWriteStream(filePath);
588
-
589
- const response = await axios({
590
- url,
591
- method: 'GET',
592
- responseType: 'stream'
593
- });
594
-
595
- response.data.pipe(writer);
596
-
597
- return new Promise((resolve, reject) => {
598
- writer.on('finish', resolve);
599
- writer.on('error', reject);
600
- });
601
- }
602
-
603
-
604
-
605
- async function Rules34Infonues(url_r34) {
606
- try {
607
- const browser = await puppeteer.launch();
608
- const page = await browser.newPage();
609
-
610
- await page.setExtraHTTPHeaders({
611
- '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',
612
- 'Referer': url_r34
613
- });
614
-
615
- await page.goto(url_r34, { referer: url_r34 });
616
-
617
- const htmlContent = await page.content();
618
- const $ = cheerio.load(htmlContent);
619
-
620
- const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() ||
621
- url_r34.match(/\/video\/\d+\/(.*)\//)?.[1];
622
-
623
- const infoElements = $("#tab_video_info > div");
624
- const result = {
625
- title,
626
- artist: [],
627
- uploader: [],
628
- tags: [],
629
- download: [],
630
- category: []
631
- };
632
-
633
- if (infoElements.length > 0) {
634
- const [videoInfo, tags, download] = [
635
- infoElements.eq(infoElements.length - 3),
636
- infoElements.eq(infoElements.length - 2),
637
- infoElements.eq(infoElements.length - 1)
638
- ];
639
-
640
- tags.find("div.wrap > a").each((_, element) => {
641
- result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
642
- });
643
- result.tags.pop(); // Menghapus elemen terakhir dari tags
644
-
645
- download.find("div.wrap > a").each((_, element) => {
646
- result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
647
- });
648
-
649
- videoInfo.find("div.cols > div").each((_, col) => {
650
- $(col).find("div.col:nth-child(1) > a").each((_, link) => {
651
- result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
652
- });
653
-
654
- $(col).find("div.col:nth-child(2) > a").each((_, link) => {
655
- result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
656
- });
657
-
658
- $(col).find("div.col:nth-child(3) > a").each((_, link) => {
659
- result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
660
- });
661
- });
662
- }
663
-
664
- await browser.close();
665
- return result;
666
- } catch (error) {
667
- console.error('Error fetching data:', error);
668
- throw error; // Lempar ulang error untuk ditangani di level atas
669
- }
670
- }
671
-
672
-
673
-
674
- async function Rules34info(url_r34) {
675
- try {
676
- // Mengambil halaman HTML dengan Axios
677
- const response = await axios.get(url_r34, {
678
- headers: {
679
- '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',
680
- 'Referer': url_r34
681
- }
682
- });
683
-
684
- const htmlContent = response.data;
685
- const $ = cheerio.load(htmlContent);
686
-
687
- 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];
688
-
689
- const infoElements = $("#tab_video_info > div");
690
- const result = {
691
- title: title,
692
- artist: [],
693
- uploader: [],
694
- tags: [],
695
- category: []
696
- };
697
-
698
- if (infoElements.length > 0) {
699
- const tags = infoElements.eq(infoElements.length - 2);
700
- const videoInfo = infoElements.eq(infoElements.length - 3);
701
-
702
- if (tags.length > 0) {
703
- tags.find("div.wrap > a").each((index, element) => {
704
- result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
705
- });
706
- result.tags.pop(); // Menghapus elemen terakhir dari tags
707
- }
708
-
709
- if (videoInfo.length > 0) {
710
- videoInfo.find("div.cols > div").each((index, col) => {
711
- const categoryLinks = $(col).find("div.col:nth-child(1) > a");
712
- categoryLinks.each((index, link) => {
713
- result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
714
- });
715
-
716
- const artistLinks = $(col).find("div.col:nth-child(2) > a");
717
- artistLinks.each((index, link) => {
718
- result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
719
- });
720
-
721
- const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
722
- uploaderLinks.each((index, link) => {
723
- result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
724
- });
725
- });
726
- }
727
- }
728
-
729
- return result;
730
- } catch (error) {
731
- console.error('Error fetching data:', error);
732
- throw error; // Rethrow error to handle it upstream
733
- }
734
- }
735
-
736
- async function Rules34(url_r34) {
737
- try {
738
- const browser = await puppeteer.launch();
739
- const page = await browser.newPage();
740
-
741
- await page.setExtraHTTPHeaders({
742
- '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',
743
- 'Referer': url_r34
744
- });
745
- await page.goto(url_r34, { referer: url_r34 });
746
-
747
- const htmlContent = await page.content();
748
- const $ = cheerio.load(htmlContent);
749
-
750
- 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];
751
-
752
- const infoElements = $("#tab_video_info > div");
753
- const result = {
754
- title: title,
755
- artist: [],
756
- uploader: [],
757
- tags: [],
758
- download: [],
759
- category: []
760
- };
761
-
762
- if (infoElements.length > 0) {
763
- const tags = infoElements.eq(infoElements.length - 2);
764
- const download = infoElements.eq(infoElements.length - 1);
765
- const videoInfo = infoElements.eq(infoElements.length - 3);
766
-
767
- if (tags.length > 0) {
768
- tags.find("div.wrap > a").each((index, element) => {
769
- result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
770
- });
771
- result.tags.pop(); // Menghapus elemen terakhir dari tags
772
- }
773
-
774
- if (download.length > 0) {
775
- download.find("div.wrap > a").each((index, element) => {
776
- result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
777
- });
778
-
779
- // Mendownload dari URL terakhir di array download
780
- const lastDownloadUrl = result.download[result.download.length - 1].url;
781
- const downloadPath = path.resolve(os.tmpdir())
782
- let filenem = `${Date.now()}_file.mp4`
783
- const filePath = path.join(downloadPath, filenem)
784
-
785
- await downloadFromUrl(lastDownloadUrl, filePath);
786
-
787
- result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result
788
- result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result
789
- }
790
-
791
- if (videoInfo.length > 0) {
792
- videoInfo.find("div.cols > div").each((index, col) => {
793
- const categoryLinks = $(col).find("div.col:nth-child(1) > a");
794
- categoryLinks.each((index, link) => {
795
- result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
796
- });
797
-
798
- const artistLinks = $(col).find("div.col:nth-child(2) > a");
799
- artistLinks.each((index, link) => {
800
- result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
801
- });
802
-
803
- const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
804
- uploaderLinks.each((index, link) => {
805
- result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
806
- });
807
- });
808
- }
809
- }
810
-
811
- await browser.close();
812
- return result;
813
- } catch (error) {
814
- console.error('Error fetching data:', error);
815
- throw error; // Rethrow error to handle it upstream
816
- }
817
- }
818
-
819
-
820
- app.get('/r34', async (req, res) => {
821
- const { url } = req.query;
822
- if (!url) {
823
- return res.status(400).send('URL is required');
824
- }
825
- try {
826
- const result = await Rules34(url);
827
- res.json(result);
828
- const filePath = result.downloadPath;
829
- // Hapus file setelah 8 menit (480000 milidetik)
830
- setTimeout(() => {
831
- fs.unlink(filePath, (err) => {
832
- if (err) {
833
- console.error(`Error deleting file: ${err.message}`);
834
- } else {
835
- console.log(`File deleted: ${filePath}`);
836
- }
837
- });
838
- }, 280000);
839
- } catch (error) {
840
- res.status(500).send('Error processing request');
841
- }
842
- });
843
-
844
-
845
- app.get('/r34/download', async (req, res) => {
846
- const { url, type = 'download' } = req.query;
847
- if (!url) {
848
- return res.status(400).send('URL is required');
849
- }
850
-
851
- try {
852
- const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34
853
- const filePath = result.downloadPath;
854
-
855
- // Cek apakah file benar-benar ada sebelum mengirim
856
- if (!fs.existsSync(filePath)) {
857
- return res.status(404).send('File not found');
858
- }
859
-
860
- const fileName = path.basename(filePath);
861
- const mimeType = 'video/mp4';
862
-
863
- res.setHeader('Content-Type', mimeType);
864
-
865
- if (type === 'stream') {
866
- const range = req.headers.range;
867
-
868
- if (range) {
869
- const stat = fs.statSync(filePath);
870
- const fileSize = stat.size;
871
-
872
- const parts = range.replace(/bytes=/, "").split("-");
873
- const start = parseInt(parts[0], 10);
874
- const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
875
-
876
- const chunksize = (end - start) + 1;
877
- const file = fs.createReadStream(filePath, { start, end });
878
- const head = {
879
- 'Content-Range': `bytes ${start}-${end}/${fileSize}`,
880
- 'Accept-Ranges': 'bytes',
881
- 'Content-Length': chunksize,
882
- 'Content-Type': mimeType,
883
- };
884
-
885
- res.writeHead(206, head);
886
- file.pipe(res);
887
- } else {
888
- res.setHeader('Content-Length', fileSize);
889
- res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file
890
- }
891
- } else if (type === 'buffer') {
892
- fs.readFile(filePath, (err, data) => {
893
- if (err) {
894
- console.error('Gagal membaca file:', err);
895
- res.status(500).send('Gagal membaca file: \n' + err);
896
- } else {
897
- res.setHeader('Content-Length', data.length);
898
- res.send(data);
899
- }
900
- });
901
- } else { // Default to 'download'
902
- res.download(filePath, fileName, (err) => {
903
- if (err) {
904
- console.error('Gagal mengirim file:', err);
905
- res.status(500).send('Gagal mengirim file: \n' + err);
906
- }
907
- });
908
- }
909
- } catch (error) {
910
- console.error('Error processing request:', error);
911
- res.status(500).send('Error processing request');
912
- }
913
- });
914
-
915
-
916
- app.get('/r34/info', async (req, res) => {
917
- const { url } = req.query;
918
- if (!url) {
919
- return res.status(400).send('URL is required');
920
- }
921
- try {
922
- const result = await Rules34Infonues(url);
923
- res.json(result);
924
- } catch (error) {
925
- res.status(500).send('Error processing request');
926
- }
927
- });
928
-
929
-
930
- async function r34Cookie(url) {
931
- const browser = await puppeteer.launch({
932
- headless: true, // Non-headless untuk debugging
933
- args: ['--no-sandbox', '--disable-setuid-sandbox']
934
- });
935
- const page = await browser.newPage();
936
- // Setel header User-Agent dan Referer
937
- await page.setExtraHTTPHeaders({
938
- 'User-Agent': getRandomUserAgent(),
939
- 'Referer': url,
940
- 'X-Forwarded-For': generateRandomIP()
941
- });
942
- await page.goto(url); // Buka URL yang diberikan
943
- const cookies = await page.cookies();
944
- await browser.close();
945
- return { cookies };
946
- }
947
-
948
- app.get('/r34cookie', async (req, res) => {
949
- const { url } = req.query;
950
- if (!url) {
951
- return res.status(400).send('URL is required');
952
- }
953
- try {
954
- const result = await r34Cookie(url);
955
- res.json(result);
956
- } catch (error) {
957
- res.status(500).send('Error processing request');
958
- }
959
- });
960
-
961
- // Fungsi untuk ping website
962
- async function pingWebsite() {
963
- const browser = await puppeteer.launch({
964
- headless: true,
965
- args: ['--no-sandbox', '--disable-setuid-sandbox']
966
- });
967
- const page = await browser.newPage();
968
- 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;]");
969
- await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
970
- console.log("Ping");
971
- await browser.close();
972
- }
973
-
974
- // Ping website setiap 5 jam
975
- async function pingEvery5Hours() {
976
- await pingWebsite();
977
- setInterval(async () => {
978
- await pingWebsite();
979
- }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
980
- }
981
-
982
- // Mulai ping
983
- pingEvery5Hours();
984
-
985
- app.listen(PORT, () => {
986
- console.log(`Server is running on port ${PORT}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
987
  });
 
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 cheerio from 'cheerio';
8
+ import { promisify } from 'util';
9
+ import { createRequire } from 'module';
10
+ import { fileURLToPath } from 'url';
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ import puppeteer from "puppeteer"
13
+ import sharp from 'sharp';
14
+ import { fileTypeFromBuffer } from 'file-type';
15
+ const require = createRequire(import.meta.url);
16
+ const PORT = process.env.PORT || 7860;
17
+ const app = express();
18
+ const writeFileAsync = promisify(fs.writeFile);
19
+ const fss = fs.promises;
20
+ const sizeOf = promisify(require('image-size'));
21
+ const { exec } = require('child_process');
22
+
23
+ app.use('/static', express.static(os.tmpdir()));
24
+
25
+ function getRandomUserAgent() {
26
+ const userAgents = [
27
+ '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;]',
28
+ '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)',
29
+ '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;]',
30
+ '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',
31
+ '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;]',
32
+ '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',
33
+ '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',
34
+ '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;]',
35
+ '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;]',
36
+ '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;]',
37
+ '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',
38
+ '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',
39
+ '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;]',
40
+ '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',
41
+ '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',
42
+ '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',
43
+ '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',
44
+ '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',
45
+ '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',
46
+ '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',
47
+ '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',
48
+ '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;]',
49
+ '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',
50
+ '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;]',
51
+ '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',
52
+ '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',
53
+ '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;]',
54
+ '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',
55
+ '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;]',
56
+ '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',
57
+ '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;]',
58
+ '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',
59
+ '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;]',
60
+ '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;]'
61
+ ];
62
+
63
+ const randomIndex = Math.floor(Math.random() * userAgents.length);
64
+ return userAgents[randomIndex];
65
+ }
66
+
67
+ app.get('/puppet', async (req, res) => {
68
+ const url = req.query.url;
69
+ if (!url) {
70
+ return res.status(400).send('URL query parameter is required');
71
+ }
72
+ try {
73
+ const browser = await puppeteer.launch();
74
+ /*({
75
+ headless: true,
76
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
77
+ });*/
78
+ const page = await browser.newPage();
79
+ await page.setUserAgent(
80
+ 'Mozilla/5.0 (Linux; Android 10; SM-G965U Build/QP1A.190711.020; wv) ' +
81
+ 'AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/114.0.5735.141 ' +
82
+ 'Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/420.0.0.32.61;]'
83
+ );
84
+ await page.setExtraHTTPHeaders({
85
+ 'Accept-Language': 'en-US,en;q=0.9',
86
+ 'Accept-Encoding': 'gzip, deflate, br',
87
+ 'Connection': 'keep-alive'
88
+ });
89
+
90
+ await page.goto(url, {
91
+ waitUntil: 'domcontentloaded',
92
+ timeout: 60000 // Timeout untuk navigasi
93
+ });
94
+
95
+ await page.waitForNavigation({
96
+ waitUntil: 'networkidle0',
97
+ timeout: 60000 // Timeout untuk menunggu navigasi selesai
98
+ });
99
+
100
+ const htmlContent = await page.content();
101
+ await new Promise(resolve => setTimeout(resolve, 15000));
102
+ await browser.close();
103
+ res.send(htmlContent);
104
+ } catch (error) {
105
+ console.error('Error fetching HTML:', error);
106
+ res.status(500).send('Error fetching HTML content');
107
+ }
108
+ });
109
+
110
+ const generateRandomIP = () => {
111
+ const octet = () => Math.floor(Math.random() * 256);
112
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
113
+ };
114
+
115
+ function generateRandomID(length = 8) {
116
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
117
+ let result = '';
118
+ for (let i = 0; i < length; i++) {
119
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
120
+ }
121
+ return result;
122
+ }
123
+
124
+ /*******************************************/
125
+ async function toonCubus(url) {
126
+ const instanceID = generateRandomID();
127
+ const tempDir = path.join(os.tmpdir(), instanceID);
128
+ let browser;
129
+
130
+ try {
131
+ // Ensure tempDir creation
132
+ await fss.mkdir(tempDir, { recursive: true });
133
+
134
+ // Extract title safely
135
+ const title = url.split('/').pop().split('.')[0];
136
+
137
+ browser = await puppeteer.launch({
138
+ headless: true,
139
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
140
+ });
141
+
142
+ const page = await browser.newPage();
143
+ 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;]");
144
+ await page.goto(url, { waitUntil: 'networkidle2' });
145
+
146
+ const data = await page.evaluate(() => {
147
+ const elements = document.querySelectorAll("#Blog1 > div > div.check-box > center > a img");
148
+ return Array.from(elements).map(img => ({ path: img.src }));
149
+ });
150
+
151
+ const imagePaths = await downloadImages(data, tempDir, instanceID);
152
+ console.log(imagePaths)
153
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
154
+
155
+ return {
156
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
157
+ path: `/static/${instanceID}.pdf`,
158
+ title: title,
159
+ Pdf_path: pdfPath
160
+ };
161
+ } catch (error) {
162
+ console.error('Error in toonCubus:', error);
163
+ throw error;
164
+ } finally {
165
+ if (browser) {
166
+ await browser.close();
167
+ }
168
+ try {
169
+ await fss.rmdir(tempDir, { recursive: true, force: true });
170
+ } catch (cleanupError) {
171
+ console.error('Error cleaning up temp directory:', cleanupError);
172
+ }
173
+ }
174
+ }
175
+
176
+
177
+ app.get('/tooncubus', async (req, res) => {
178
+ const { url } = req.query;
179
+ if (!url) {
180
+ return res.status(400).send('URL is required');
181
+ }
182
+ try {
183
+ const result = await toonCubus(url);
184
+ exec(`ls ${os.tmpdir()}`, (err, stdout) => {
185
+ if (err) console.error(err);
186
+ else console.log(stdout);
187
+ });
188
+ res.json(result);
189
+ setTimeout(async () => {
190
+ try {
191
+ await fs.unlink(result.Pdf_path);
192
+ console.log(`File deleted: ${result.Pdf_path}`);
193
+ } catch (err) {
194
+ console.error(`Error deleting file: ${err.message}`);
195
+ }
196
+ }, 330000); // 5 minutes
197
+ } catch (error) {
198
+ res.status(500).send('Error processing request');
199
+ }
200
+ });
201
+ /********************************************/
202
+
203
+ /*******************************************/
204
+ function extractGalleryToken(url) {
205
+ const regex = /https:\/\/e-hentai\.org\/g\/(\d+)\/([\w-]+)\/?/;
206
+ const match = url.match(regex);
207
+ return match
208
+ ? { gallery_id: match[1], gallery_token: match[2], valid: true }
209
+ : { gallery_id: null, gallery_token: null, valid: false };
210
+ }
211
+
212
+ async function E_Hentai(url) {
213
+ const checkUrl = extractGalleryToken(url);
214
+ if (!checkUrl.valid) throw new Error('URL invalid');
215
+
216
+ const instanceID = generateRandomID();
217
+ const tempDir = path.join(os.tmpdir(), instanceID);
218
+
219
+ try {
220
+ // Ensure tempDir creation
221
+ await fss.mkdir(tempDir, { recursive: true });
222
+
223
+ const { data: metadata } = await axios.post('https://files.xianqiao.wang/https://api.e-hentai.org/api.php', {
224
+ method: "gdata",
225
+ gidlist: [
226
+ [Number(checkUrl.gallery_id), checkUrl.gallery_token]
227
+ ],
228
+ namespace: 1
229
+ }, {
230
+ headers: {
231
+ 'Content-Type': 'application/json'
232
+ }
233
+ });
234
+
235
+ const { data } = await axios.get(url, { headers: {
236
+ '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;]',
237
+ 'Referer': url,
238
+ }});
239
+
240
+ const $ = cheerio.load(data);
241
+
242
+ const imageList = [];
243
+ const tds = $('body > div:nth-child(10) > table > tbody > tr > td');
244
+ const noClassTds = tds.filter((i, td) => !$(td).attr('class')).length;
245
+
246
+ if (noClassTds > 0) {
247
+ // Jika ada td tanpa kelas, ambil gambar untuk setiap halaman
248
+ for (let i = 1; i <= noClassTds; i++) {
249
+ let newUrl = `${url}?p=${i - 1}`;
250
+ console.log(newUrl)
251
+ const response = await axios.get(newUrl, { headers: {
252
+ '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;]',
253
+ 'Referer': url,
254
+ }});
255
+
256
+ const $cada = cheerio.load(response.data);
257
+ let imageLinks = []
258
+ $cada('#gdt > div').each((_, element) => {
259
+ const link = $cada(element).find('div > a').attr('href');
260
+ if (link) {
261
+ imageLinks.push("https://files.xianqiao.wang/" + link);
262
+ }
263
+ });
264
+
265
+ await Promise.all(imageLinks.map(async (link) => {
266
+ try {
267
+ const { data: imgPageData } = await axios.get(link);
268
+ const $imgPage = cheerio.load(imgPageData);
269
+ const imageSrc = $imgPage('#img').attr('src');
270
+ if (imageSrc) {
271
+ imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
272
+ }
273
+ } catch (error) {
274
+ console.error(`Error fetching URL ${link}:`, error.message);
275
+ }
276
+ }));
277
+ }
278
+ } else {
279
+ // Jika tidak ada td tanpa kelas, ambil gambar dari halaman pertama
280
+ let imageLinks = []
281
+ $('#gdt > div').each((_, element) => {
282
+ const link = $(element).find('div > a').attr('href');
283
+ if (link) {
284
+ imageLinks.push("https://files.xianqiao.wang/" + link);
285
+ }
286
+ });
287
+
288
+ await Promise.all(imageLinks.map(async (link) => {
289
+ try {
290
+ const { data: imgPageData } = await axios.get(link);
291
+ const $imgPage = cheerio.load(imgPageData);
292
+ const imageSrc = $imgPage('#img').attr('src');
293
+ if (imageSrc) {
294
+ imageList.push({ path: "https://files.xianqiao.wang/" + imageSrc });
295
+ }
296
+ } catch (error) {
297
+ console.error(`Error fetching URL ${link}:`, error.message);
298
+ }
299
+ }));
300
+ }
301
+
302
+ console.log(imageList)
303
+ console.log(imageList.length)
304
+
305
+ const imagePaths = await downloadImages(imageList, tempDir, instanceID);
306
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
307
+
308
+ return {
309
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
310
+ path: `/static/${instanceID}.pdf`,
311
+ metadata,
312
+ Pdf_path: pdfPath
313
+ };
314
+ } catch (error) {
315
+ console.error('Error in E_Hentai:', error);
316
+ throw error;
317
+ } finally {
318
+ try {
319
+ await fss.rmdir(tempDir, { recursive: true });
320
+ } catch (cleanupError) {
321
+ console.error('Error cleaning up temp directory:', cleanupError);
322
+ }
323
+ }
324
+ }
325
+
326
+ app.get('/ehentai', async (req, res) => {
327
+ const { url } = req.query;
328
+ if (!url) {
329
+ return res.status(400).send('URL is required');
330
+ }
331
+ try {
332
+ const result = await E_Hentai(url);
333
+ exec(`ls ${os.tmpdir()}`, (err, stdout) => {
334
+ if (err) console.error(err);
335
+ else console.log(stdout);
336
+ });
337
+ res.json(result);
338
+ setTimeout(async () => {
339
+ try {
340
+ await fs.unlink(result.Pdf_path);
341
+ console.log(`File deleted: ${result.Pdf_path}`);
342
+ } catch (err) {
343
+ console.error(`Error deleting file: ${err.message}`);
344
+ }
345
+ }, 330000); // 5 minutes
346
+ } catch (error) {
347
+ res.status(500).send('Error processing request');
348
+ }
349
+ });
350
+
351
+ /********************************************/
352
+
353
+
354
+
355
+ async function komiku_download(url) {
356
+ const instanceID = generateRandomID();
357
+ const tempDir = path.join(os.tmpdir(), instanceID);
358
+ await fss.mkdir(tempDir);
359
+
360
+ const title = url.split('/').filter(part => part).pop();
361
+
362
+ try {
363
+ const response = await axios.get(url, {
364
+ headers: {
365
+ '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;]',
366
+ 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
367
+ 'X-Forwarded-For': generateRandomIP()
368
+ }
369
+ });
370
+ const html = response.data;
371
+ const $ = cheerio.load(html);
372
+ const imgList = [];
373
+
374
+ $('#Baca_Komik img').each((index, element) => {
375
+ const src = $(element).attr('src');
376
+ imgList.push({ path: "https://files.xianqiao.wang/" + src });
377
+ });
378
+
379
+ const imagePaths = await downloadImages(imgList, tempDir, instanceID);
380
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
381
+
382
+ return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title, Pdf_path: pdfPath };
383
+ } catch (error) {
384
+ console.log(error);
385
+ throw error;
386
+ } finally {
387
+ await fss.rmdir(tempDir, { recursive: true });
388
+ }
389
+ }
390
+
391
+ async function downloadImage(image, tempDir, instanceID) {
392
+ try {
393
+ // Fetch the image data
394
+ const response = await axios.get(image.path, {
395
+ responseType: 'arraybuffer',
396
+ headers: {
397
+ '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;]',
398
+ 'Referer': image.path,
399
+ }
400
+ });
401
+ const buffer = Buffer.from(response.data, 'binary');
402
+ const mimesd = await fileTypeFromBuffer(buffer);
403
+ const ext = mimesd ? mimesd.ext : 'jpeg';
404
+ const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.${ext}`;
405
+ await writeFileAsync(imagePath, buffer);
406
+ return imagePath;
407
+ } catch (error) {
408
+ console.error('Error downloading image:', error);
409
+ throw error;
410
+ }
411
+ }
412
+
413
+ async function downloadImages(imgList, tempDir, instanceID) {
414
+ const imagePaths = [];
415
+ for (const img of imgList) {
416
+ const imagePath = await downloadImage(img, tempDir, instanceID);
417
+ imagePaths.push(imagePath);
418
+ }
419
+ return imagePaths;
420
+ }
421
+
422
+ async function createPDF(imagePaths, instanceID, tempDir) {
423
+ const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
424
+ const doc = new PDFDocument({ autoFirstPage: false });
425
+
426
+ doc.pipe(fs.createWriteStream(pdfPath));
427
+
428
+ for (const imagePath of imagePaths) {
429
+ try {
430
+ // Check if image needs conversion
431
+ const imageExt = path.extname(imagePath).toLowerCase();
432
+ const supportedExtensions = ['.jpg', '.jpeg', '.png'];
433
+ let convertedImagePath = imagePath;
434
+
435
+ if (!supportedExtensions.includes(imageExt)) {
436
+ convertedImagePath = await convertImage(imagePath);
437
+ }
438
+
439
+ const { width, height } = await getImageDimensions(convertedImagePath);
440
+ doc.addPage({ size: [width, height] });
441
+ doc.image(convertedImagePath, 0, 0, { width: width, height: height });
442
+
443
+ // Remove converted images if they were created
444
+ if (convertedImagePath !== imagePath) {
445
+ fs.unlinkSync(convertedImagePath);
446
+ }
447
+ } catch (error) {
448
+ console.error(`Error processing image ${imagePath}:`, error.message);
449
+ }
450
+ }
451
+
452
+ doc.end();
453
+
454
+ return pdfPath;
455
+ }
456
+
457
+ async function getImageDimensions(imagePath) {
458
+ const dimensions = await sizeOf(imagePath);
459
+ return dimensions;
460
+ }
461
+
462
+ async function convertImage(imagePath) {
463
+ return new Promise((resolve, reject) => {
464
+ const outputImagePath = imagePath.replace(/\.\w+$/, '.jpg');
465
+ exec(`convert "${imagePath}" "${outputImagePath}"`, (error, stdout, stderr) => {
466
+ if (error) {
467
+ console.error('ImageMagick Error:', stderr);
468
+ return reject(error);
469
+ }
470
+ resolve(outputImagePath);
471
+ });
472
+ });
473
+ }
474
+
475
+ app.get('/download', async (req, res) => {
476
+ const { url } = req.query;
477
+ if (!url) {
478
+ return res.status(400).send('URL is required');
479
+ }
480
+
481
+ try {
482
+ const result = await komiku_download(url);
483
+ res.json(result);
484
+ setTimeout(() => {
485
+ fs.unlink(result.Pdf_path, (err) => {
486
+ if (err) {
487
+ console.error(`Error deleting file: ${err.message}`);
488
+ } else {
489
+ console.log(`File deleted: ${result.Pdf_path}`);
490
+ }
491
+ });
492
+ }, 330000);
493
+ } catch (error) {
494
+ res.status(500).send('Error processing request');
495
+ }
496
+ });
497
+
498
+ async function nhentai(url) {
499
+ const instanceID = generateRandomID();
500
+ const tempDir = `./${instanceID}`;
501
+
502
+ await fss.mkdir(tempDir); // Membuat direktori sementara untuk menyimpan file sementara
503
+ const title = url.split('g/').filter(part => part).pop(); // Mendapatkan ID galeri dari URL
504
+
505
+ try {
506
+ const response = await axios.get(url, {
507
+ headers: {
508
+ '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;]',
509
+ 'Referer': 'https://nhentai.net/',
510
+ 'X-Forwarded-For': generateRandomIP()
511
+ }
512
+ });
513
+
514
+ const $ = cheerio.load(response.data);
515
+ const scriptContent = $('script').filter((i, el) =>
516
+ $(el).html().includes('window._gallery = JSON.parse')
517
+ ).html();
518
+
519
+ const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1];
520
+ const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\');
521
+ const jsonData = JSON.parse(decodedString);
522
+ console.log(jsonData);
523
+
524
+ const imgList = jsonData.images.pages.map((_, index) => ({
525
+ path: `https://i5.nhentai.net/galleries/${jsonData.media_id}/${index + 1}.jpg&f=1&nofb=1`
526
+ }));
527
+
528
+ const imagePaths = await downloadImageNhs(imgList, tempDir, instanceID);
529
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
530
+
531
+ console.log(`PDF berhasil dibuat: ${pdfPath}`);
532
+ return {
533
+ url: `https://arashicode-komik.hf.space/static/${instanceID}.pdf`,
534
+ path: pdfPath,
535
+ result: jsonData
536
+ };
537
+ } catch (error) {
538
+ console.log(error);
539
+ throw error; // Menghentikan eksekusi jika terjadi error
540
+ } finally {
541
+ await fss.rmdir(tempDir, { recursive: true }); // Menghapus direktori sementara
542
+ }
543
+ }
544
+
545
+ async function downloadImageNh(image, tempDir, instanceID) {
546
+ const servers = [
547
+ "https://i5.nhentai.net",
548
+ "https://i3.nhentai.net",
549
+ "https://i7.nhentai.net"
550
+ ];
551
+
552
+ let lastError = null; // Menyimpan error terakhir
553
+
554
+ for (const server of servers) {
555
+ try {
556
+ const response = await axios.get(`https://external-content.duckduckgo.com/iu/?u=${server}/galleries/${image.path.split('galleries/')[1]}`, {
557
+ responseType: 'arraybuffer',
558
+ headers: {
559
+ '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;]',
560
+ 'Referer': 'https://nhentai.net/'
561
+ }
562
+ });
563
+
564
+ const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`;
565
+ await writeFileAsync(imagePath, response.data);
566
+
567
+ return imagePath; // Mengembalikan path gambar yang berhasil diunduh
568
+ } catch (error) {
569
+ console.log(`Error with server ${server}:`, error.message);
570
+ lastError = error; // Menyimpan error jika terjadi
571
+ }
572
+ }
573
+
574
+ throw new Error(`Failed to download image after trying all servers. Last error: ${lastError.message}`);
575
+ }
576
+
577
+
578
+ async function downloadImageNhs(imgList, tempDir, instanceID) {
579
+ const imagePaths = [];
580
+ for (const img of imgList) {
581
+ const imagePath = await downloadImageNh(img, tempDir, instanceID);
582
+ imagePaths.push(imagePath);
583
+ }
584
+ return imagePaths;
585
+ }
586
+
587
+ app.get('/nhentai', async (req, res) => {
588
+ const { url } = req.query;
589
+ if (!url) {
590
+ return res.status(400).send('URL is required');
591
+ }
592
+ try {
593
+ const result = await nhentai(url);
594
+ res.json(result);
595
+ setTimeout(() => {
596
+ fs.unlink(result.path, (err) => {
597
+ if (err) {
598
+ console.error(`Error deleting file: ${err.message}`);
599
+ } else {
600
+ console.log(`File deleted: ${result.path}`);
601
+ }
602
+ });
603
+ }, 370000);
604
+ } catch (error) {
605
+ res.status(500).send('Error processing request');
606
+ }
607
+ });
608
+
609
+
610
+ async function downloadFromUrl(url, filePath) {
611
+ const writer = fs.createWriteStream(filePath);
612
+
613
+ const response = await axios({
614
+ url,
615
+ method: 'GET',
616
+ responseType: 'stream'
617
+ });
618
+
619
+ response.data.pipe(writer);
620
+
621
+ return new Promise((resolve, reject) => {
622
+ writer.on('finish', resolve);
623
+ writer.on('error', reject);
624
+ });
625
+ }
626
+
627
+
628
+
629
+ async function Rules34Infonues(url_r34) {
630
+ try {
631
+ const browser = await puppeteer.launch();
632
+ const page = await browser.newPage();
633
+
634
+ await page.setExtraHTTPHeaders({
635
+ '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',
636
+ 'Referer': url_r34
637
+ });
638
+
639
+ await page.goto(url_r34, { referer: url_r34 });
640
+
641
+ const htmlContent = await page.content();
642
+ const $ = cheerio.load(htmlContent);
643
+
644
+ const title = $("body > div > div.wrapper > div.main > div.container > div > div > div:nth-child(1) > div.heading > h1").text().trim() ||
645
+ url_r34.match(/\/video\/\d+\/(.*)\//)?.[1];
646
+
647
+ const infoElements = $("#tab_video_info > div");
648
+ const result = {
649
+ title,
650
+ artist: [],
651
+ uploader: [],
652
+ tags: [],
653
+ download: [],
654
+ category: []
655
+ };
656
+
657
+ if (infoElements.length > 0) {
658
+ const [videoInfo, tags, download] = [
659
+ infoElements.eq(infoElements.length - 3),
660
+ infoElements.eq(infoElements.length - 2),
661
+ infoElements.eq(infoElements.length - 1)
662
+ ];
663
+
664
+ tags.find("div.wrap > a").each((_, element) => {
665
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
666
+ });
667
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
668
+
669
+ download.find("div.wrap > a").each((_, element) => {
670
+ result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
671
+ });
672
+
673
+ videoInfo.find("div.cols > div").each((_, col) => {
674
+ $(col).find("div.col:nth-child(1) > a").each((_, link) => {
675
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
676
+ });
677
+
678
+ $(col).find("div.col:nth-child(2) > a").each((_, link) => {
679
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
680
+ });
681
+
682
+ $(col).find("div.col:nth-child(3) > a").each((_, link) => {
683
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
684
+ });
685
+ });
686
+ }
687
+
688
+ await browser.close();
689
+ return result;
690
+ } catch (error) {
691
+ console.error('Error fetching data:', error);
692
+ throw error; // Lempar ulang error untuk ditangani di level atas
693
+ }
694
+ }
695
+
696
+
697
+
698
+ async function Rules34info(url_r34) {
699
+ try {
700
+ // Mengambil halaman HTML dengan Axios
701
+ const response = await axios.get(url_r34, {
702
+ headers: {
703
+ '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',
704
+ 'Referer': url_r34
705
+ }
706
+ });
707
+
708
+ const htmlContent = response.data;
709
+ const $ = cheerio.load(htmlContent);
710
+
711
+ 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];
712
+
713
+ const infoElements = $("#tab_video_info > div");
714
+ const result = {
715
+ title: title,
716
+ artist: [],
717
+ uploader: [],
718
+ tags: [],
719
+ category: []
720
+ };
721
+
722
+ if (infoElements.length > 0) {
723
+ const tags = infoElements.eq(infoElements.length - 2);
724
+ const videoInfo = infoElements.eq(infoElements.length - 3);
725
+
726
+ if (tags.length > 0) {
727
+ tags.find("div.wrap > a").each((index, element) => {
728
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
729
+ });
730
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
731
+ }
732
+
733
+ if (videoInfo.length > 0) {
734
+ videoInfo.find("div.cols > div").each((index, col) => {
735
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
736
+ categoryLinks.each((index, link) => {
737
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
738
+ });
739
+
740
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
741
+ artistLinks.each((index, link) => {
742
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
743
+ });
744
+
745
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
746
+ uploaderLinks.each((index, link) => {
747
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
748
+ });
749
+ });
750
+ }
751
+ }
752
+
753
+ return result;
754
+ } catch (error) {
755
+ console.error('Error fetching data:', error);
756
+ throw error; // Rethrow error to handle it upstream
757
+ }
758
+ }
759
+
760
+ async function Rules34(url_r34) {
761
+ try {
762
+ const browser = await puppeteer.launch();
763
+ const page = await browser.newPage();
764
+
765
+ await page.setExtraHTTPHeaders({
766
+ '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',
767
+ 'Referer': url_r34
768
+ });
769
+ await page.goto(url_r34, { referer: url_r34 });
770
+
771
+ const htmlContent = await page.content();
772
+ const $ = cheerio.load(htmlContent);
773
+
774
+ 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];
775
+
776
+ const infoElements = $("#tab_video_info > div");
777
+ const result = {
778
+ title: title,
779
+ artist: [],
780
+ uploader: [],
781
+ tags: [],
782
+ download: [],
783
+ category: []
784
+ };
785
+
786
+ if (infoElements.length > 0) {
787
+ const tags = infoElements.eq(infoElements.length - 2);
788
+ const download = infoElements.eq(infoElements.length - 1);
789
+ const videoInfo = infoElements.eq(infoElements.length - 3);
790
+
791
+ if (tags.length > 0) {
792
+ tags.find("div.wrap > a").each((index, element) => {
793
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
794
+ });
795
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
796
+ }
797
+
798
+ if (download.length > 0) {
799
+ download.find("div.wrap > a").each((index, element) => {
800
+ result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
801
+ });
802
+
803
+ // Mendownload dari URL terakhir di array download
804
+ const lastDownloadUrl = result.download[result.download.length - 1].url;
805
+ const downloadPath = path.resolve(os.tmpdir())
806
+ let filenem = `${Date.now()}_file.mp4`
807
+ const filePath = path.join(downloadPath, filenem)
808
+
809
+ await downloadFromUrl(lastDownloadUrl, filePath);
810
+
811
+ result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result
812
+ result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result
813
+ }
814
+
815
+ if (videoInfo.length > 0) {
816
+ videoInfo.find("div.cols > div").each((index, col) => {
817
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
818
+ categoryLinks.each((index, link) => {
819
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
820
+ });
821
+
822
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
823
+ artistLinks.each((index, link) => {
824
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
825
+ });
826
+
827
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
828
+ uploaderLinks.each((index, link) => {
829
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
830
+ });
831
+ });
832
+ }
833
+ }
834
+
835
+ await browser.close();
836
+ return result;
837
+ } catch (error) {
838
+ console.error('Error fetching data:', error);
839
+ throw error; // Rethrow error to handle it upstream
840
+ }
841
+ }
842
+
843
+
844
+ app.get('/r34', async (req, res) => {
845
+ const { url } = req.query;
846
+ if (!url) {
847
+ return res.status(400).send('URL is required');
848
+ }
849
+ try {
850
+ const result = await Rules34(url);
851
+ res.json(result);
852
+ const filePath = result.downloadPath;
853
+ // Hapus file setelah 8 menit (480000 milidetik)
854
+ setTimeout(() => {
855
+ fs.unlink(filePath, (err) => {
856
+ if (err) {
857
+ console.error(`Error deleting file: ${err.message}`);
858
+ } else {
859
+ console.log(`File deleted: ${filePath}`);
860
+ }
861
+ });
862
+ }, 280000);
863
+ } catch (error) {
864
+ res.status(500).send('Error processing request');
865
+ }
866
+ });
867
+
868
+
869
+ app.get('/r34/download', async (req, res) => {
870
+ const { url, type = 'download' } = req.query;
871
+ if (!url) {
872
+ return res.status(400).send('URL is required');
873
+ }
874
+
875
+ try {
876
+ const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34
877
+ const filePath = result.downloadPath;
878
+
879
+ // Cek apakah file benar-benar ada sebelum mengirim
880
+ if (!fs.existsSync(filePath)) {
881
+ return res.status(404).send('File not found');
882
+ }
883
+
884
+ const fileName = path.basename(filePath);
885
+ const mimeType = 'video/mp4';
886
+
887
+ res.setHeader('Content-Type', mimeType);
888
+
889
+ if (type === 'stream') {
890
+ const range = req.headers.range;
891
+
892
+ if (range) {
893
+ const stat = fs.statSync(filePath);
894
+ const fileSize = stat.size;
895
+
896
+ const parts = range.replace(/bytes=/, "").split("-");
897
+ const start = parseInt(parts[0], 10);
898
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
899
+
900
+ const chunksize = (end - start) + 1;
901
+ const file = fs.createReadStream(filePath, { start, end });
902
+ const head = {
903
+ 'Content-Range': `bytes ${start}-${end}/${fileSize}`,
904
+ 'Accept-Ranges': 'bytes',
905
+ 'Content-Length': chunksize,
906
+ 'Content-Type': mimeType,
907
+ };
908
+
909
+ res.writeHead(206, head);
910
+ file.pipe(res);
911
+ } else {
912
+ res.setHeader('Content-Length', fileSize);
913
+ res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file
914
+ }
915
+ } else if (type === 'buffer') {
916
+ fs.readFile(filePath, (err, data) => {
917
+ if (err) {
918
+ console.error('Gagal membaca file:', err);
919
+ res.status(500).send('Gagal membaca file: \n' + err);
920
+ } else {
921
+ res.setHeader('Content-Length', data.length);
922
+ res.send(data);
923
+ }
924
+ });
925
+ } else { // Default to 'download'
926
+ res.download(filePath, fileName, (err) => {
927
+ if (err) {
928
+ console.error('Gagal mengirim file:', err);
929
+ res.status(500).send('Gagal mengirim file: \n' + err);
930
+ }
931
+ });
932
+ }
933
+ } catch (error) {
934
+ console.error('Error processing request:', error);
935
+ res.status(500).send('Error processing request');
936
+ }
937
+ });
938
+
939
+
940
+ app.get('/r34/info', async (req, res) => {
941
+ const { url } = req.query;
942
+ if (!url) {
943
+ return res.status(400).send('URL is required');
944
+ }
945
+ try {
946
+ const result = await Rules34Infonues(url);
947
+ res.json(result);
948
+ } catch (error) {
949
+ res.status(500).send('Error processing request');
950
+ }
951
+ });
952
+
953
+
954
+ async function r34Cookie(url) {
955
+ const browser = await puppeteer.launch({
956
+ headless: true, // Non-headless untuk debugging
957
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
958
+ });
959
+ const page = await browser.newPage();
960
+ // Setel header User-Agent dan Referer
961
+ await page.setExtraHTTPHeaders({
962
+ 'User-Agent': getRandomUserAgent(),
963
+ 'Referer': url,
964
+ 'X-Forwarded-For': generateRandomIP()
965
+ });
966
+ await page.goto(url); // Buka URL yang diberikan
967
+ const cookies = await page.cookies();
968
+ await browser.close();
969
+ return { cookies };
970
+ }
971
+
972
+ app.get('/r34cookie', async (req, res) => {
973
+ const { url } = req.query;
974
+ if (!url) {
975
+ return res.status(400).send('URL is required');
976
+ }
977
+ try {
978
+ const result = await r34Cookie(url);
979
+ res.json(result);
980
+ } catch (error) {
981
+ res.status(500).send('Error processing request');
982
+ }
983
+ });
984
+
985
+ // Fungsi untuk ping website
986
+ async function pingWebsite() {
987
+ const browser = await puppeteer.launch({
988
+ headless: true,
989
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
990
+ });
991
+ const page = await browser.newPage();
992
+ 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;]");
993
+ await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
994
+ console.log("Ping");
995
+ await browser.close();
996
+ }
997
+
998
+ // Ping website setiap 5 jam
999
+ async function pingEvery5Hours() {
1000
+ await pingWebsite();
1001
+ setInterval(async () => {
1002
+ await pingWebsite();
1003
+ }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
1004
+ }
1005
+
1006
+ // Mulai ping
1007
+ pingEvery5Hours();
1008
+
1009
+ app.listen(PORT, () => {
1010
+ console.log(`Server is running on port ${PORT}`);
1011
  });