nsfw / index.js
Closure-RI's picture
Update index.js
5929edd verified
import axios from 'axios';
import * as cheerio from 'cheerio';
import { createRequire } from 'module';
import os from 'os';
import express from 'express';
import { promisify, format } 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';
import mime from "mime-types";
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 bodyParser = require('body-parser');
app.use(bodyParser.json());
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.use(express.urlencoded({ extended: true }));
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()}`;
};
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 iwaraDL(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.goto("https://fetchfile.me/download-iwara/", { waitUntil: 'domcontentloaded' });
await page.type('#url', url);
await page.click('#ring');
await page.waitForSelector('#result > div > div.youtube.col-md-7 > ul > li');
const title = await page.$eval('#result > div > div.youtube.col-md-7 > h2', el => el.innerText);
const originalSource = await page.$eval('#mp4 > table > tbody > tr:nth-child(1) > td:nth-child(3) > a.dlw', el => el.href || null);
const high = await page.$eval('#mp4 > table > tbody > tr:nth-child(2) > td:nth-child(3) > a.dlw', el => el.href || null);
const standard = await page.$eval('#mp4 > table > tbody > tr:nth-child(3) > td:nth-child(3) > a.dlw', el => el.href || null);
const low = await page.$eval('#mp4 > table > tbody > tr:nth-child(4) > td:nth-child(3) > a.dlw', el => el.href || null);
let ht = await page.content();
console.log("\n========================\n\n\n " + ht + " \n========================\n")
await browser.close();
return {
title,
originalSource: originalSource || 'Original source not available',
high: high || 'High quality not available',
standard: standard || 'Standard quality not available',
low: low || 'Low quality not available'
};
}
// Rute untuk menerima data melalui query string (GET)
app.get('/iwara/download', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'Parameter url is required' });
try {
const base64Result = await iwaraDL(url);
res.json(base64Result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
async function XnxxDown(inputUrl) {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const context = await browser.createIncognitoBrowserContext();
const page = await context.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://www.locoloader.com/?url=${encodeURIComponent(inputUrl)}`, { waitUntil: 'domcontentloaded' });
await page.waitForSelector("#extraction > div > div.hl > h1 > a");
const title = await page.$eval(
"#extraction > div > div.hl > h1 > a",
el => el.innerText.trim()
);
const url = await page.$eval(
"#extraction > div > div.hl > h1 > a",
el => el.href
);
const img = await page.$eval(
"#extraction > div > div.content-final-single__thumb-wrapper > div > div > img",
el => el.src
);
const type = await page.$eval(
"#extraction > div > div:nth-child(3) > div.display-table-cell.linkInfo > div.icon-media",
el => el.innerText.trim()
);
const downloadLink = await page.$eval(
"#extraction > div > div:nth-child(3) > div.display-table-cell.linkButtons > a.bt.dl",
el => el.href
);
await browser.close();
return { title, url, img, type, downloadLink };
}
app.get('/xnxx/download', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'Parameter url is required' });
try {
const base64Result = await XnxxDown(url);
res.json(base64Result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
class Xnxx {
constructor() {
}
async search(nama_porn, page) {
let urls = `https://www.xnxx.com/search/${nama_porn}`;
if (this.page > 0) {
urls += `/${Number(page) - 1}`;
}
const ress = await axios.get(urls);
const $ = cheerio.load(ress.data);
let dataVideo = [];
const videoPromises = [];
$('div.thumb-block').each((i, element) => {
const judul = $(element).find('p a').attr('title');
const url = $(element).find('p a').attr('href');
const thumbnail = $(element).find('div.thumb-inside div.thumb a img').attr('data-src') || $(element).find('p a img').attr('src');
const views = $(element).find('.metadata .right').text().trim();
const durasi = $(element).find('.metadata').contents().filter(function() {
return this.nodeType === 3;
}).text().trim();
const urlVideo = `https://www.xnxx.com${url}`;
videoPromises.push(
axios.get(urlVideo).then((resss) => {
const $$ = cheerio.load(resss.data);
const detailJudul = $$('#video-content-metadata .video-title strong').text().trim() || judul;
const detailDurasiMatch = $$('#video-content-metadata .metadata').text().match(/(\d+min \d+sec|\d+sec)/);
const detailDurasi = detailDurasiMatch ? detailDurasiMatch[0] : durasi;
const detailViewsMatch = $$('#video-content-metadata .metadata').html().match(/(\d+(?:,\d+)?)\s*<span class="icon-f icf-eye"><\/span>/);
const detailViews = detailViewsMatch ? detailViewsMatch[1].replace(/,/g, '') : views;
const detailRating = $$('#video-votes .rating-box.value').text().trim();
const jumlahKomentar = $$('#tabComments .nb-video-comments').text().trim();
const tag = $$('.video-tags a.is-keyword').map((_, tag) => $$(tag).text()).get().join(', ');
dataVideo.push({
judul: detailJudul,
thumbnail: thumbnail,
url: urlVideo,
views: detailViews,
durasi: detailDurasi,
rating: detailRating,
jumlahKomentar: jumlahKomentar,
tag: tag
});
})
);
});
await Promise.all(videoPromises);
let next = $("#content-thumbs > div:nth-child(4) > ul > li")
.find("a.no-page")
.attr('href')?.match(/\/(\d+)$/)?.[1] || null;
return { next, dataVideo };
}
async download(videoURL) {
try {
const ress = await axios.get("https://arashicode-api.hf.space/xnxx/download?url=" + videoURL);
return ress.data;
} catch (err) {
throw new Error(`Gagal mengambil link download: ${err}`);
}
}
}
app.get('/xnxx/search', async (req, res) => {
const { query, page } = req.query;
if (!query) return res.status(400).json({ error: 'Parameter query is required' });
try {
const xnxx = new Xnxx();
let result = await xnxx.search(query, page);
res.json(result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
/**********************************************************************************/
class XvideosScraper {
constructor() {
this.baseURL = 'https://www.xvideos.com';
this.browser = null;
this.page = null;
this.context = null;
}
async initialize() {
this.browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
this.context = await this.browser.createIncognitoBrowserContext();
this.page = await this.context.newPage();
await this.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;]");
}
async search(query, pageNumber) {
const url = `${this.baseURL}/?k=${encodeURIComponent(query)}`;
if(pageNumber > 0) {
url += `&p=${pageNumber}`;
}
console.log(`Navigating to: ${url}`);
await this.page.goto(url, { waitUntil: 'networkidle2' });
const result = await this.page.evaluate(() => {
function generateVideoUrl(url, use169, replaceJpgWithMp4) {
if (replaceJpgWithMp4) {
return url.replace(".jpg", ".mp4");
}
let newUrl = url.substring(0, url.lastIndexOf("/"))
.replace(/\/thumbs(169)?(xnxx)?((l*)|(poster))\//, "/videopreview/");
newUrl += use169 ? "_169.mp4" : "_43.mp4";
newUrl = newUrl.replace(/(-[0-9]+)_([0-9]+)/, "_$2$1");
return newUrl;
}
const elements = document.querySelectorAll('#content > div.mozaique > div');
const next = document.querySelector("#content > div.pagination > ul > li:last-child > a")?.href || null;
const data = Array.from(elements).map(el => {
const link = el.querySelector('div.thumb-inside > div > a')?.href || null;
const image = el.querySelector('div.thumb-inside > div > a > img')?.src || null;
const title = el.querySelector('div.thumb-under > p.title > a')?.getAttribute("title") || '';
const duration = el.querySelector('div.thumb-under > p.metadata > span > span.duration')?.textContent.trim() || '';
const quality = el.querySelector('div.thumb-inside > div > a > span')?.textContent.trim() || '';
const uploader = el.querySelector('div.thumb-under > p.metadata > span > span:nth-child(2) > a > span')?.textContent.trim() || '';
const idMatch = el.querySelector('script')?.innerHTML.match(/xv\.thumbs\.prepareVideo\((\d+)\)/);
const id = idMatch ? idMatch[1] : '';
const preview = image ? generateVideoUrl(image, true, false) : '';
return { link, image, title, duration, quality, uploader, id, preview };
}).filter(item => item.title.length >= 1);
return { next, data };
});
return result;
}
async close() {
await this.browser.close();
}
async download(videoURL) {
try {
const ress = await axios.get("https://arashicode-api.hf.space/xnxx/download?url=" + videoURL);
return ress.data;
} catch (err) {
throw new Error(`Gagal mengambil link download: ${err}`);
}
}
}
app.get('/xvideos/search', async (req, res) => {
const { query, page } = req.query;
if (!query) return res.status(400).json({ error: 'Parameter query is required' });
try {
const scraper = new XvideosScraper();
await scraper.initialize();
let result = await scraper.search(query, page);
res.json(result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
app.get('/xvideos/download', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'Parameter url is required' });
try {
const base64Result = await XnxxDown(url);
res.json(base64Result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
/**********************************************************************************/
const SearchWhentai = async (query) => {
const headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
};
try {
const { data } = await axios.get("https://watchhentai.net/?s=" + query, { headers });
const $ = cheerio.load(data);
const results = [];
$('.result-item').each((_, element) => {
const title = $(element).find('.title a').text().trim();
const link = $(element).find('.title a').attr('href');
const year = $(element).find('.meta .year').text().trim();
const description = $(element).find('.contenido p').text().trim();
const image = $(element).find('.image img').attr('src');
results.push({ title, link, year, description, image });
});
return results;
} catch (error) {
throw new Error(`Failed to scrape data: ${error.message}`);
}
};
const getDataWhentai = async (url) => {
try {
const { data } = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
},
});
const $ = cheerio.load(data);
const title = $("#single > div.content.right > div.sheader > div.data > h1").text().trim();
const thumb = $("#single > div.content.right > div.sheader > div.poster > img").attr('src');
const type = $("#single > div.content.right > div.sheader > div.poster > div > span").text().trim();
const year = $("#single > div.content.right > div.sheader > div.data > div.sgeneros > a:nth-child(1)").text().trim();
const tags = $("#single > div.content.right > div.sheader > div.data > div.sgeneros > a")
.map((_, el) => $(el).text().trim())
.get();
const sinopsis = $("#single > div.content.right > div:nth-child(2) > div > p").text().trim();
const alternativeTitle = $("#single > div.content.right > div:nth-child(5) > div:nth-child(2) > span > h3").text().trim();
const releaseDate = $("#single > div.content.right > div:nth-child(5) > div:nth-child(3) > span").text().trim();
const lastUpdated = $("#single > div.content.right > div:nth-child(5) > div:nth-child(4) > span").text().trim();
const season = $("#single > div.content.right > div:nth-child(5) > div:nth-child(5) > span").text().trim();
const totalEpisodes = $("#single > div.content.right > div:nth-child(5) > div:nth-child(6) > span").text().trim();
const averageDuration = $("#single > div.content.right > div:nth-child(5) > div:nth-child(7) > span").text().trim();
const quality = $("#single > div.content.right > div:nth-child(5) > div:nth-child(8) > span > a")
.map((_, el) => $(el).text().trim())
.get();
const studio = $("#single > div.content.right > div:nth-child(5) > div:nth-child(9) > span > a").text().trim();
const episodes = $("#seasons > div > div > ul > li").map((_, el) => {
const episodeThumb = $(el).find("div.imagen > img").attr('src');
const episodeUrl = $(el).find("div.episodiotitle > a").attr('href').replace("/videos/", "/download/");
const episodeTitle = $(el).find("div.episodiotitle > a").text().trim();
const uploadDate = $(el).find("div.episodiotitle > span").text().trim();
return { episodeUrl, episodeTitle, uploadDate };
}).get();
return {
title,
thumb,
type,
year,
tags,
sinopsis,
episodes,
};
} catch (error) {
throw new Error(`Failed to scrape data: ${error.message}`);
}
};
const DownloadWhentai = async (url) => {
try {
const { data } = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
},
});
const $ = cheerio.load(data);
const buttons = $("#single > div.content.right > div > div._4continuar > button").map((_, el) => {
const href = $(el).attr('onclick')?.match(/window\.location\.href\s*=\s*'([^']+)'/)?.[1];
const text = $(el).text().trim();
return { href, text };
}).get();
return buttons
} catch (error) {
throw new Error(`Failed to scrape data: ${error.message}`);
}
};
app.get('/whentai/search', async (req, res) => {
const { query } = req.query;
if (!query) return res.status(400).json({ error: 'Parameter query is required' });
try {
let result = await SearchWhentai(query);
res.json(result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
app.get('/whentai/detail', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'Parameter url is required' });
try {
let result = await getDataWhentai(url);
res.json(result); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(error);
}
});
app.get('/whentai/download', async (req, res) => {
const { url } = req.query;
if (!url) return res.status(400).json({ error: 'Parameter url is required' });
try {
let result = await DownloadWhentai(url);
res.json({ result }); // Mengirimkan buffer gambar sebagai respons
} catch (error) {
res.status(500).send(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}`);
});