Nexchan commited on
Commit
3cf4e79
·
verified ·
1 Parent(s): 3ed92fd

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +593 -593
index.js CHANGED
@@ -1,594 +1,594 @@
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
-
14
-
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
-
21
-
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
- const generateRandomIP = () => {
67
- const octet = () => Math.floor(Math.random() * 256);
68
- return `${octet()}.${octet()}.${octet()}.${octet()}`;
69
- };
70
-
71
- function generateRandomID(length = 8) {
72
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
73
- let result = '';
74
- for (let i = 0; i < length; i++) {
75
- result += characters.charAt(Math.floor(Math.random() * characters.length));
76
- }
77
- return result;
78
- }
79
-
80
- async function komiku_download(url) {
81
- const instanceID = generateRandomID();
82
- const tempDir = path.join(os.tmpdir(), instanceID);
83
- await fss.mkdir(tempDir);
84
-
85
- const title = url.split('/').filter(part => part).pop();
86
-
87
- try {
88
- const response = await axios.get(url, {
89
- headers: {
90
- '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;]',
91
- 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
92
- 'X-Forwarded-For': generateRandomIP()
93
- }
94
- });
95
- const html = response.data;
96
- const $ = cheerio.load(html);
97
- const imgList = [];
98
-
99
- $('#Baca_Komik img').each((index, element) => {
100
- const src = $(element).attr('src');
101
- imgList.push({ path: src });
102
- });
103
-
104
- const imagePaths = await downloadImages(imgList, tempDir, instanceID);
105
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
106
-
107
- return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title };
108
- } catch (error) {
109
- console.log(error);
110
- throw error;
111
- } finally {
112
- await fss.rmdir(tempDir, { recursive: true });
113
- }
114
- }
115
-
116
- async function downloadImage(image, tempDir, instanceID) {
117
- const response = await axios.get(image.path, {
118
- responseType: 'arraybuffer',
119
- headers: {
120
- '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;]',
121
- 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
122
- 'X-Forwarded-For': generateRandomIP()
123
- }
124
- });
125
- const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`);
126
- await writeFileAsync(imagePath, response.data);
127
-
128
- return imagePath;
129
- }
130
-
131
- async function downloadImages(imgList, tempDir, instanceID) {
132
- const imagePaths = [];
133
- for (const img of imgList) {
134
- const imagePath = await downloadImage(img, tempDir, instanceID);
135
- imagePaths.push(imagePath);
136
- }
137
- return imagePaths;
138
- }
139
-
140
- async function createPDF(imagePaths, instanceID, tempDir) {
141
- const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
142
- const doc = new PDFDocument({ autoFirstPage: false });
143
-
144
- doc.pipe(fs.createWriteStream(pdfPath));
145
-
146
- for (const imagePath of imagePaths) {
147
- const { width, height } = await getImageDimensions(imagePath);
148
- doc.addPage({ size: [width, height] });
149
- doc.image(imagePath, 0, 0, { width: width, height: height });
150
- }
151
-
152
- doc.end();
153
-
154
- return pdfPath;
155
- }
156
-
157
- async function getImageDimensions(imagePath) {
158
- const sizeOf = promisify(require('image-size'));
159
- const dimensions = await sizeOf(imagePath);
160
- return dimensions;
161
- }
162
-
163
- app.get('/download', async (req, res) => {
164
- const { url } = req.query;
165
- if (!url) {
166
- return res.status(400).send('URL is required');
167
- }
168
-
169
- try {
170
- const result = await komiku_download(url);
171
- res.json(result);
172
- } catch (error) {
173
- res.status(500).send('Error processing request');
174
- }
175
- });
176
-
177
- async function nhentai(url) {
178
- const instanceID = generateRandomID();
179
- const tempDir = `./${instanceID}`;
180
- await fss.mkdir(tempDir);
181
- const title = url.split('g/').filter(part => part).pop();
182
- try {
183
- const response = await axios.get(url, {
184
- headers: {
185
- '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;]',
186
- 'Referer': 'https://nhentai.net/',
187
- 'X-Forwarded-For': generateRandomIP()
188
- }
189
- })
190
- const $ = cheerio.load(response.data);
191
- const scriptContent = $('script').filter((i, el) => {
192
- return $(el).html().includes('window._gallery = JSON.parse');
193
- }).html();
194
-
195
- const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1];
196
- const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\');
197
- const jsonData = JSON.parse(decodedString);
198
- console.log(jsonData)
199
-
200
- const imgList = [];
201
- for (let i = 0; i < jsonData.images.pages.length; i++) {
202
- 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` });
203
- }
204
-
205
- const imagePaths = await downloadImageNhs(imgList, tempDir, instanceID);
206
- const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
207
-
208
- console.log(`PDF berhasil dibuat: ${pdfPath}`);
209
- return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: pdfPath, result: jsonData };
210
- } catch (error) {
211
- console.log(error);
212
- throw error;
213
- } finally {
214
- await fss.rmdir(tempDir, { recursive: true });
215
- }
216
- }
217
-
218
- async function downloadImageNh(image, tempDir, instanceID) {
219
- const response = await axios.get(image.path, {
220
- responseType: 'arraybuffer',
221
- headers: {
222
- '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;]',
223
- 'Referer': 'https://nhentai.net/'
224
- }
225
- });
226
-
227
- const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`;
228
- await writeFileAsync(imagePath, response.data);
229
-
230
- return imagePath;
231
- }
232
-
233
- async function downloadImageNhs(imgList, tempDir, instanceID) {
234
- const imagePaths = [];
235
- for (const img of imgList) {
236
- const imagePath = await downloadImageNh(img, tempDir, instanceID);
237
- imagePaths.push(imagePath);
238
- }
239
- return imagePaths;
240
- }
241
-
242
- app.get('/nhentai', async (req, res) => {
243
- const { url } = req.query;
244
- if (!url) {
245
- return res.status(400).send('URL is required');
246
- }
247
- try {
248
- const result = await nhentai(url);
249
- res.json(result);
250
- setTimeout(() => {
251
- fs.unlink(result.path, (err) => {
252
- if (err) {
253
- console.error(`Error deleting file: ${err.message}`);
254
- } else {
255
- console.log(`File deleted: ${filePath}`);
256
- }
257
- });
258
- }, 480000);
259
- } catch (error) {
260
- res.status(500).send('Error processing request');
261
- }
262
- });
263
-
264
-
265
- async function downloadFromUrl(url, filePath) {
266
- const writer = fs.createWriteStream(filePath);
267
-
268
- const response = await axios({
269
- url,
270
- method: 'GET',
271
- responseType: 'stream'
272
- });
273
-
274
- response.data.pipe(writer);
275
-
276
- return new Promise((resolve, reject) => {
277
- writer.on('finish', resolve);
278
- writer.on('error', reject);
279
- });
280
- }
281
-
282
- async function Rules34info(url_r34) {
283
- try {
284
- // Mengambil halaman HTML dengan Axios
285
- const response = await axios.get(url_r34, {
286
- headers: {
287
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
288
- 'Referer': url_r34
289
- }
290
- });
291
-
292
- const htmlContent = response.data;
293
- const $ = cheerio.load(htmlContent);
294
-
295
- 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];
296
-
297
- const infoElements = $("#tab_video_info > div");
298
- const result = {
299
- title: title,
300
- artist: [],
301
- uploader: [],
302
- tags: [],
303
- category: []
304
- };
305
-
306
- if (infoElements.length > 0) {
307
- const tags = infoElements.eq(infoElements.length - 2);
308
- const videoInfo = infoElements.eq(infoElements.length - 3);
309
-
310
- if (tags.length > 0) {
311
- tags.find("div.wrap > a").each((index, element) => {
312
- result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
313
- });
314
- result.tags.pop(); // Menghapus elemen terakhir dari tags
315
- }
316
-
317
- if (videoInfo.length > 0) {
318
- videoInfo.find("div.cols > div").each((index, col) => {
319
- const categoryLinks = $(col).find("div.col:nth-child(1) > a");
320
- categoryLinks.each((index, link) => {
321
- result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
322
- });
323
-
324
- const artistLinks = $(col).find("div.col:nth-child(2) > a");
325
- artistLinks.each((index, link) => {
326
- result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
327
- });
328
-
329
- const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
330
- uploaderLinks.each((index, link) => {
331
- result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
332
- });
333
- });
334
- }
335
- }
336
-
337
- return result;
338
- } catch (error) {
339
- console.error('Error fetching data:', error);
340
- throw error; // Rethrow error to handle it upstream
341
- }
342
- }
343
-
344
- async function Rules34(url_r34) {
345
- try {
346
- const browser = await puppeteer.launch();
347
- const page = await browser.newPage();
348
-
349
- await page.setExtraHTTPHeaders({
350
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
351
- 'Referer': url_r34
352
- });
353
- await page.goto(url_r34, { referer: url_r34 });
354
-
355
- const htmlContent = await page.content();
356
- const $ = cheerio.load(htmlContent);
357
-
358
- 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];
359
-
360
- const infoElements = $("#tab_video_info > div");
361
- const result = {
362
- title: title,
363
- artist: [],
364
- uploader: [],
365
- tags: [],
366
- download: [],
367
- category: []
368
- };
369
-
370
- if (infoElements.length > 0) {
371
- const tags = infoElements.eq(infoElements.length - 2);
372
- const download = infoElements.eq(infoElements.length - 1);
373
- const videoInfo = infoElements.eq(infoElements.length - 3);
374
-
375
- if (tags.length > 0) {
376
- tags.find("div.wrap > a").each((index, element) => {
377
- result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
378
- });
379
- result.tags.pop(); // Menghapus elemen terakhir dari tags
380
- }
381
-
382
- if (download.length > 0) {
383
- download.find("div.wrap > a").each((index, element) => {
384
- result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
385
- });
386
-
387
- // Mendownload dari URL terakhir di array download
388
- const lastDownloadUrl = result.download[result.download.length - 1].url;
389
- const downloadPath = path.resolve(os.tmpdir())
390
- let filenem = `${Date.now()}_file.mp4`
391
- const filePath = path.join(downloadPath, filenem)
392
-
393
- await downloadFromUrl(lastDownloadUrl, filePath);
394
-
395
- result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result
396
- result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result
397
- }
398
-
399
- if (videoInfo.length > 0) {
400
- videoInfo.find("div.cols > div").each((index, col) => {
401
- const categoryLinks = $(col).find("div.col:nth-child(1) > a");
402
- categoryLinks.each((index, link) => {
403
- result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
404
- });
405
-
406
- const artistLinks = $(col).find("div.col:nth-child(2) > a");
407
- artistLinks.each((index, link) => {
408
- result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
409
- });
410
-
411
- const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
412
- uploaderLinks.each((index, link) => {
413
- result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
414
- });
415
- });
416
- }
417
- }
418
-
419
- await browser.close();
420
- return result;
421
- } catch (error) {
422
- console.error('Error fetching data:', error);
423
- throw error; // Rethrow error to handle it upstream
424
- }
425
- }
426
-
427
- app.get('/r34', async (req, res) => {
428
- const { url } = req.query;
429
- if (!url) {
430
- return res.status(400).send('URL is required');
431
- }
432
- try {
433
- const result = await Rules34(url);
434
- res.json(result);
435
- const filePath = result.downloadPath;
436
- // Hapus file setelah 8 menit (480000 milidetik)
437
- setTimeout(() => {
438
- fs.unlink(filePath, (err) => {
439
- if (err) {
440
- console.error(`Error deleting file: ${err.message}`);
441
- } else {
442
- console.log(`File deleted: ${filePath}`);
443
- }
444
- });
445
- }, 480000);
446
- } catch (error) {
447
- res.status(500).send('Error processing request');
448
- }
449
- });
450
-
451
-
452
- app.get('/r34/download', async (req, res) => {
453
- const { url, type = 'download' } = req.query;
454
- if (!url) {
455
- return res.status(400).send('URL is required');
456
- }
457
-
458
- try {
459
- const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34
460
- const filePath = result.downloadPath;
461
-
462
- // Cek apakah file benar-benar ada sebelum mengirim
463
- if (!fs.existsSync(filePath)) {
464
- return res.status(404).send('File not found');
465
- }
466
-
467
- const fileName = path.basename(filePath);
468
- const mimeType = 'video/mp4';
469
-
470
- res.setHeader('Content-Type', mimeType);
471
-
472
- if (type === 'stream') {
473
- const range = req.headers.range;
474
-
475
- if (range) {
476
- const stat = fs.statSync(filePath);
477
- const fileSize = stat.size;
478
-
479
- const parts = range.replace(/bytes=/, "").split("-");
480
- const start = parseInt(parts[0], 10);
481
- const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
482
-
483
- const chunksize = (end - start) + 1;
484
- const file = fs.createReadStream(filePath, { start, end });
485
- const head = {
486
- 'Content-Range': `bytes ${start}-${end}/${fileSize}`,
487
- 'Accept-Ranges': 'bytes',
488
- 'Content-Length': chunksize,
489
- 'Content-Type': mimeType,
490
- };
491
-
492
- res.writeHead(206, head);
493
- file.pipe(res);
494
- } else {
495
- res.setHeader('Content-Length', fileSize);
496
- res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file
497
- }
498
- } else if (type === 'buffer') {
499
- fs.readFile(filePath, (err, data) => {
500
- if (err) {
501
- console.error('Gagal membaca file:', err);
502
- res.status(500).send('Gagal membaca file: \n' + err);
503
- } else {
504
- res.setHeader('Content-Length', data.length);
505
- res.send(data);
506
- }
507
- });
508
- } else { // Default to 'download'
509
- res.download(filePath, fileName, (err) => {
510
- if (err) {
511
- console.error('Gagal mengirim file:', err);
512
- res.status(500).send('Gagal mengirim file: \n' + err);
513
- }
514
- });
515
- }
516
- } catch (error) {
517
- console.error('Error processing request:', error);
518
- res.status(500).send('Error processing request');
519
- }
520
- });
521
-
522
-
523
- app.get('/r34/info', async (req, res) => {
524
- const { url } = req.query;
525
- if (!url) {
526
- return res.status(400).send('URL is required');
527
- }
528
- try {
529
- const result = await Rules34info(url);
530
- res.json(result);
531
- } catch (error) {
532
- res.status(500).send('Error processing request');
533
- }
534
- });
535
-
536
-
537
- async function r34Cookie(url) {
538
- const browser = await puppeteer.launch({
539
- headless: true, // Non-headless untuk debugging
540
- args: ['--no-sandbox', '--disable-setuid-sandbox']
541
- });
542
- const page = await browser.newPage();
543
- // Setel header User-Agent dan Referer
544
- await page.setExtraHTTPHeaders({
545
- 'User-Agent': getRandomUserAgent(),
546
- 'Referer': url,
547
- 'X-Forwarded-For': generateRandomIP()
548
- });
549
- await page.goto(url); // Buka URL yang diberikan
550
- const cookies = await page.cookies();
551
- await browser.close();
552
- return { cookies };
553
- }
554
-
555
- app.get('/r34cookie', async (req, res) => {
556
- const { url } = req.query;
557
- if (!url) {
558
- return res.status(400).send('URL is required');
559
- }
560
- try {
561
- const result = await r34Cookie(url);
562
- res.json(result);
563
- } catch (error) {
564
- res.status(500).send('Error processing request');
565
- }
566
- });
567
-
568
- // Fungsi untuk ping website
569
- async function pingWebsite() {
570
- const browser = await puppeteer.launch({
571
- headless: true,
572
- args: ['--no-sandbox', '--disable-setuid-sandbox']
573
- });
574
- const page = await browser.newPage();
575
- 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;]");
576
- await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
577
- console.log("Ping");
578
- await browser.close();
579
- }
580
-
581
- // Ping website setiap 5 jam
582
- async function pingEvery5Hours() {
583
- await pingWebsite();
584
- setInterval(async () => {
585
- await pingWebsite();
586
- }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
587
- }
588
-
589
- // Mulai ping
590
- pingEvery5Hours();
591
-
592
- app.listen(PORT, () => {
593
- console.log(`Server is running on port ${PORT}`);
594
  });
 
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
+
14
+
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
+
21
+
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
+ const generateRandomIP = () => {
67
+ const octet = () => Math.floor(Math.random() * 256);
68
+ return `${octet()}.${octet()}.${octet()}.${octet()}`;
69
+ };
70
+
71
+ function generateRandomID(length = 8) {
72
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
73
+ let result = '';
74
+ for (let i = 0; i < length; i++) {
75
+ result += characters.charAt(Math.floor(Math.random() * characters.length));
76
+ }
77
+ return result;
78
+ }
79
+
80
+ async function komiku_download(url) {
81
+ const instanceID = generateRandomID();
82
+ const tempDir = path.join(os.tmpdir(), instanceID);
83
+ await fss.mkdir(tempDir);
84
+
85
+ const title = url.split('/').filter(part => part).pop();
86
+
87
+ try {
88
+ const response = await axios.get(url, {
89
+ headers: {
90
+ '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;]',
91
+ 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
92
+ 'X-Forwarded-For': generateRandomIP()
93
+ }
94
+ });
95
+ const html = response.data;
96
+ const $ = cheerio.load(html);
97
+ const imgList = [];
98
+
99
+ $('#Baca_Komik img').each((index, element) => {
100
+ const src = $(element).attr('src');
101
+ imgList.push({ path: src });
102
+ });
103
+
104
+ const imagePaths = await downloadImages(imgList, tempDir, instanceID);
105
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
106
+
107
+ return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: `/static/${instanceID}.pdf`, title: title };
108
+ } catch (error) {
109
+ console.log(error);
110
+ throw error;
111
+ } finally {
112
+ await fss.rmdir(tempDir, { recursive: true });
113
+ }
114
+ }
115
+
116
+ async function downloadImage(image, tempDir, instanceID) {
117
+ const response = await axios.get(image.path, {
118
+ responseType: 'arraybuffer',
119
+ headers: {
120
+ '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;]',
121
+ 'Referer': 'https://komiku.id/devious-son-of-heaven-chapter-04/',
122
+ 'X-Forwarded-For': generateRandomIP()
123
+ }
124
+ });
125
+ const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`);
126
+ await writeFileAsync(imagePath, response.data);
127
+
128
+ return imagePath;
129
+ }
130
+
131
+ async function downloadImages(imgList, tempDir, instanceID) {
132
+ const imagePaths = [];
133
+ for (const img of imgList) {
134
+ const imagePath = await downloadImage(img, tempDir, instanceID);
135
+ imagePaths.push(imagePath);
136
+ }
137
+ return imagePaths;
138
+ }
139
+
140
+ async function createPDF(imagePaths, instanceID, tempDir) {
141
+ const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
142
+ const doc = new PDFDocument({ autoFirstPage: false });
143
+
144
+ doc.pipe(fs.createWriteStream(pdfPath));
145
+
146
+ for (const imagePath of imagePaths) {
147
+ const { width, height } = await getImageDimensions(imagePath);
148
+ doc.addPage({ size: [width, height] });
149
+ doc.image(imagePath, 0, 0, { width: width, height: height });
150
+ }
151
+
152
+ doc.end();
153
+
154
+ return pdfPath;
155
+ }
156
+
157
+ async function getImageDimensions(imagePath) {
158
+ const sizeOf = promisify(require('image-size'));
159
+ const dimensions = await sizeOf(imagePath);
160
+ return dimensions;
161
+ }
162
+
163
+ app.get('/download', async (req, res) => {
164
+ const { url } = req.query;
165
+ if (!url) {
166
+ return res.status(400).send('URL is required');
167
+ }
168
+
169
+ try {
170
+ const result = await komiku_download(url);
171
+ res.json(result);
172
+ } catch (error) {
173
+ res.status(500).send('Error processing request');
174
+ }
175
+ });
176
+
177
+ async function nhentai(url) {
178
+ const instanceID = generateRandomID();
179
+ const tempDir = `./${instanceID}`;
180
+ await fss.mkdir(tempDir);
181
+ const title = url.split('g/').filter(part => part).pop();
182
+ try {
183
+ const response = await axios.get(url, {
184
+ headers: {
185
+ '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;]',
186
+ 'Referer': 'https://nhentai.net/',
187
+ 'X-Forwarded-For': generateRandomIP()
188
+ }
189
+ })
190
+ const $ = cheerio.load(response.data);
191
+ const scriptContent = $('script').filter((i, el) => {
192
+ return $(el).html().includes('window._gallery = JSON.parse');
193
+ }).html();
194
+
195
+ const jsonString = scriptContent.match(/JSON\.parse\("(.*)"\)/)[1];
196
+ const decodedString = jsonString.replace(/\\u0022/g, '"').replace(/\\u005C/g, '\\');
197
+ const jsonData = JSON.parse(decodedString);
198
+ console.log(jsonData)
199
+
200
+ const imgList = [];
201
+ for (let i = 0; i < jsonData.images.pages.length; i++) {
202
+ 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` });
203
+ }
204
+
205
+ const imagePaths = await downloadImageNhs(imgList, tempDir, instanceID);
206
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
207
+
208
+ console.log(`PDF berhasil dibuat: ${pdfPath}`);
209
+ return { url: "https://arashicode-komik.hf.space/static/" + instanceID + ".pdf", path: pdfPath, result: jsonData };
210
+ } catch (error) {
211
+ console.log(error);
212
+ throw error;
213
+ } finally {
214
+ await fss.rmdir(tempDir, { recursive: true });
215
+ }
216
+ }
217
+
218
+ async function downloadImageNh(image, tempDir, instanceID) {
219
+ const response = await axios.get(image.path, {
220
+ responseType: 'arraybuffer',
221
+ headers: {
222
+ '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;]',
223
+ 'Referer': 'https://nhentai.net/'
224
+ }
225
+ });
226
+
227
+ const imagePath = `${tempDir}/image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`;
228
+ await writeFileAsync(imagePath, response.data);
229
+
230
+ return imagePath;
231
+ }
232
+
233
+ async function downloadImageNhs(imgList, tempDir, instanceID) {
234
+ const imagePaths = [];
235
+ for (const img of imgList) {
236
+ const imagePath = await downloadImageNh(img, tempDir, instanceID);
237
+ imagePaths.push(imagePath);
238
+ }
239
+ return imagePaths;
240
+ }
241
+
242
+ app.get('/nhentai', async (req, res) => {
243
+ const { url } = req.query;
244
+ if (!url) {
245
+ return res.status(400).send('URL is required');
246
+ }
247
+ try {
248
+ const result = await nhentai(url);
249
+ res.json(result);
250
+ setTimeout(() => {
251
+ fs.unlink(result.path, (err) => {
252
+ if (err) {
253
+ console.error(`Error deleting file: ${err.message}`);
254
+ } else {
255
+ console.log(`File deleted: ${filePath}`);
256
+ }
257
+ });
258
+ }, 480000);
259
+ } catch (error) {
260
+ res.status(500).send('Error processing request');
261
+ }
262
+ });
263
+
264
+
265
+ async function downloadFromUrl(url, filePath) {
266
+ const writer = fs.createWriteStream(filePath);
267
+
268
+ const response = await axios({
269
+ url,
270
+ method: 'GET',
271
+ responseType: 'stream'
272
+ });
273
+
274
+ response.data.pipe(writer);
275
+
276
+ return new Promise((resolve, reject) => {
277
+ writer.on('finish', resolve);
278
+ writer.on('error', reject);
279
+ });
280
+ }
281
+
282
+ async function Rules34info(url_r34) {
283
+ try {
284
+ // Mengambil halaman HTML dengan Axios
285
+ const response = await axios.get(url_r34, {
286
+ headers: {
287
+ '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',
288
+ 'Referer': url_r34
289
+ }
290
+ });
291
+
292
+ const htmlContent = response.data;
293
+ const $ = cheerio.load(htmlContent);
294
+
295
+ 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];
296
+
297
+ const infoElements = $("#tab_video_info > div");
298
+ const result = {
299
+ title: title,
300
+ artist: [],
301
+ uploader: [],
302
+ tags: [],
303
+ category: []
304
+ };
305
+
306
+ if (infoElements.length > 0) {
307
+ const tags = infoElements.eq(infoElements.length - 2);
308
+ const videoInfo = infoElements.eq(infoElements.length - 3);
309
+
310
+ if (tags.length > 0) {
311
+ tags.find("div.wrap > a").each((index, element) => {
312
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
313
+ });
314
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
315
+ }
316
+
317
+ if (videoInfo.length > 0) {
318
+ videoInfo.find("div.cols > div").each((index, col) => {
319
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
320
+ categoryLinks.each((index, link) => {
321
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
322
+ });
323
+
324
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
325
+ artistLinks.each((index, link) => {
326
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
327
+ });
328
+
329
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
330
+ uploaderLinks.each((index, link) => {
331
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
332
+ });
333
+ });
334
+ }
335
+ }
336
+
337
+ return result;
338
+ } catch (error) {
339
+ console.error('Error fetching data:', error);
340
+ throw error; // Rethrow error to handle it upstream
341
+ }
342
+ }
343
+
344
+ async function Rules34(url_r34) {
345
+ try {
346
+ const browser = await puppeteer.launch();
347
+ const page = await browser.newPage();
348
+
349
+ await page.setExtraHTTPHeaders({
350
+ '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',
351
+ 'Referer': url_r34
352
+ });
353
+ await page.goto(url_r34, { referer: url_r34 });
354
+
355
+ const htmlContent = await page.content();
356
+ const $ = cheerio.load(htmlContent);
357
+
358
+ 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];
359
+
360
+ const infoElements = $("#tab_video_info > div");
361
+ const result = {
362
+ title: title,
363
+ artist: [],
364
+ uploader: [],
365
+ tags: [],
366
+ download: [],
367
+ category: []
368
+ };
369
+
370
+ if (infoElements.length > 0) {
371
+ const tags = infoElements.eq(infoElements.length - 2);
372
+ const download = infoElements.eq(infoElements.length - 1);
373
+ const videoInfo = infoElements.eq(infoElements.length - 3);
374
+
375
+ if (tags.length > 0) {
376
+ tags.find("div.wrap > a").each((index, element) => {
377
+ result.tags.push({ title: $(element).text().trim(), url: $(element).attr('href') });
378
+ });
379
+ result.tags.pop(); // Menghapus elemen terakhir dari tags
380
+ }
381
+
382
+ if (download.length > 0) {
383
+ download.find("div.wrap > a").each((index, element) => {
384
+ result.download.push({ quality: $(element).text().trim(), url: $(element).attr('href') });
385
+ });
386
+
387
+ // Mendownload dari URL terakhir di array download
388
+ const lastDownloadUrl = result.download[result.download.length - 1].url;
389
+ const downloadPath = path.resolve(os.tmpdir())
390
+ let filenem = `${Date.now()}_file.mp4`
391
+ const filePath = path.join(downloadPath, filenem)
392
+
393
+ await downloadFromUrl(lastDownloadUrl, filePath);
394
+
395
+ result.downloadPath = filePath; // Menambahkan path file yang telah di-download ke dalam objek result
396
+ result.downloadUrl = "https://arashicode-komik.hf.space/static/" + filenem; // Menambahkan path file yang telah di-download ke dalam objek result
397
+ }
398
+
399
+ if (videoInfo.length > 0) {
400
+ videoInfo.find("div.cols > div").each((index, col) => {
401
+ const categoryLinks = $(col).find("div.col:nth-child(1) > a");
402
+ categoryLinks.each((index, link) => {
403
+ result.category.push({ title: $(link).text().trim(), url: $(link).attr('href') });
404
+ });
405
+
406
+ const artistLinks = $(col).find("div.col:nth-child(2) > a");
407
+ artistLinks.each((index, link) => {
408
+ result.artist.push({ title: $(link).text().trim(), url: $(link).attr('href') });
409
+ });
410
+
411
+ const uploaderLinks = $(col).find("div.col:nth-child(3) > a");
412
+ uploaderLinks.each((index, link) => {
413
+ result.uploader.push({ title: $(link).text().trim(), url: $(link).attr('href') });
414
+ });
415
+ });
416
+ }
417
+ }
418
+
419
+ await browser.close();
420
+ return result;
421
+ } catch (error) {
422
+ console.error('Error fetching data:', error);
423
+ throw error; // Rethrow error to handle it upstream
424
+ }
425
+ }
426
+
427
+ app.get('/r34', async (req, res) => {
428
+ const { url } = req.query;
429
+ if (!url) {
430
+ return res.status(400).send('URL is required');
431
+ }
432
+ try {
433
+ const result = await Rules34(url);
434
+ res.json(result);
435
+ const filePath = result.downloadPath;
436
+ // Hapus file setelah 8 menit (480000 milidetik)
437
+ setTimeout(() => {
438
+ fs.unlink(filePath, (err) => {
439
+ if (err) {
440
+ console.error(`Error deleting file: ${err.message}`);
441
+ } else {
442
+ console.log(`File deleted: ${filePath}`);
443
+ }
444
+ });
445
+ }, 280000);
446
+ } catch (error) {
447
+ res.status(500).send('Error processing request');
448
+ }
449
+ });
450
+
451
+
452
+ app.get('/r34/download', async (req, res) => {
453
+ const { url, type = 'download' } = req.query;
454
+ if (!url) {
455
+ return res.status(400).send('URL is required');
456
+ }
457
+
458
+ try {
459
+ const result = await Rules34(url); // Mendapatkan jalur unduhan dari modul Rules34
460
+ const filePath = result.downloadPath;
461
+
462
+ // Cek apakah file benar-benar ada sebelum mengirim
463
+ if (!fs.existsSync(filePath)) {
464
+ return res.status(404).send('File not found');
465
+ }
466
+
467
+ const fileName = path.basename(filePath);
468
+ const mimeType = 'video/mp4';
469
+
470
+ res.setHeader('Content-Type', mimeType);
471
+
472
+ if (type === 'stream') {
473
+ const range = req.headers.range;
474
+
475
+ if (range) {
476
+ const stat = fs.statSync(filePath);
477
+ const fileSize = stat.size;
478
+
479
+ const parts = range.replace(/bytes=/, "").split("-");
480
+ const start = parseInt(parts[0], 10);
481
+ const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
482
+
483
+ const chunksize = (end - start) + 1;
484
+ const file = fs.createReadStream(filePath, { start, end });
485
+ const head = {
486
+ 'Content-Range': `bytes ${start}-${end}/${fileSize}`,
487
+ 'Accept-Ranges': 'bytes',
488
+ 'Content-Length': chunksize,
489
+ 'Content-Type': mimeType,
490
+ };
491
+
492
+ res.writeHead(206, head);
493
+ file.pipe(res);
494
+ } else {
495
+ res.setHeader('Content-Length', fileSize);
496
+ res.sendFile(filePath); // Menggunakan res.sendFile untuk mengirim file
497
+ }
498
+ } else if (type === 'buffer') {
499
+ fs.readFile(filePath, (err, data) => {
500
+ if (err) {
501
+ console.error('Gagal membaca file:', err);
502
+ res.status(500).send('Gagal membaca file: \n' + err);
503
+ } else {
504
+ res.setHeader('Content-Length', data.length);
505
+ res.send(data);
506
+ }
507
+ });
508
+ } else { // Default to 'download'
509
+ res.download(filePath, fileName, (err) => {
510
+ if (err) {
511
+ console.error('Gagal mengirim file:', err);
512
+ res.status(500).send('Gagal mengirim file: \n' + err);
513
+ }
514
+ });
515
+ }
516
+ } catch (error) {
517
+ console.error('Error processing request:', error);
518
+ res.status(500).send('Error processing request');
519
+ }
520
+ });
521
+
522
+
523
+ app.get('/r34/info', async (req, res) => {
524
+ const { url } = req.query;
525
+ if (!url) {
526
+ return res.status(400).send('URL is required');
527
+ }
528
+ try {
529
+ const result = await Rules34info(url);
530
+ res.json(result);
531
+ } catch (error) {
532
+ res.status(500).send('Error processing request');
533
+ }
534
+ });
535
+
536
+
537
+ async function r34Cookie(url) {
538
+ const browser = await puppeteer.launch({
539
+ headless: true, // Non-headless untuk debugging
540
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
541
+ });
542
+ const page = await browser.newPage();
543
+ // Setel header User-Agent dan Referer
544
+ await page.setExtraHTTPHeaders({
545
+ 'User-Agent': getRandomUserAgent(),
546
+ 'Referer': url,
547
+ 'X-Forwarded-For': generateRandomIP()
548
+ });
549
+ await page.goto(url); // Buka URL yang diberikan
550
+ const cookies = await page.cookies();
551
+ await browser.close();
552
+ return { cookies };
553
+ }
554
+
555
+ app.get('/r34cookie', async (req, res) => {
556
+ const { url } = req.query;
557
+ if (!url) {
558
+ return res.status(400).send('URL is required');
559
+ }
560
+ try {
561
+ const result = await r34Cookie(url);
562
+ res.json(result);
563
+ } catch (error) {
564
+ res.status(500).send('Error processing request');
565
+ }
566
+ });
567
+
568
+ // Fungsi untuk ping website
569
+ async function pingWebsite() {
570
+ const browser = await puppeteer.launch({
571
+ headless: true,
572
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
573
+ });
574
+ const page = await browser.newPage();
575
+ 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;]");
576
+ await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
577
+ console.log("Ping");
578
+ await browser.close();
579
+ }
580
+
581
+ // Ping website setiap 5 jam
582
+ async function pingEvery5Hours() {
583
+ await pingWebsite();
584
+ setInterval(async () => {
585
+ await pingWebsite();
586
+ }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds
587
+ }
588
+
589
+ // Mulai ping
590
+ pingEvery5Hours();
591
+
592
+ app.listen(PORT, () => {
593
+ console.log(`Server is running on port ${PORT}`);
594
  });