import axios from 'axios'; import * as cheerio from 'cheerio'; import { createRequire } from 'module'; import os from 'os'; import express from 'express'; import { promisify } from 'util'; import { fileTypeFromBuffer } from 'file-type'; import ffmpeg from 'fluent-ffmpeg'; import nodeID3 from 'node-id3'; import ytdl from 'ytdl-core'; import FormData from 'form-data'; import fetch from 'node-fetch'; const require = createRequire(import.meta.url); const fs = require('fs'); const path = require('path'); const { google } = require('googleapis'); const puppeteer = require('puppeteer'); import { fileURLToPath } from 'url'; const PORT = process.env.PORT || 7860; const app = express(); const readFileAsync = promisify(fs.readFile); const tempDir = path.join(os.tmpdir(), "temp"); const fss = fs.promises; const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Membuat direktori sementara jika belum ada (async () => { if (!fs.existsSync(tempDir)) { await fss.mkdir(tempDir, { recursive: true }); } })(); const { exec } = require('child_process'); const writeFileAsync = promisify(fs.writeFile); const execPromise = promisify(exec); const youtube = google.youtube({ version: 'v3', auth: 'AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg' }); const tempDirBase = tempDir const https = require('https'); const agent = new https.Agent({ rejectUnauthorized: false // Nonaktifkan verifikasi sertifikat }); app.use('/temp', express.static(tempDir)); app.use(express.json()); app.use(express.raw({ type: '*/*', limit: '10mb' })); // Untuk menangani buffer dan data binary app.all('/axios/:method/*', async (req, res) => { const { method } = req.params; const targetUrl = decodeURIComponent(req.params[0]); // Menangani URL setelah /:method/ const responseType = req.query.responseType || ''; // Menangani opsi responseType let option = { headers: { ...req.headers, // Menyalin semua header dari permintaan asli 'User-Agent': req.headers['user-agent'] || 'Mozilla/5.0 (Linux; Android 12; SM-S908B Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.58 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/357.0.0.23.115;] WhatsApp/1.2.3', // Menambahkan custom user-agent }, httpsAgent: agent }; if (responseType) { option.responseType = responseType; } try { let response; if (method.toLowerCase() === 'get') { response = await axios.get(targetUrl, option); } else if (method.toLowerCase() === 'post') { option.data = req.body; response = await axios.post(targetUrl, req.body, option); } else { res.status(405).json({ error: 'Method not allowed' }); return; } // Mengambil Content-Type dari header respons const mimeType = response.headers['content-type']; const buffer = Buffer.from(response.data, 'binary'); res.status(response.status); res.set(response.headers); // Set headers dari respons API // Menangani respons berdasarkan Content-Type if (mimeType && (mimeType.includes('text') || mimeType.includes('json') || mimeType.includes('html') || mimeType.includes('plain'))) { // Kirim data sebagai teks res.send(buffer.toString('utf-8')); } else { // Kirim file binary, termasuk PDF res.setHeader('Content-Length', buffer.length); res.send(buffer); } } catch (error) { console.error('Error:', error.response ? error.response.data : error.message); const statusCode = error.response ? error.response.status : 500; const errorMessage = error.response ? error.response.data : error.message; res.status(statusCode).json({ error: errorMessage }); } }); app.get("/", (req, res) => { res.type("json"); const keluaran = { success: true, author: "Nex", data: { igdl: "/igdl", twdl: "/twdl" }, }; res.send(keluaran); }); // Fungsi untuk menghasilkan IP acak const generateRandomIP = () => { const octet = () => Math.floor(Math.random() * 256); return `${octet()}.${octet()}.${octet()}.${octet()}`; }; // Fungsi untuk upload file async function uploader(buffer) { const { ext } = await fileTypeFromBuffer(buffer); const bodyForm = new FormData(); bodyForm.append('file', buffer, `file.${ext}`); const response = await fetch('https://aemt.me/api/upload.php', { method: 'POST', body: bodyForm, }); return { status: response.status, creator: 'Nex', result: await response.json(), }; } // Fungsi untuk mendapatkan URL thumbnail HD async function getHDThumbnailUrl(videoId) { try { const response = await youtube.videos.list({ part: 'snippet', id: videoId }); return response.data.items[0].snippet.thumbnails.maxres.url; } catch (error) { console.error('Error fetching HD thumbnail URL:', error.message); return null; } } const getVideoDetailsWithApi = async (videoId) => { const url = `https://www.googleapis.com/youtube/v3/videos?part=snippet&id=${videoId}&key=AIzaSyBPkpdJEGtAHebbaP3_CcA1_urfMFfeLLg`; try { const response = await axios.get(url); const video = response.data.items[0]; const title = video.snippet.title; const description = video.snippet.description; const thumbnail = video.snippet.thumbnails.high.url; const channelTitle = video.snippet.channelTitle; const publishedAt = video.snippet.publishedAt; const tags = video.snippet.tags; const videoDetails = { title: title, description: description, thumbnail: thumbnail, channelTitle: channelTitle, publishedAt: publishedAt, tags: tags, }; return videoDetails } catch (error) { console.error('An error occurred:', error); } }; // Fungsi untuk mendapatkan ID video dari URL async function GetId(data) { 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})/; const res = regex.exec(data); if (res && res[1]) return res[1]; throw new Error("Please check the URL you have entered"); } // Fungsi untuk menambahkan tag ID3 ke file audio async function addAudioTags(media, title, artist, year, imagecover) { try { let audioBuffer; if (typeof media === 'string') { const response = await axios.get(media, { responseType: 'arraybuffer', maxContentLength: -1 }); audioBuffer = Buffer.from(response.data); } else if (media instanceof Buffer) { audioBuffer = media; } else { throw new Error('Media harus berupa URL string atau Buffer.'); } const randomFilename = generateRandomName(10) + '.mp3'; const tmpFilePath = path.join(tempDir, randomFilename); fs.writeFileSync(tmpFilePath, audioBuffer); const tags = { title, artist, year }; if (typeof imagecover === 'string') { const response = await axios.get(imagecover, { responseType: 'arraybuffer' }); const coverBuffer = Buffer.from(response.data); tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: coverBuffer }; } else if (imagecover instanceof Buffer) { tags.image = { mime: 'image/jpeg', type: { id: 3, name: 'Front Cover' }, description: 'Cover', imageBuffer: imagecover }; } const success = nodeID3.write(tags, tmpFilePath); console[success ? 'log' : 'error'](success ? 'Tag ID3 berhasil diubah!' : 'Gagal mengubah tag ID3.'); return { msg: `Audio berhasil diubah.`, path: `${tmpFilePath}` }; } catch (error) { console.error('Terjadi kesalahan:', error); throw new Error('Terjadi kesalahan saat mengubah audio.'); } } // Fungsi untuk menghasilkan nama acak function generateRandomName(length) { const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let randomName = ''; for (let i = 0; i < length; i++) { randomName += characters.charAt(Math.floor(Math.random() * characters.length)); } return randomName; } async function fetchCobaltOnly(url, opts = {}) { try { const response = await axios.post('https://cobalt-7.kwiatekmiki.com/api/json', { url, ...opts }, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } } ); return response.data; } catch (error) { if (error.response) { const contentType = error.response.headers['content-type']; if (contentType && contentType.includes('json')) { throw error.response.data.message || 'An error occurred'; } throw error.response.statusText; } throw error.message; } } const servers = [ "https://co.eepy.today/", "https://cdn1.meow.gs/", "https://cdn2.meow.gs/", "https://cdn3.meow.gs/", "https://cdn4.meow.gs/", "https://cdn5.meow.gs/", ]; async function cobalt(config) { try { if (!(typeof config === "object")) { throw new Error("Invalid config input, config must be a JSON object!"); } config = { url: config?.url || null, videoQuality: config?.videoQuality || "720", audioFormat: config?.audioFormat || "mp3", audioBitrate: config?.audioBitrate || "128", filenameStyle: config?.filenameStyle || "classic", downloadMode: config?.downloadMode || "auto", youtubeVideoCodec: config?.youtubeVideoCodec || "h264", youtubeDubLang: config?.youtubeDubLang || "en", alwaysProxy: config?.alwaysProxy || false, disableMetadata: config?.disableMetadata || false, tiktokFullAudio: config?.tiktokFullAudio || true, tiktokH265: config?.tiktokH265 || true, twitterGif: config?.twitterGif || true, youtubeHLS: config?.youtubeHLS || false, }; if (!config.url) { throw new Error("Missing URL input!"); } for (let i = 0; i < servers.length; i++) { try { console.log(`Trying server: ${servers[i]}`); // Log server yang dicoba const response = await axios.post(servers[i], config, { headers: { accept: "application/json", contentType: "application/json", }, }); const data = response.data; if (data.status === "error") { throw new Error("Failed to fetch content from server."); } console.log(`Success with server: ${servers[i]}`); // Log server sukses return { success: true, result: data, }; } catch (error) { if (i === servers.length - 1) { // Jika sudah mencoba semua server throw error; } console.warn(`Server ${servers[i]} failed. Trying next server...`); // Log server gagal } } } catch (error) { return { success: false, errors: error.message || error, }; } } // Fungsi untuk mendapatkan URL audio MP3 dari video YouTube async function getAudioMP3Url(videoUrl) { try { /*------------------ const requestData = {"url":videoUrl,"vQuality":"360","filenamePattern":"pretty","isAudioOnly":"true"} const config = { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36', 'Referer': 'https://cobalt.tools/' } }; */ let obj = { url: videoUrl } const video = await fetchCobaltOnly(obj.url, { isAudioOnly: 'audio', vQuality: 'max' }) const path_audio = path.join(tempDir, generateRandomName(10) + '.mp3'); const id_video = await GetId(videoUrl); const infoVids = await getVideoDetailsWithApi(id_video); let uploadResult; let convert; await new Promise((resolve, reject) => { ffmpeg() .input(video.url) .outputOptions('-f mp3') .outputOptions('-acodec libmp3lame') .outputOptions('-ab 128k') .outputOptions('-ar 44100') .on('end', async () => { try { const buffer = fs.readFileSync(path_audio); convert = await addAudioTags(buffer, infoVids.title, infoVids.channelTitle, 2024, infoVids.thumbnail); const buffer2 = fs.readFileSync(convert.path); fs.unlinkSync(path_audio); resolve(); } catch (error) { reject(error); } }) .on('error', (err) => { console.error('FFmpeg conversion error:', err); reject(err); }) .save(path_audio); }); return { status: 200, title: infoVids.title, result: { url_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}`, curl_path: `https://${process.env.SPACE_HOST}/temp/${path.basename(convert.path)}?download=1&filename=${infoVids.title}`, path: convert.path }, infoVids }; } catch (error) { console.error('Error:', error); throw new Error('Failed to process audio URL'); } } // Endpoint untuk mengunduh audio MP3 dari YouTube app.get('/ytmp3', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await getAudioMP3Url(url); res.json(result); // Menghapus file setelah 10 menit try { await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes await fss.unlink(result.result.path); console.log(`File ${result.result.path} deleted.`); } catch (error) { console.error(`Error deleting file ${result.result.path}:`, error); } } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); async function fetchHtml(url) { // Launch browser dengan mode headless const browser = await puppeteer.launch(); // Buat page baru const page = await browser.newPage(); // Set User Agent untuk menghindari deteksi bot //await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.3'); 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;]"); // Navigasi ke URL yang diinginkan //await page.goto(url); await page.goto(url, { waitUntil: 'networkidle2' }); // Tunggu sampai page selesai loading //await page.waitForNavigation({ waitUntil: 'networkidle2' }); // Ambil HTML dari page const html = await page.content(); // Tutup browser await browser.close(); // Return HTML return html; } app.get('/html', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await fetchHtml(url); res.send(result); } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); async function XnDl(url) { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'], timeout: 60000 // Timeout untuk peluncuran browser }); try { const page = await browser.newPage(); 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;]"); await page.goto(url.replace("xnxx.com", "xnxxvideodownload.com"), { waitUntil: 'domcontentloaded', timeout: 60000 // Timeout untuk navigasi }); await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 60000 // Timeout untuk menunggu navigasi selesai }); const data = await page.evaluate(() => { const title = document.querySelector("body > main > section.e.j.d2.dsection > h2")?.textContent || ''; const thumbnail = document.querySelector("body > main > section.e.j.d2.dsection > div > div.thumbdiv > img")?.src || ''; const url = document.querySelector("body > main > section.e.j.d2.dsection > div > div.thumbdiv > a")?.href || ''; const table = document.getElementById('dtable')?.getElementsByTagName('table')[0]; const videoDownload = []; if (table) { for (let i = 0; i < table.rows.length; i++) { const row = table.rows[i]; const rowData = { quality: row.cells[0]?.innerText || '', ext: row.cells[1]?.innerText || '', url: row.cells[2]?.getElementsByTagName('a')[0]?.href || '' }; videoDownload.push(rowData); } } return { title, thumbnail, url, videoDownload }; }); return data; } catch (error) { console.error('Error:', error); return null; } finally { await browser.close(); } } app.get('/xnxx', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await XnDl(url); res.send(result); } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); /* ┏┓┏━┓┏━━━┓┏━┓┏━┓┏━━┓┏┓┏━┓┏┓╋┏┓ ┃┃┃┏┛┃┏━┓┃┃┃┗┛┃┃┗┫┣┛┃┃┃┏┛┃┃╋┃┃ ┃┗┛┛╋┃┃╋┃┃┃┏┓┏┓┃╋┃┃╋┃┗┛┛╋┃┃╋┃┃ ┃┏┓┃╋┃┃╋┃┃┃┃┃┃┃┃╋┃┃╋┃┏┓┃╋┃┃╋┃┃ ┃┃┃┗┓┃┗━┛┃┃┃┃┃┃┃┏┫┣┓┃┃┃┗┓┃┗━┛┃ ┗┛┗━┛┗━━━┛┗┛┗┛┗┛┗━━┛┗┛┗━┛┗━━━┛ */ function generateRandomID(length = 8) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * characters.length)); } return result; } async function komiku_download(url) { const instanceID = generateRandomID(); const tempDir = path.join(tempDirBase, instanceID); await fss.mkdir(tempDir); // Extracting the title from the URL const title = url.split('/').filter(part => part).pop(); try { const response = await axios.get(url); const html = response.data; const $ = cheerio.load(html); const imgList = []; $('#Baca_Komik img').each((index, element) => { const src = $(element).attr('src'); imgList.push({ path: src }); }); await processImages(imgList, tempDir, instanceID); const pdfPath = await createPDF(instanceID, tempDir); console.log(`PDF berhasil dibuat: ${pdfPath}`); return { path: pdfPath, title: title, url: `https://${process.env.SPACE_HOST}/temp/${path.basename(pdfPathq)}` }; } catch (error) { console.log(error); throw error; } finally { await fss.rmdir(tempDir, { recursive: true }); } } async function downloadImage(image, tempDir, instanceID) { const response = await axios.get(image.path, { responseType: 'arraybuffer' }); const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`); await writeFileAsync(imagePath, response.data); const imageHeight = await getImageHeight(imagePath); const newHeight = Math.floor(imageHeight * 0.7); const command = `convert ${imagePath} -resize 720x${newHeight}! -quality 75 -background white -gravity center -extent 720x${newHeight} ${imagePath}`; await execPromise(command); return imagePath; } async function getImageHeight(imagePath) { const { stdout } = await execPromise(`identify -format "%h" ${imagePath}`); return parseInt(stdout.trim()); } async function processImages(imgList, tempDir, instanceID) { const maxImagesPerPage = 10; // Maksimal 10 gambar per halaman let partIndex = 0; let partImages = []; for (let i = 0; i < imgList.length; i++) { const imagePath = await downloadImage(imgList[i], tempDir, instanceID); partImages.push(imagePath); if (partImages.length >= maxImagesPerPage) { await combineAndSave(partImages, partIndex, tempDir, instanceID); partImages = []; partIndex++; } } // Jika masih ada gambar yang belum diproses if (partImages.length > 0) { await combineAndSave(partImages, partIndex, tempDir, instanceID); } } async function combineAndSave(imagePaths, partIndex, tempDir, instanceID) { const combinedImagePath = path.join(tempDir, `combined_part_${instanceID}_${partIndex}.jpg`); const command = `convert ${imagePaths.join(' ')} -append -quality 75 ${combinedImagePath}`; await execPromise(command); imagePaths.forEach(fs.unlinkSync); return combinedImagePath; } async function createPDF(instanceID, tempDir) { const combinedParts = fs.readdirSync(tempDir).filter(file => file.startsWith(`combined_part_${instanceID}_`)); const combinedImagesPath = combinedParts.map(file => path.join(tempDir, file)).join(' '); const pdfPath = path.join(tempDir, `${instanceID}.pdf`); const createPDFCommand = `convert ${combinedImagesPath} ${pdfPath}`; await execPromise(createPDFCommand); return pdfPath; } app.get('/komiku/download', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await komiku_download(url); res.json(result); // Menghapus file setelah 10 menit try { await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes await fss.unlink(result.path); console.log(`File ${result.path} deleted.`); } catch (error) { console.error(`Error deleting file ${result.path}:`, error); } } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); /* V2 V2 V2 V2 */ async function komiku_downloadV2(url) { const instanceID = generateRandomID(); const tempDir = path.join(tempDirBase, instanceID); await fss.mkdir(tempDir); // Extracting the title from the URL const title = url.split('/').filter(part => part).pop(); let browser; try { browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); await page.goto(url, { waitUntil: 'networkidle2' }); // Extracting images from the page const imgList = await page.evaluate(() => { return Array.from(document.querySelectorAll('#Baca_Komik img')).map(img => img.src); }); const images = imgList.map(src => ({ path: src })); await processImagesV2(images, tempDir, instanceID); const pdfPath = await createPDFV2(instanceID, tempDir); console.log(`PDF berhasil dibuat: ${pdfPath}`); return { path: pdfPath, title: title, url: `https://${process.env.SPACE_HOST}/temp/${path.basename(pdfPath)}` }; } catch (error) { console.log(error); throw error; } finally { if (browser) { await browser.close(); } await fss.rmdir(tempDir, { recursive: true }); } } async function downloadImageV2(image, tempDir, instanceID) { const response = await puppeteer.download(image.path, { responseType: 'arraybuffer' }); const imagePath = path.join(tempDir, `image_${instanceID}_${Date.now()}_${Math.floor(Math.random() * 1000)}.jpg`); await writeFileAsync(imagePath, response); const imageHeight = await getImageHeightV2(imagePath); const newHeight = Math.floor(imageHeight * 0.7); const command = `convert ${imagePath} -resize 720x${newHeight}! -quality 75 -background white -gravity center -extent 720x${newHeight} ${imagePath}`; await execPromise(command); return imagePath; } async function getImageHeightV2(imagePath) { const { stdout } = await execPromise(`identify -format "%h" ${imagePath}`); return parseInt(stdout.trim()); } async function processImagesV2(imgList, tempDir, instanceID) { const maxImagesPerPage = 10; // Maksimal 10 gambar per halaman let partIndex = 0; let partImages = []; for (let i = 0; i < imgList.length; i++) { const imagePath = await downloadImageV2(imgList[i], tempDir, instanceID); partImages.push(imagePath); if (partImages.length >= maxImagesPerPage) { await combineAndSaveV2(partImages, partIndex, tempDir, instanceID); partImages = []; partIndex++; } } // Jika masih ada gambar yang belum diproses if (partImages.length > 0) { await combineAndSaveV2(partImages, partIndex, tempDir, instanceID); } } async function combineAndSaveV2(imagePaths, partIndex, tempDir, instanceID) { const combinedImagePath = path.join(tempDir, `combined_part_${instanceID}_${partIndex}.jpg`); const command = `convert ${imagePaths.join(' ')} -append -quality 75 ${combinedImagePath}`; await execPromise(command); imagePaths.forEach(fs.unlinkSync); return combinedImagePath; } async function createPDFV2(instanceID, tempDir) { const combinedParts = fs.readdirSync(tempDir).filter(file => file.startsWith(`combined_part_${instanceID}_`)); const combinedImagesPath = combinedParts.map(file => path.join(tempDir, file)).join(' '); const pdfPath = path.join(tempDir, `${instanceID}.pdf`); const createPDFCommand = `convert ${combinedImagesPath} ${pdfPath}`; await execPromise(createPDFCommand); return pdfPath; } app.get('/komiku/downloadV2', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await komiku_downloadV2(url); res.json(result); // Menghapus file setelah 10 menit try { await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000)); // 10 minutes await fss.unlink(result.path); console.log(`File ${result.path} deleted.`); } catch (error) { console.error(`Error deleting file ${result.path}:`, error); } } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); /***********/ async function getLatestKomik(page) { const url = `https://api.komiku.id/manga/page/${page}/`; const headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36', 'Referer': 'https://komiku.id/pustaka/' }; try { const response = await axios.get(url, { headers }); const $ = cheerio.load(response.data); const mangaArray = []; // Scraping data $('.bge').each((index, element) => { const title = $(element).find('.kan h3').text().trim(); const link_komik = $(element).find('.bgei a').attr('href'); const imgSrc = $(element).find('.bgei img').attr('src'); const type = $(element).find('.tpe1_inf b').text().trim(); const type2 = $(element).find('.tpe1_inf').text().trim(); const description = $(element).find('.kan p').text().trim(); const readersInfo = $(element).find('.judul2').text().trim(); const latestChapter = "https://komiku.id" + $(element).find('.new1:last-child a').attr('href'); mangaArray.push({ title, link_komik, imgSrc, type, type2, description, readersInfo, latestChapter }); }); return mangaArray; } catch (error) { console.error('Error fetching the URL', error); throw error; } } async function GetKomik(url) { try { const response = await axios.get(url); const $ = cheerio.load(response.data); const cover = $('#Informasi > div > img').attr('src'); const judul = $('#Informasi > table > tbody > tr:nth-child(1) > td:nth-child(2)').text().trim(); const jenis = $('#Informasi > table > tbody > tr:nth-child(3) > td:nth-child(2) > b').text().trim(); const konsepCerita = $('#Informasi > table > tbody > tr:nth-child(4) > td:nth-child(2)').text().trim(); const author = $('#Informasi > table > tbody > tr:nth-child(5) > td:nth-child(2)').text().trim(); const status = $('#Informasi > table > tbody > tr:nth-child(6) > td:nth-child(2)').text().trim(); const sinopsis = $('#Judul > p.desc').text().trim(); const genreElements = $('#Informasi > ul > li').map((i, el) => $(el).text().trim()).get(); const chapterElements = $('#daftarChapter > tr').map((i, el) => { if (i === 0) { return null; } return { judulSeries: $(el).find('td.judulseries > a').text().trim(), tanggalUpdate: $(el).find('td.tanggalseries').text().trim(), url: "https://komiku.id" + $(el).find('td.judulseries > a').attr('href') }; }).get().filter(chapter => chapter !== null); const mangaInfo = { cover, judul, sinopsis, jenis, konsepCerita, author, status, genres: genreElements, chapters: chapterElements }; return mangaInfo; } catch (error) { console.error('Error fetching the URL', error); throw error; } } app.get('/komiku/latest', async (req, res) => { try { const { page } = req.query; if (!page) return res.status(400).json({ error: 'Parameter page is required' }); let result = await getLatestKomik(page); res.json(result); } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); app.get('/komiku', async (req, res) => { try { const { url } = req.query; if (!url) return res.status(400).json({ error: 'Parameter url is required' }); let result = await GetKomik(url); res.json(result); } catch (error) { console.error('Error processing request:', error); res.status(500).json({ error: 'Failed to process request\n' + error }); } }); app.post("/cobalt", async (req, res) => { const config = req.body; try { if (!config.url) { return res.status(400).json({ success: false, message: "Missing 'url' in the request body.", }); } const result = await cobalt(config); if (result.success) { return res.status(200).json(result); } else { return res.status(500).json({ success: false, message: "Failed to process the request.", errors: result, }); } } catch (error) { res.status(500).json({ success: false, message: "Internal server error.", errors: error || error.message, }); } }); /******************* ┏┓┏━┓┏━━━┓┏━┓┏━┓┏━━┓┏┓┏━┓┏┓╋┏┓ ┃┃┃┏┛┃┏━┓┃┃┃┗┛┃┃┗┫┣┛┃┃┃┏┛┃┃╋┃┃ ┃┗┛┛╋┃┃╋┃┃┃┏┓┏┓┃╋┃┃╋┃┗┛┛╋┃┃╋┃┃ ┃┏┓┃╋┃┃╋┃┃┃┃┃┃┃┃╋┃┃╋┃┏┓┃╋┃┃╋┃┃ ┃┃┃┗┓┃┗━┛┃┃┃┃┃┃┃┏┫┣┓┃┃┃┗┓┃┗━┛┃ ┗┛┗━┛┗━━━┛┗┛┗┛┗┛┗━━┛┗┛┗━┛┗━━━┛ *********************/ // Fungsi untuk ping website async function pingWebsite() { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); 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;]"); await page.goto('https://huggingface.co/spaces/ArashiCode/api'); console.log("Ping"); await browser.close(); } // Ping website setiap 5 jam async function pingEvery5Hours() { await pingWebsite(); setInterval(async () => { await pingWebsite(); }, 5 * 60 * 60 * 1000); // 5 hours in milliseconds } // Mulai ping pingEvery5Hours(); app.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });