Spaces:
Running
Running
import axios from 'axios'; | |
import 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; | |
} | |
// 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/' } }; | |
const { data: video } = await axios.post('https://api.cobalt.tools/api/json', requestData, config); | |
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 | |
}); | |
} | |
}); | |
/* | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββ«β£βββββββββββ | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββ«β£βββββββββββ | |
ββββββββββββββββββββββββββββββ | |
*/ | |
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 | |
}); | |
} | |
}); | |
/******************* | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββ«β£βββββββββββ | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββββββββββββββ | |
ββββββββββββββββββ«β£βββββββββββ | |
ββββββββββββββββββββββββββββββ | |
*********************/ | |
// 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}`); | |
}); |