Nexchan commited on
Commit
5f9ad1e
1 Parent(s): f53f1f1

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +54 -430
index.js CHANGED
@@ -1,247 +1,23 @@
 
 
 
 
 
1
  import axios from 'axios';
2
  import cheerio from 'cheerio';
3
- import { createRequire } from 'module';
4
- import os from 'os';
5
- import express from 'express';
6
  import { promisify } from 'util';
7
- import { fileTypeFromBuffer } from 'file-type';
8
- import ffmpeg from 'fluent-ffmpeg';
9
- import nodeID3 from 'node-id3';
10
- import ytdl from 'ytdl-core';
11
- import FormData from 'form-data';
12
- import fetch from 'node-fetch';
13
 
14
  const require = createRequire(import.meta.url);
15
- const fs = require('fs');
16
- const path = require('path');
17
- const { google } = require('googleapis');
18
  const puppeteer = require('puppeteer');
19
  import { fileURLToPath } from 'url';
20
  const PORT = process.env.PORT || 7860;
21
  const app = express();
22
- const readFileAsync = promisify(fs.readFile);
23
-
24
- const tempDir = path.join(os.tmpdir(), "temp");
25
- const fss = fs.promises;
26
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
27
- // Membuat direktori sementara jika belum ada
28
- (async () => {
29
- if (!fs.existsSync(tempDir)) {
30
- await fss.mkdir(tempDir, { recursive: true });
31
- }
32
- })();
33
- const { exec } = require('child_process');
34
  const writeFileAsync = promisify(fs.writeFile);
35
- const execPromise = promisify(exec);
36
- const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' });
37
-
38
-
39
-
40
- const tempDirBase = tempDir
41
-
42
-
43
- app.use('/temp', express.static(tempDir));
44
- app.use(express.json());
45
-
46
- app.get("/", (req, res) => {
47
- res.type("json");
48
- const keluaran = {
49
- success: true,
50
- author: "Nex",
51
- data: {
52
- igdl: "/igdl",
53
- twdl: "/twdl"
54
- },
55
- };
56
- res.send(keluaran);
57
- });
58
-
59
- // Fungsi untuk menghasilkan IP acak
60
- const generateRandomIP = () => {
61
- const octet = () => Math.floor(Math.random() * 256);
62
- return `${octet()}.${octet()}.${octet()}.${octet()}`;
63
- };
64
-
65
- // Fungsi untuk upload file
66
- async function uploader(buffer) {
67
- const { ext } = await fileTypeFromBuffer(buffer);
68
- const bodyForm = new FormData();
69
- bodyForm.append('file', buffer, `file.${ext}`);
70
-
71
- const response = await fetch('https://aemt.me/api/upload.php', {
72
- method: 'POST',
73
- body: bodyForm,
74
- });
75
-
76
- return {
77
- status: response.status,
78
- creator: 'Nex',
79
- result: await response.json(),
80
- };
81
- }
82
-
83
- // Fungsi untuk mendapatkan URL thumbnail HD
84
- async function getHDThumbnailUrl(videoId) {
85
- try {
86
- const response = await youtube.videos.list({ part: 'snippet', id: videoId });
87
- return response.data.items[0].snippet.thumbnails.maxres.url;
88
- } catch (error) {
89
- console.error('Error fetching HD thumbnail URL:', error.message);
90
- return null;
91
- }
92
- }
93
-
94
- // Fungsi untuk mendapatkan ID video dari URL
95
- async function GetId(data) {
96
- const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtu(?:be\.com\/(?:watch\?(?:v=|vi=)|v\/|vi\/)|\.be\/|be\.com\/embed\/|be\.com\/shorts\/)|youtube\.com\/\?(?:v=|vi=))([\w-]{11})/;
97
- const res = regex.exec(data);
98
- if (res && res[1]) return res[1];
99
- throw new Error("Please check the URL you have entered");
100
- }
101
-
102
- // Fungsi untuk menambahkan tag ID3 ke file audio
103
- async function addAudioTags(media, title, artist, year, imagecover) {
104
- try {
105
- let audioBuffer;
106
- if (typeof media === 'string') {
107
- const response = await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 });
108
- audioBuffer = Buffer.from(response.data);
109
- } else if (media instanceof Buffer) {
110
- audioBuffer = media;
111
- } else {
112
- throw new Error('Media harus berupa URL string atau Buffer.');
113
- }
114
-
115
- const randomFilename = generateRandomName(10) + '.mp3';
116
- const tmpFilePath = path.join(tempDir, randomFilename);
117
- fs.writeFileSync(tmpFilePath, audioBuffer);
118
-
119
- const tags = { title, artist, year };
120
- if (typeof imagecover === 'string') {
121
- const response = await axios.get(imagecover, { responseType: 'arraybuffer' });
122
- const coverBuffer = Buffer.from(response.data);
123
- tags.image = {
124
- mime: 'image/jpeg',
125
- type: { id: 3, name: 'Front Cover' },
126
- description: 'Cover',
127
- imageBuffer: coverBuffer
128
- };
129
- } else if (imagecover instanceof Buffer) {
130
- tags.image = {
131
- mime: 'image/jpeg',
132
- type: { id: 3, name: 'Front Cover' },
133
- description: 'Cover',
134
- imageBuffer: imagecover
135
- };
136
- }
137
-
138
- const success = nodeID3.write(tags, tmpFilePath);
139
- console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.');
140
-
141
- return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` };
142
- } catch (error) {
143
- console.error('Terjadi kesalahan:', error);
144
- throw new Error('Terjadi kesalahan saat mengubah audio.');
145
- }
146
- }
147
-
148
- // Fungsi untuk menghasilkan nama acak
149
- function generateRandomName(length) {
150
- const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
151
- let randomName = '';
152
- for (let i = 0; i < length; i++) {
153
- randomName += characters.charAt(Math.floor(Math.random() * characters.length));
154
- }
155
- return randomName;
156
- }
157
-
158
- // Fungsi untuk mendapatkan URL audio MP3 dari video YouTube
159
- async function getAudioMP3Url(videoUrl) {
160
- try {
161
- const info = await ytdl.getInfo(videoUrl);
162
- const audioFormat = ytdl.chooseFormat(info.formats, { filter: 'audioonly', quality: 'highestaudio' });
163
- const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3');
164
- let uploadResult;
165
- let convert;
166
-
167
- await new Promise((resolve, reject) => {
168
- ffmpeg()
169
- .input(audioFormat.url)
170
- .outputOptions('-f mp3')
171
- .outputOptions('-acodec libmp3lame')
172
- .outputOptions('-ab 128k')
173
- .outputOptions('-ar 44100')
174
- .on('end', async () => {
175
- try {
176
- const buffer = fs.readFileSync(path_audio);
177
- const id_video = await GetId(videoUrl);
178
- const hd_thumbnail = await getHDThumbnailUrl(id_video);
179
- convert = await addAudioTags(buffer, info.videoDetails.title, info.videoDetails.ownerChannelName, 2024, hd_thumbnail);
180
- const buffer2 = fs.readFileSync(convert.path);
181
-
182
- fs.unlinkSync(path_audio);
183
-
184
- resolve();
185
- } catch (error) {
186
- reject(error);
187
- }
188
- })
189
- .on('error', (err) => {
190
- console.error('FFmpeg conversion error:', err);
191
- reject(err);
192
- })
193
- .save(path_audio);
194
- });
195
-
196
- return {
197
- status: 200,
198
- title: info.videoDetails.title,
199
- result: {
200
- url_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}`,
201
- curl_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}?download=1&filename=${info.videoDetails.title}`,
202
- path: convert.path
203
- }
204
- };
205
- } catch (error) {
206
- console.error('Error:', error);
207
- throw new Error('Failed to process audio URL');
208
- }
209
- }
210
-
211
- // Endpoint untuk mengunduh audio MP3 dari YouTube
212
- app.get('/ytmp3', async (req, res) => {
213
- try {
214
- const { url } = req.query;
215
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
216
-
217
- let result = await getAudioMP3Url(url);
218
- res.json(result);
219
-
220
- // Menghapus file setelah 10 menit
221
- try {
222
- await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
223
- await fss.unlink(result.result.path);
224
- console.log(`File ${result.result.path} deleted.`);
225
- } catch (error) {
226
- console.error(`Error deleting file ${result.result.path}:`, error);
227
- }
228
- } catch (error) {
229
- console.error('Error processing request:', error);
230
- res.status(500).json({
231
- error: 'Failed to process request\n' + error
232
- });
233
- }
234
- });
235
 
236
 
237
- /*
238
- ┏┓┏━┓┏━━━┓┏━┓┏━┓┏━━┓┏┓┏━┓┏┓╋┏┓
239
- ┃┃┃┏┛┃┏━┓┃┃┃┗┛┃┃┗┫┣┛┃┃┃┏┛┃┃╋┃┃
240
- ┃┗┛┛╋┃┃╋┃┃┃┏┓┏┓┃╋┃┃╋┃┗┛┛╋┃┃╋┃┃
241
- ┃┏┓┃╋┃┃╋┃┃┃┃┃┃┃┃╋┃┃╋┃┏┓┃╋┃┃╋┃┃
242
- ┃┃┃┗┓┃┗━┛┃┃┃┃┃┃┃┏┫┣┓┃┃┃┗┓┃┗━┛┃
243
- ┗┛┗━┛┗━━━┛┗┛┗┛┗┛┗━━┛┗┛┗━┛┗━━━┛
244
- */
245
 
246
  function generateRandomID(length = 8) {
247
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
@@ -254,14 +30,18 @@ function generateRandomID(length = 8) {
254
 
255
  async function komiku_download(url) {
256
  const instanceID = generateRandomID();
257
- const tempDir = path.join(tempDirBase, instanceID);
258
  await fss.mkdir(tempDir);
259
 
260
- // Extracting the title from the URL
261
  const title = url.split('/').filter(part => part).pop();
262
 
263
  try {
264
- const response = await axios.get(url);
 
 
 
 
 
265
  const html = response.data;
266
  const $ = cheerio.load(html);
267
  const imgList = [];
@@ -271,11 +51,10 @@ async function komiku_download(url) {
271
  imgList.push({ path: src });
272
  });
273
 
274
- await processImages(imgList, tempDir, instanceID);
275
- const pdfPath = await createPDF(instanceID, tempDir);
276
 
277
- console.log(`PDF berhasil dibuat: ${pdfPath}`);
278
- return { path: pdfPath, title: title, url: `https://${process.env.SPACE_HOST}/temp/${path.basename(pdfPathq)}` };
279
  } catch (error) {
280
  console.log(error);
281
  throw error;
@@ -285,220 +64,65 @@ async function komiku_download(url) {
285
  }
286
 
287
  async function downloadImage(image, tempDir, instanceID) {
288
- const response = await axios.get(image.path, { responseType: 'arraybuffer' });
 
 
 
 
 
 
289
  const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`);
290
  await writeFileAsync(imagePath, response.data);
291
 
292
- const imageHeight = await getImageHeight(imagePath);
293
- const newHeight = Math.floor(imageHeight * 0.7);
294
- const command = `convert ${imagePath} -resize 720x${newHeight}! -quality 75 -background white -gravity center -extent 720x${newHeight} ${imagePath}`;
295
- await execPromise(command);
296
-
297
  return imagePath;
298
  }
299
 
300
- async function getImageHeight(imagePath) {
301
- const { stdout } = await execPromise(`identify -format "%h" ${imagePath}`);
302
- return parseInt(stdout.trim());
303
- }
304
-
305
- async function processImages(imgList, tempDir, instanceID) {
306
- const maxImagesPerPage = 10; // Maksimal 10 gambar per halaman
307
- let partIndex = 0;
308
- let partImages = [];
309
-
310
- for (let i = 0; i < imgList.length; i++) {
311
- const imagePath = await downloadImage(imgList[i], tempDir, instanceID);
312
- partImages.push(imagePath);
313
-
314
- if (partImages.length >= maxImagesPerPage) {
315
- await combineAndSave(partImages, partIndex, tempDir, instanceID);
316
- partImages = [];
317
- partIndex++;
318
- }
319
- }
320
-
321
- // Jika masih ada gambar yang belum diproses
322
- if (partImages.length > 0) {
323
- await combineAndSave(partImages, partIndex, tempDir, instanceID);
324
  }
 
325
  }
326
 
327
- async function combineAndSave(imagePaths, partIndex, tempDir, instanceID) {
328
- const combinedImagePath = path.join(tempDir, `combined_part_${instanceID}_${partIndex}.jpg`);
329
- const command = `convert ${imagePaths.join(' ')} -append -quality 75 ${combinedImagePath}`;
330
- await execPromise(command);
331
 
332
- imagePaths.forEach(fs.unlinkSync);
333
 
334
- return combinedImagePath;
335
- }
336
-
337
- async function createPDF(instanceID, tempDir) {
338
- const combinedParts = fs.readdirSync(tempDir).filter(file => file.startsWith(`combined_part_${instanceID}_`));
339
- const combinedImagesPath = combinedParts.map(file => path.join(tempDir, file)).join(' ');
340
 
341
- const pdfPath = path.join(tempDir, `${instanceID}.pdf`);
342
- const createPDFCommand = `convert ${combinedImagesPath} ${pdfPath}`;
343
- await execPromise(createPDFCommand);
344
 
345
  return pdfPath;
346
  }
347
 
348
- app.get('/komiku/download', async (req, res) => {
349
- try {
350
- const { url } = req.query;
351
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
352
-
353
- let result = await komiku_download(url);
354
- res.json(result);
355
-
356
- // Menghapus file setelah 10 menit
357
- try {
358
- await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes
359
- await fss.unlink(result.path);
360
- console.log(`File ${result.path} deleted.`);
361
- } catch (error) {
362
- console.error(`Error deleting file ${result.path}:`, error);
363
- }
364
- } catch (error) {
365
- console.error('Error processing request:', error);
366
- res.status(500).json({
367
- error: 'Failed to process request\n' + error
368
- });
369
- }
370
- });
371
-
372
- /***********/
373
-
374
- async function getLatestKomik(page) {
375
- const url = `https://api.komiku.id/manga/page/${page}/`;
376
- const headers = {
377
- 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36',
378
- 'Referer': 'https://komiku.id/pustaka/'
379
- };
380
-
381
- try {
382
- const response = await axios.get(url, { headers });
383
- const $ = cheerio.load(response.data);
384
- const mangaArray = [];
385
-
386
- // Scraping data
387
- $('.bge').each((index, element) => {
388
- const title = $(element).find('.kan h3').text().trim();
389
- const link_komik = $(element).find('.bgei a').attr('href');
390
- const imgSrc = $(element).find('.bgei img').attr('src');
391
- const type = $(element).find('.tpe1_inf b').text().trim();
392
- const type2 = $(element).find('.tpe1_inf').text().trim();
393
- const description = $(element).find('.kan p').text().trim();
394
- const readersInfo = $(element).find('.judul2').text().trim();
395
- const latestChapter = "https://komiku.id" + $(element).find('.new1:last-child a').attr('href');
396
-
397
- mangaArray.push({
398
- title,
399
- link_komik,
400
- imgSrc,
401
- type,
402
- type2,
403
- description,
404
- readersInfo,
405
- latestChapter
406
- });
407
- });
408
 
409
- return mangaArray;
410
- } catch (error) {
411
- console.error('Error fetching the URL', error);
412
- throw error;
413
  }
414
- }
415
 
416
- async function GetKomik(url) {
417
  try {
418
- const response = await axios.get(url);
419
- const $ = cheerio.load(response.data);
420
-
421
- const cover = $('#Informasi > div > img').attr('src');
422
- const judul = $('#Informasi > table > tbody > tr:nth-child(1) > td:nth-child(2)').text().trim();
423
- const jenis = $('#Informasi > table > tbody > tr:nth-child(3) > td:nth-child(2) > b').text().trim();
424
- const konsepCerita = $('#Informasi > table > tbody > tr:nth-child(4) > td:nth-child(2)').text().trim();
425
- const author = $('#Informasi > table > tbody > tr:nth-child(5) > td:nth-child(2)').text().trim();
426
- const status = $('#Informasi > table > tbody > tr:nth-child(6) > td:nth-child(2)').text().trim();
427
- const sinopsis = $('#Judul > p.desc').text().trim();
428
-
429
- const genreElements = $('#Informasi > ul > li').map((i, el) => $(el).text().trim()).get();
430
-
431
- const chapterElements = $('#daftarChapter > tr').map((i, el) => {
432
- if (i === 0) {
433
- return null;
434
- }
435
- return {
436
- judulSeries: $(el).find('td.judulseries > a').text().trim(),
437
- tanggalUpdate: $(el).find('td.tanggalseries').text().trim(),
438
- url: "https://komiku.id" + $(el).find('td.judulseries > a').attr('href')
439
- };
440
- }).get().filter(chapter => chapter !== null);
441
-
442
- const mangaInfo = {
443
- cover,
444
- judul,
445
- sinopsis,
446
- jenis,
447
- konsepCerita,
448
- author,
449
- status,
450
- genres: genreElements,
451
- chapters: chapterElements
452
- };
453
-
454
- return mangaInfo;
455
  } catch (error) {
456
- console.error('Error fetching the URL', error);
457
- throw error;
458
  }
459
- }
460
-
461
-
462
- app.get('/komiku/latest', async (req, res) => {
463
- try {
464
- const { page } = req.query;
465
- if (!page) return res.status(400).json({ error: 'Parameter page is required' });
466
-
467
- let result = await getLatestKomik(page);
468
- res.json(result);
469
- } catch (error) {
470
- console.error('Error processing request:', error);
471
- res.status(500).json({
472
- error: 'Failed to process request\n' + error
473
- });
474
- }
475
  });
476
 
477
- app.get('/komiku', async (req, res) => {
478
- try {
479
- const { url } = req.query;
480
- if (!url) return res.status(400).json({ error: 'Parameter url is required' });
481
-
482
- let result = await GetKomik(url);
483
- res.json(result);
484
- } catch (error) {
485
- console.error('Error processing request:', error);
486
- res.status(500).json({
487
- error: 'Failed to process request\n' + error
488
- });
489
- }
490
- });
491
-
492
-
493
- /*******************
494
- ┏┓┏━┓┏━━━┓┏━┓┏━┓┏━━┓┏┓┏━┓┏┓╋┏┓
495
- ┃┃┃┏┛┃┏━┓┃┃┃┗┛┃┃┗┫┣┛┃┃┃┏┛┃┃╋┃┃
496
- ┃┗┛┛╋┃┃╋┃┃┃┏┓┏┓┃╋┃┃╋┃┗┛┛╋┃┃╋┃┃
497
- ┃┏┓┃╋┃┃╋┃┃┃┃┃┃┃┃╋┃┃╋┃┏┓┃╋┃┃╋┃┃
498
- ┃┃┃┗┓┃┗━┛┃┃┃┃┃┃┃┏┫┣┓┃┃┃┗┓┃┗━┛┃
499
- ┗┛┗━┛┗━━━┛┗┛┗┛┗┛┗━━┛┗┛┗━┛┗━━━┛
500
- *********************/
501
-
502
  // Fungsi untuk ping website
503
  async function pingWebsite() {
504
  const browser = await puppeteer.launch({
@@ -507,7 +131,7 @@ async function pingWebsite() {
507
  });
508
  const page = await browser.newPage();
509
  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;]");
510
- await page.goto('https://huggingface.co/spaces/ArashiCode/api');
511
  console.log("Ping");
512
  await browser.close();
513
  }
 
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
+
 
 
 
 
 
10
 
11
  const require = createRequire(import.meta.url);
 
 
 
12
  const puppeteer = require('puppeteer');
13
  import { fileURLToPath } from 'url';
14
  const PORT = process.env.PORT || 7860;
15
  const app = express();
 
 
 
 
 
 
 
 
 
 
 
 
16
  const writeFileAsync = promisify(fs.writeFile);
17
+ const fss = fs.promises;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
 
20
+ app.use('/static', express.static(os.tmpdir()));
 
 
 
 
 
 
 
21
 
22
  function generateRandomID(length = 8) {
23
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 
30
 
31
  async function komiku_download(url) {
32
  const instanceID = generateRandomID();
33
+ const tempDir = path.join(os.tmpdir(), instanceID);
34
  await fss.mkdir(tempDir);
35
 
 
36
  const title = url.split('/').filter(part => part).pop();
37
 
38
  try {
39
+ const response = await axios.get(url, {
40
+ headers: {
41
+ '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;]',
42
+ 'Referer': 'https://komiku.id/'
43
+ }
44
+ });
45
  const html = response.data;
46
  const $ = cheerio.load(html);
47
  const imgList = [];
 
51
  imgList.push({ path: src });
52
  });
53
 
54
+ const imagePaths = await downloadImages(imgList, tempDir, instanceID);
55
+ const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
56
 
57
+ return { path: `/static/${instanceID}.pdf`, title: title };
 
58
  } catch (error) {
59
  console.log(error);
60
  throw error;
 
64
  }
65
 
66
  async function downloadImage(image, tempDir, instanceID) {
67
+ const response = await axios.get(image.path, {
68
+ responseType: 'arraybuffer',
69
+ headers: {
70
+ '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;]',
71
+ 'Referer': 'https://komiku.id/'
72
+ }
73
+ });
74
  const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`);
75
  await writeFileAsync(imagePath, response.data);
76
 
 
 
 
 
 
77
  return imagePath;
78
  }
79
 
80
+ async function downloadImages(imgList, tempDir, instanceID) {
81
+ const imagePaths = [];
82
+ for (const img of imgList) {
83
+ const imagePath = await downloadImage(img, tempDir, instanceID);
84
+ imagePaths.push(imagePath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
+ return imagePaths;
87
  }
88
 
89
+ async function createPDF(imagePaths, instanceID, tempDir) {
90
+ const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
91
+ const doc = new PDFDocument({ autoFirstPage: false });
 
92
 
93
+ doc.pipe(fs.createWriteStream(pdfPath));
94
 
95
+ for (const imagePath of imagePaths) {
96
+ const { width, height } = await getImageDimensions(imagePath);
97
+ doc.addPage({ size: [width, height] });
98
+ doc.image(imagePath, 0, 0, { width: width, height: height });
99
+ }
 
100
 
101
+ doc.end();
 
 
102
 
103
  return pdfPath;
104
  }
105
 
106
+ async function getImageDimensions(imagePath) {
107
+ const sizeOf = promisify(require('image-size'));
108
+ const dimensions = await sizeOf(imagePath);
109
+ return dimensions;
110
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
+ app.get('/download', async (req, res) => {
113
+ const { url } = req.query;
114
+ if (!url) {
115
+ return res.status(400).send('URL is required');
116
  }
 
117
 
 
118
  try {
119
+ const result = await komiku_download(url);
120
+ res.json(result);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  } catch (error) {
122
+ res.status(500).send('Error processing request');
 
123
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  });
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  // Fungsi untuk ping website
127
  async function pingWebsite() {
128
  const browser = await puppeteer.launch({
 
131
  });
132
  const page = await browser.newPage();
133
  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;]");
134
+ await page.goto('https://huggingface.co/spaces/ArashiCode/komik/');
135
  console.log("Ping");
136
  await browser.close();
137
  }