Closure-RI commited on
Commit
31e13bd
·
verified ·
1 Parent(s): 0af9bb5

Update index.js

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