import { createRequire } from 'module';
import { fileURLToPath } from 'url';
import path from 'path';
import PDFDocument from 'pdfkit';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const require = createRequire(import.meta.url);
const { promisify } = require('util');
const express = require('express');
const axios = require('axios');
const cheerio = require('cheerio');
const fs = require('fs');
const { tmpdir } = require('os');
const { join } = require('path');
const nodeID3 = require('node-id3');
const puppeteer = require('puppeteer');
const app = express();
const PORT = 7860;
const { format } = require("util");
const os = require("os");
const writeFileAsync = promisify(fs.writeFile);
const fss = fs.promises;
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(os.tmpdir(), 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 });
});
const imagePaths = await downloadImages(imgList, tempDir, instanceID);
const pdfPath = await createPDF(imagePaths, instanceID, tempDir);
console.log(`PDF berhasil dibuat: ${pdfPath}`);
return { path: pdfPath, title: title };
} 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);
return imagePath;
}
async function downloadImages(imgList, tempDir, instanceID) {
const imagePaths = [];
for (const img of imgList) {
const imagePath = await downloadImage(img, tempDir, instanceID);
imagePaths.push(imagePath);
}
return imagePaths;
}
async function createPDF(imagePaths, instanceID, tempDir) {
const pdfPath = path.join(os.tmpdir(), `${instanceID}.pdf`);
const doc = new PDFDocument({ autoFirstPage: false });
doc.pipe(fs.createWriteStream(pdfPath));
for (const imagePath of imagePaths) {
const { width, height } = await getImageDimensions(imagePath);
doc.addPage({ size: [width, height] });
doc.image(imagePath, 0, 0, { width: width, height: height });
}
doc.end();
return pdfPath;
}
async function getImageDimensions(imagePath) {
const { promisify } = require('util');
const sizeOf = promisify(require('image-size'));
const dimensions = await sizeOf(imagePath);
return dimensions;
}
app.get('/komikudl', async (req, res) => {
const url = req.query.url;
if (!url) {
return res.status(400).send('URL is required');
}
try {
const data = await komiku_download(url);
res.download(data.path, `${data.title}.pdf`, (err) => {
if (err) {
console.error(err);
}
fs.unlinkSync(data.path); // Remove the file after sending it
});
} catch (error) {
res.status(500).send('An error occurred while generating the PDF');
}
});
app.get('/add', async (req, res) => {
try {
const { url, title, artist, year, imgUrl } = req.query;
// Ambil file audio dari URL
const response = await axios.get(url, {
responseType: 'arraybuffer'
});
// Simpan file audio ke dalam buffer
const audioBuffer = Buffer.from(response.data);
// Buat nama file yang acak
const randomFilename = Math.random().toString(36).substring(7) + '.mp3';
// Path untuk menyimpan file sementara
const tmpFilePath = join(tmpdir(), randomFilename);
// Simpan file audio ke dalam sistem file sementara
fs.writeFileSync(tmpFilePath, audioBuffer);
// Buat objek tag ID3
const tags = {
title: title,
artist: artist,
year: year
// Anda juga dapat menambahkan gambar album (cover) jika diperlukan
};
// Jika ada URL untuk cover, ambil gambarnya dan tambahkan ke dalam tag ID3
if (imgUrl) {
const coverResponse = await axios.get(imgUrl, {
responseType: 'arraybuffer'
});
const coverBuffer = Buffer.from(coverResponse.data);
tags.image = {
mime: 'image/jpeg', // Sesuaikan dengan tipe mime gambar
type: {
id: 3, // Jenis gambar (3 untuk cover album)
name: 'Front Cover'
},
description: 'Cover', // Deskripsi (opsional)
imageBuffer: coverBuffer
};
}
// Ubah tag ID3 dari file audio
const success = nodeID3.write(tags, tmpFilePath);
if (success) {
console.log('Tag ID3 berhasil diubah!');
} else {
console.error('Gagal mengubah tag ID3.');
}
// Kirim link download audio yang sudah diubah
const downloadLink = `https://${process.env.SPACE_HOST}/download/${randomFilename}`;
res.json({ msg: `Audio berhasil diubah.`, link: downloadLink });
} catch (error) {
console.error('Terjadi kesalahan:', error);
res.status(500).send('Terjadi kesalahan saat mengubah audio.');
}
});
async function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Route untuk mendownload audio yang sudah diubah
app.get('/download/:filename', async (req, res) => {
const { filename } = req.params;
const filePath = join(tmpdir(), filename);
res.download(filePath, () => {
// Hapus file setelah berhasil didownload
fs.unlinkSync(filePath);
});
});
const startTime = new Date();
// Fungsi untuk menghitung waktu berjalan dalam format yang diinginkan
function waktuBerjalan() {
const sekarang = new Date();
const selisih = sekarang.getTime() - startTime.getTime();
const hari = Math.floor(selisih / (1000 * 60 * 60 * 24));
const jam = Math.floor((selisih % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const menit = Math.floor((selisih % (1000 * 60 * 60)) / (1000 * 60));
const detik = Math.floor((selisih % (1000 * 60)) / 1000);
if (hari > 0) {
return `${hari} hari ${jam} jam ${menit} menit ${detik} detik`;
} else if (jam > 0) {
return `${jam} jam ${menit} menit ${detik} detik`;
} else if (menit > 0) {
return `${menit} menit ${detik} detik`;
} else {
return `${detik} detik`;
}
}
app.get('/ping', (req, res) => {
res.send('Server is up and running!' + waktuBerjalan());
});
const pingServer = async () => {
try {
const pingResponse = await axios.get(`https://${process.env.SPACE_HOST}` + '/ping');
console.log('Server pinged at:', new Date().toLocaleTimeString());
} catch (error) {
console.error('Failed to ping server:', error.message);
}
};
/*other api*/
async function searchResepPuppeter(query, hal) {
let pages = "https://cookpad.com/id/cari/" + query + "?event=search.typed_query"
if(hal > 1) {
pages += "&page=" + hal;
}
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.setExtraHTTPHeaders({
'Referer': pages
});
await page.goto(pages);
const baseUrl = page.url();
let jason = {
list: [],
next_page: false
};
const liHtmlArray = jason.list;
const ulElement = await page.$("#main_contents > div.lg\\:flex.lg\\:items-start > div.relative.lg\\:w-3\\/5 > ul");
if (ulElement) {
const listItemsWithId = await ulElement.$$("li[id]");
for (const li of listItemsWithId) {
const linkElement = await li.$("div.flex-auto.m-sm > div > div.flex.justify-between > h2 > a");
const imageElement = await li.$("div.flex-none.w-20.xs\\:w-auto.h-auto > picture > img");
const authorElement = await li.$("div.flex-auto.m-sm > div > div.border-t.border-dashed.border-cookpad-gray-400.pt-sm.mt-auto > div > span.break-all.clamp-1 > span");
const li_url = await (await linkElement.getProperty('href')).jsonValue();
const li_text = await (await linkElement.getProperty('innerText')).jsonValue();
const li_img = await (await imageElement.getProperty('src')).jsonValue();
const li_author = await (await authorElement.getProperty('innerText')).jsonValue();
let anu = {
url: li_url,
title: li_text,
thumbnail: li_img,
author: li_author
};
liHtmlArray.push(anu);
}
} else {
console.error("Element
tidak ditemukan.");
}
jason.title = await page.$eval("#search-recipes-header > div > h1", element => element.innerText);
const nextPageElement = await page.$("#main_contents > div.lg\\:flex.lg\\:items-start > div.relative.lg\\:w-3\\/5 > div.pagination.my-lg > a:nth-child(9)");
if (nextPageElement) {
const nextPageHref = await (await nextPageElement.getProperty('href')).jsonValue();
jason.next_page = nextPageHref;
} else {
const nextPageElementAlt = await page.$("#main_contents > div.lg\\:flex.lg\\:items-start > div.relative.lg\\:w-3\\/5 > div.pagination.my-lg > a");
if (nextPageElementAlt) {
const nextPageHrefAlt = await (await nextPageElementAlt.getProperty('href')).jsonValue();
jason.next_page = nextPageHrefAlt;
} else {
jason.next_page = false;
}
}
await browser.close();
return jason;
}
async function getRecipeData(url) {
try {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// Atur user agent sebagai perangkat Android
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);
// Tunggu hingga elemen thumbnail muncul di DOM
await page.waitForSelector("#recipe_image > a > div > picture > img");
const title = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > div > h1").innerText.trim());
const author = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > div > a > div > div.clamp-1 > span.text-cookpad-14.text-cookpad-gray-700.font-semibold").innerText);
const authorId = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > div > a > div > div.clamp-1 > span.text-cookpad-12.text-cookpad-gray-600").innerText);
const authorProfileLink = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > div > a").href);
const messageFromAuthor = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > meta:nth-child(3)").content || "");
const linkPage = await page.evaluate(() => document.querySelector("#recipe > div > div.md\\:w-2\\/3.flex-shrink-0 > link").href);
const thumbnail = await page.$eval("#recipe_image > a > div > picture > img", img => img.src)
.catch(() => "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQIchzBjMg4dcOYFswOtv5c1NUOutP5fRGviA&usqp=CAU");
const ingredientsList = await page.$$eval("#ingredients > div.ingredient-list > ol > li[id]", lis => lis.map(li => li.innerText));
const stepsList = await page.$$eval("#steps > ol > li[id]", lis => {
return lis.map(li => {
const stepText = li.querySelector("div:nth-child(2) > p").innerText;
let stepImage = null;
const imageAnchor = li.querySelector("div.-mx-rg.px-rg.flex.space-x-sm.mb-sm.overflow-auto.scroll-bar-hidden > a:nth-child(1)");
if (imageAnchor) {
stepImage = imageAnchor.querySelector("picture > img").src;
}
return {
text: stepText,
image: stepImage
};
});
});
await browser.close();
const recipeData = {
title: title,
author: author,
authorId: authorId,
authorProfileLink: authorProfileLink,
messageFromAuthor: messageFromAuthor,
linkPage: linkPage,
thumb: thumbnail,
ingredients: ingredientsList,
steps: stepsList
};
return recipeData;
} catch (error) {
console.error("Error:", error);
return null;
}
}
app.get('/cookpad', async (req, res) => {
try {
const query = req.query.query;
const page = req.query.page || 1; // Jika parameter page tidak ada, atur nilainya menjadi 1 secara default
const resep_search = await searchResepPuppeter(query, page);
res.json(resep_search);
} catch (e) {
console.error(e);
res.status(500).json({ error: 'Internal Server Error \n' + e});
}
});
app.get('/get-cookpad', async (req, res) => {
try {
const url = req.query.url;
const recipeData = await getRecipeData(url);
res.json(recipeData);
} catch (e) {
console.error(e);
res.status(500).json({ error: 'Internal Server Error \n' + e });
}
});
app.get('/eval', async (req, res) => {
try {
const text_input = req.query.cmd;
let evalCmd = "";
try {
evalCmd = /await/i.test(text_input) ? await eval("(async() => { " + text_input + " })()") : eval(text_input);
} catch (e) {
evalCmd = e;
}
new Promise(async (resolve, reject) => {
try {
resolve(evalCmd);
} catch (err) {
reject(err);
}
})
.then((result) => {
res.send(format(result));
})
.catch((err) => {
res.send(format(err));
});
} catch (e) {
console.error(e);
res.status(500).json({ error: 'Internal Server Error \n' + e });
}
});
async function waitForElementOrClose(page, selector, maxTries = 15) {
for (let i = 0; i < maxTries; i++) {
try {
await page.waitForSelector(selector); // Menunggu elemen tanpa batasan waktu tambahan
console.log(`Element '${selector}' found.`);
return true; // Mengembalikan true jika elemen ditemukan
} catch (error) {
console.log(`Element '${selector}' not found. Retrying...`);
if (i === maxTries - 1) {
console.log(`Max retries reached. Closing the browser.`);
return false; // Mengembalikan false jika elemen tidak ditemukan dalam jumlah percobaan maksimum
}
}
}
}
app.get('/r34', async (req, res) => {
try {
const url = req.query.url;
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.setExtraHTTPHeaders({
'Referer': 'https://www.pornloaders.com/rule34video-download/'
});
// Navigate to the page
await page.goto('https://www.pornloaders.com/rule34video-download/');
await page.type('#__next > main > div > div.DownloadPage_Hero__hoO8_ > form > div > input', url);
// Click the submit button
await page.click('#__next > main > div > div.DownloadPage_Hero__hoO8_ > form > div > button');
const elementFound = await waitForElementOrClose(page, '#__next > main > div > div.DownloadPage_Hero__hoO8_ > div.DownloadPage_Loading__Yp4ut > div > a');
if (elementFound) {
const href = await page.evaluate(() => {
const element = document.querySelector('#__next > main > div > div.DownloadPage_Hero__hoO8_ > div.DownloadPage_Loading__Yp4ut > div > a');
return element ? element.href : null; // Memeriksa apakah elemen ditemukan sebelum mengambil atribut href
});
if (href) {
res.json({url: href});
} else {
res.status(404).json({ error: 'Element not found or href attribute is missing.' });
}
await browser.close();
}
} catch (e) {
console.error(e);
res.status(500).json({
error: 'Internal Server Error \n' + e
});
}
});
app.get('/r34/v2', async (req, res) => {
try {
const url = req.query.url;
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.setExtraHTTPHeaders({
'Referer': 'https://pastedownload.com/rule34video-video-downloader/'
});
// Navigate to the page
await page.goto('https://pastedownload.com/rule34video-video-downloader/');
await page.type('#url', url);
// Click the submit button
await page.click('#send > div');
const elementFound = await waitForElementOrClose(page, '#links > div.col-md-4 > div.video-details > img');
if (elementFound) {
const href = await page.evaluate(() => {
const url1 = document.querySelector("#links > div.col-md-8.video-links > div:nth-child(2) > a").href;
const url2 = document.querySelector("#links > div.col-md-8.video-links > div:nth-child(3) > a").href;
const url3 = document.querySelector("#links > div.col-md-8.video-links > div:nth-child(4) > a").href;
return [url1,url2,url3];
});
if (href) {
res.json(href);
} else {
res.status(404).json({ error: 'Element not found or href attribute is missing.' });
}
await browser.close();
}
} catch (e) {
console.error(e);
res.status(500).json({
error: 'Internal Server Error \n' + e
});
}
});
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/Nexchan/yutub');
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 berjalan di port ${PORT}`);
});