Spaces:
Paused
Paused
| const fs = require('fs') | |
| const os = require('os') | |
| const util = require('util') | |
| const axios = require('axios') | |
| const bytes = require('bytes') | |
| const sharp = require('sharp') | |
| const morgan = require('morgan') | |
| const express = require('express') | |
| const cp = require('child_process') | |
| const PDFDocument = require('pdfkit') | |
| const playwright = require('playwright-extra') | |
| // const stealth = require('puppeteer-extra-plugin-stealth') | |
| // playwright.chromium.use(stealth()) | |
| const { NinexbuddySource, NinexbuddyScraper } = require("./lib/buddy.js") | |
| const kyou = new NinexbuddyScraper() | |
| const app = express() | |
| app.set('json spaces', 4) | |
| app.use(morgan('dev')) | |
| const limitSize = '500mb' | |
| app.use(express.json({ limit: limitSize })) | |
| app.use(express.urlencoded({ extended: true, limit: limitSize })) | |
| const tmpFolder = os.tmpdir() | |
| app.use((req, res, next) => { | |
| fs.readdirSync(tmpFolder).map(file => { | |
| file = `${tmpFolder}/${file}` | |
| let stats = fs.statSync(file) | |
| if (!stats.isFile()) return | |
| if (Date.now() - stats.mtimeMs >= 1000 * 60 * 30) { | |
| fs.unlinkSync(file) | |
| console.log('Deleted file', file) | |
| } | |
| }) | |
| next() | |
| }) | |
| app.use('/file', express.static(tmpFolder)) | |
| app.all('/', (req, res) => { | |
| const status = {} | |
| const used = process.memoryUsage() | |
| for (let key in used) status[key] = formatSize(used[key]) | |
| const disk = cp.execSync('du -sh').toString().split('M')[0] | |
| status.diskUsage = `${disk} MB` | |
| const totalmem = os.totalmem() | |
| const freemem = os.freemem() | |
| status.memoryUsage = `${formatSize(totalmem - freemem)} / ${formatSize(totalmem)}` | |
| res.json({ | |
| creator: '@rippanteq7', | |
| message: 'Hello World', | |
| uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], | |
| status | |
| }) | |
| }) | |
| app.get('/proxy', async (req, res) => { | |
| const { url } = req.query; | |
| if (!url) return res.json({ success: false, message: 'Required parameter url' }); | |
| try { | |
| const response = await axios({ | |
| method: 'get', | |
| url, | |
| responseType: 'stream', | |
| headers: { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', | |
| 'Referer': url | |
| } | |
| }); | |
| // Mengatur header agar tetap sesuai dengan respons asli | |
| res.set(response.headers); | |
| // Streaming langsung ke response | |
| response.data.pipe(res); | |
| } catch (error) { | |
| console.error(error.message); | |
| res.status(500).json({ success: false, message: 'Error fetching video' }); | |
| } | |
| }); | |
| app.get('/pages', async (req, res) => { | |
| const targetUrl = req.query.url; | |
| if (!targetUrl) { | |
| return res.status(400).json({ error: 'Parameter "url" dibutuhkan' }); | |
| } | |
| const browser = await playwright.chromium.launch({ | |
| headless: true, | |
| executablePath: '/usr/bin/chromium', // pastikan path ini benar di server kamu | |
| args: ['--no-sandbox'] | |
| }); | |
| const context = await browser.newContext({ | |
| extraHTTPHeaders: { | |
| 'accept': '*/*', | |
| 'accept-language': 'en-US,en;q=0.9,id;q=0.8', | |
| 'cache-control': 'no-cache', | |
| 'origin': 'https://doujindesu.tv', | |
| 'pragma': 'no-cache', | |
| 'referer': 'https://doujindesu.tv', | |
| 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"', | |
| 'sec-ch-ua-mobile': '?0', | |
| 'sec-ch-ua-platform': '"Windows"', | |
| 'sec-fetch-dest': 'script', | |
| 'sec-fetch-mode': 'cors', | |
| 'sec-fetch-site': 'cross-site', | |
| 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' | |
| } | |
| }); | |
| try { | |
| const page = await context.newPage(); | |
| await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 60000 }); | |
| // Tunggu ekstra jika perlu ngelewatin challenge | |
| await page.waitForTimeout(8000); | |
| const content = await page.content(); | |
| res.send(content); | |
| } catch (err) { | |
| res.status(500).json({ error: 'Gagal fetch halaman', detail: err.message }); | |
| } finally { | |
| await browser.close(); | |
| } | |
| }); | |
| app.all('/imagetopdf', async (req, res) => { | |
| if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
| try { | |
| console.log(new Date().toLocaleString('id', { timeZone: 'Asia/Jakarta' }), '\n', req.body) | |
| const { images } = req.body | |
| if (!(images && Array.isArray(images))) return res.json({ success: false, message: 'Required an array image url' }) | |
| const buffer = await toPDF(images) | |
| res.setHeader('Content-Disposition', `attachment; filename=${Math.random().toString(36).slice(2)}.pdf`) | |
| res.setHeader('Content-Type', 'application/pdf') | |
| res.setHeader('Content-Length', buffer.byteLength) | |
| res.send(buffer) | |
| } catch (e) { | |
| console.log(e) | |
| e = String(e) | |
| res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
| } | |
| }) | |
| app.all('/webp2png', async (req, res) => { | |
| if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
| try { | |
| const { file } = req.body | |
| if (!(file && isBase64(file))) return res.json({ success: false, message: 'Payload body file must be filled in base64 format' }) | |
| const fileBuffer = Buffer.from(file, 'base64') | |
| const fileName = `${Math.random().toString(36).slice(2)}.png` | |
| const convertData = await sharp(fileBuffer).png().toBuffer() | |
| await fs.promises.writeFile(`${tmpFolder}/${fileName}`, convertData) | |
| res.send(`https://${req.get('host')}/file/${fileName}`) | |
| } catch (e) { | |
| console.log(e) | |
| e = String(e) | |
| res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
| } | |
| }) | |
| app.all(['/webp2gif', '/webp2mp4'], async (req, res) => { | |
| if (!['POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
| try { | |
| const { file } = req.body | |
| if (!(file && isBase64(file))) return res.json({ success: false, message: 'Payload body file must be filled in base64 format' }) | |
| const fileBuffer = Buffer.from(file, 'base64') | |
| const fileName = `${Math.random().toString(36).slice(2)}.webp` | |
| const filePath = `${tmpFolder}/${fileName}` | |
| await fs.promises.writeFile(filePath, fileBuffer) | |
| const exec = util.promisify(cp.exec).bind(cp) | |
| await exec(`convert ${filePath} ${filePath.replace('.webp', '.gif')}`) | |
| if (/gif/.test(req.path)) return res.send(`https://${req.get('host')}/file/${fileName.replace('.webp', '.gif')}`) | |
| await exec(`ffmpeg -i ${filePath.replace('.webp', '.gif')} -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" ${filePath.replace(/.webp|.gif/g, '')}.mp4`) | |
| res.send(`https://${req.get('host')}/file/${fileName.replace('.webp', '.mp4')}`) | |
| } catch (e) { | |
| console.log(e) | |
| e = String(e) | |
| res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
| } | |
| }) | |
| app.get('/fetch', async (req, res) => { | |
| try { | |
| if (!req.query.url) return res.json({ message: 'Required an url' }) | |
| let json = await axios.get(req.query.url) | |
| res.json(json.data) | |
| } catch (e) { | |
| res.send(e) | |
| } | |
| }) | |
| app.all(['/enhance', '/hd', '/upscale'], async (req, res) => { | |
| if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
| try { | |
| const { url } = req.method !== 'GET' ? req.body : req.query | |
| if (!url) return res.json({ success: false, message: 'Required parameter url' }) | |
| const result = await enhanceImage(url) | |
| res.json({ success: true, result }) | |
| } catch (e) { | |
| console.log(e) | |
| e = String(e) | |
| res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
| } | |
| }) | |
| app.all('/animelast', async (req, res) => { | |
| const result = await scrapeAnimeInfo(); | |
| res.json({ | |
| creator: '@Kyouka', | |
| message: 'Success', | |
| uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], | |
| result | |
| }); | |
| }); | |
| app.all('/dood', async (req, res) => { | |
| const { url } = req.query | |
| if (!url) return res.json({ success: false, message: 'Required parameter url' }) | |
| const result = await kyou.execWithArgs(url) | |
| res.json({ | |
| creator: '@Kyouka', | |
| message: 'Success', | |
| uptime: new Date(process.uptime() * 1000).toUTCString().split(' ')[4], | |
| result | |
| }); | |
| }); | |
| app.get('/igstalk', async (req, res) => { | |
| try { | |
| if (!req.query.user) return res.json({ message: 'Required an username' }) | |
| let result = await igStalk(req.query.user) | |
| res.json({ result }) | |
| } catch (e) { | |
| res.send(e) | |
| } | |
| }) | |
| app.all('/stablediff/illusion', async (req, res) => { | |
| if (!['GET', 'POST'].includes(req.method)) return res.status(405).json({ success: false, message: 'Method Not Allowed' }) | |
| try { | |
| const { | |
| prompt, | |
| negative_prompt = 'low quality', | |
| image_url, | |
| num_inference_steps = 25, | |
| controlnet_conditioning_scale = 1 | |
| } = req.method !== 'GET' ? req.body : req.query | |
| if (!(prompt && image_url)) return res.json({ success: false, message: 'Required parameter prompt & image_url' }) | |
| const headers = { | |
| 'Content-Type': 'application/json', | |
| Authorization: `Key ${process.env.falAIKey}` | |
| } | |
| const { detail, response_url } = await (await fetch('https://54285744-illusion-diffusion.gateway.alpha.fal.ai/fal/queue/submit', { | |
| method: 'POST', | |
| body: JSON.stringify({ | |
| prompt, negative_prompt, image_url, | |
| num_inference_steps, controlnet_conditioning_scale | |
| }), | |
| headers | |
| })).json() | |
| if (detail) return res.json({ success: false, message: detail }) | |
| let retry = 0 | |
| while (true) { | |
| await new Promise(resolve => setTimeout(resolve, 2500)) | |
| const prediction = await (await fetch(response_url, { headers })).json() | |
| console.log(prediction) | |
| if (retry > 10) return res.json({ success: false, message: prediction.detail || 'Max retry has reached' }) | |
| if (prediction.image) return res.json({ success: true, result: prediction }) | |
| retry += 1 | |
| } | |
| } catch (e) { | |
| console.log(e) | |
| e = String(e) | |
| res.status(500).json({ error: true, message: e === '[object Object]' ? 'Internal Server Error' : e }) | |
| } | |
| }) | |
| app.get('/dongo', async (req, res) => { | |
| const { url } = req.query | |
| if (!url) return res.json({ success: false, message: 'Required parameter url' }) | |
| const browser = await playwright.chromium.launch({ | |
| headless: true, | |
| executablePath: '/usr/bin/chromium', | |
| args: ['--no-sandbox'] | |
| }) | |
| const context = await browser.newContext({ | |
| extraHTTPHeaders: { | |
| 'accept': '*/*', | |
| 'accept-language': 'en-US,en;q=0.9,id;q=0.8', | |
| 'cache-control': 'no-cache', | |
| 'origin': url, | |
| 'pragma': 'no-cache', | |
| 'referer': url, | |
| 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"', | |
| 'sec-ch-ua-mobile': '?0', | |
| 'sec-ch-ua-platform': '"Windows"', | |
| 'sec-fetch-dest': 'script', | |
| 'sec-fetch-mode': 'cors', | |
| 'sec-fetch-site': 'cross-site', | |
| 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' | |
| } | |
| }); | |
| const page = await context.newPage(); | |
| await page.goto(url); | |
| const content = await page.content(); // Get the page content as HTML | |
| await browser.close(); | |
| res.send(content); // Send the page content as response | |
| }); | |
| app.get('/fetch-page', async (req, res) => { | |
| const targetUrl = req.query.url; | |
| if (!targetUrl) { | |
| return res.status(400).json({ | |
| developer: "KyoukaDev", | |
| status: false, | |
| message: 'Parameter "url" dibutuhkan', | |
| }); | |
| } | |
| const baseUrl = new URL(targetUrl).origin; | |
| const browser = await playwright.chromium.launch({ | |
| headless: true, | |
| executablePath: '/usr/bin/chromium', // pastikan path ini valid | |
| args: ['--no-sandbox'] | |
| }); | |
| const context = await browser.newContext({ | |
| extraHTTPHeaders: { | |
| 'accept': '*/*', | |
| 'accept-language': 'en-US,en;q=0.9,id;q=0.8', | |
| 'cache-control': 'no-cache', | |
| 'origin': baseUrl, | |
| 'pragma': 'no-cache', | |
| 'referer': baseUrl, | |
| 'sec-ch-ua': '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"', | |
| 'sec-ch-ua-mobile': '?0', | |
| 'sec-ch-ua-platform': '"Windows"', | |
| 'sec-fetch-dest': 'script', | |
| 'sec-fetch-mode': 'cors', | |
| 'sec-fetch-site': 'cross-site', | |
| 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' | |
| } | |
| }); | |
| try { | |
| const page = await context.newPage(); | |
| await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 60000 }); | |
| await page.waitForTimeout(8000); | |
| const content = await page.content(); | |
| res.json({ | |
| developer: "KyoukaDev", | |
| status: true, | |
| data: { | |
| results: [ | |
| { content } | |
| ] | |
| } | |
| }); | |
| } catch (err) { | |
| res.status(500).json({ | |
| developer: "KyoukaDev", | |
| status: false, | |
| message: 'Gagal fetch halaman', | |
| error: err.message | |
| }); | |
| } finally { | |
| await browser.close(); | |
| } | |
| }); | |
| const PORT = process.env.PORT || 7860 | |
| app.listen(PORT, () => console.log('App running on port', PORT)) | |
| function formatSize(num) { | |
| return bytes(+num || 0, { unitSeparator: ' ' }) | |
| } | |
| function isBase64(str) { | |
| try { | |
| return btoa(atob(str)) === str | |
| } catch { | |
| return false | |
| } | |
| } | |
| function toPDF(urls) { | |
| return new Promise(async (resolve, reject) => { | |
| try { | |
| if (!Array.isArray(urls)) urls = [urls] | |
| const doc = new PDFDocument({ margin: 0, size: 'A4' }) | |
| const buffers = [] | |
| for (let i = 0; i < urls.length; i++) { | |
| const response = await fetch(urls[i], { headers: { referer: urls[i] }}) | |
| if (!response.ok) continue | |
| const type = response.headers.get('content-type') | |
| if (!/image/.test(type)) continue | |
| let buffer = Buffer.from(await response.arrayBuffer()) | |
| if (/gif|webp/.test(type)) buffer = await sharp(buffer).png().toBuffer() | |
| doc.image(buffer, 0, 0, { fit: [595.28, 841.89], align: 'center', valign: 'center' }) | |
| if (urls.length !== i + 1) doc.addPage() | |
| } | |
| doc.on('data', (chunk) => buffers.push(chunk)) | |
| doc.on('end', () => resolve(Buffer.concat(buffers))) | |
| doc.on('error', reject) | |
| doc.end() | |
| } catch (e) { | |
| console.log(e) | |
| reject(e) | |
| } | |
| }) | |
| } | |
| async function scrapeAnimeInfo() { | |
| try { | |
| const browser = await playwright.chromium.launch({ | |
| headless: true, | |
| executablePath: '/usr/bin/chromium', | |
| args: ['--no-sandbox'] | |
| }); | |
| const page = await browser.newPage(); | |
| await page.goto('http://66.29.129.161/?filter=latest&cat=1'); | |
| const pageContent = await page.content(); | |
| console.log(pageContent); | |
| // Wait for the list of videos to load | |
| await page.waitForSelector('.videos-list'); | |
| // Extract data from all articles | |
| const videoData = await page.$$eval('.videos-list article', articles => { | |
| return articles.map(article => { | |
| const thumbnail = article.querySelector('.post-thumbnail img').src; | |
| const title = article.querySelector('header.entry-header span').textContent; | |
| const url = article.querySelector('a').href; | |
| const duration = article.querySelector('.duration').textContent.trim(); | |
| return { thumbnail, title, url, duration }; | |
| }); | |
| }); | |
| await browser.close(); | |
| return videoData; | |
| } catch (error) { | |
| console.error('An error occurred during scraping:', error); | |
| return []; // Return an empty array in case of error | |
| } | |
| } | |
| async function enhanceImage(url) { | |
| const browser = await playwright.chromium.launch({ | |
| headless: true, | |
| executablePath: '/usr/bin/chromium', | |
| args: ['--no-sandbox'] | |
| }) | |
| const page = await browser.newPage() | |
| await page.goto('https://snapedit.app/id/enhance/upload') | |
| await page.waitForLoadState('domcontentloaded') | |
| const arrayBuffer = await (await fetch(url)).arrayBuffer() | |
| page.on('filechooser', (fileChooser) => { | |
| const fileObject = { | |
| name: 'file.jpg', | |
| mimeType: 'image/jpg', | |
| buffer: Buffer.from(arrayBuffer) | |
| } | |
| fileChooser.setFiles([fileObject]) | |
| }) | |
| await page.getByRole('button', { name: 'Unggah gambar', exact: true }).click() | |
| const response = await page.waitForResponse(res => { | |
| console.log(res.url()) | |
| return res.url().includes('api/enhance/v1') | |
| }, { timeout: 60 * 1000 }) | |
| const json = await response.json() | |
| await browser.close() | |
| return json | |
| } | |
| async function igStalk(user) { | |
| const getDetailPost = async url => { | |
| let html = (await axios.get(url, { headers: { 'Referer': 'https://www.picuki.com/', 'User-Agent': fakeua.mobile() }})).data | |
| let $ = cheerio.load(html), obj = {} | |
| obj.caption = $('title').text().trim().split(' Instagram post ')[1].split(' - Picuki.com')[0] | |
| obj.ago = $('div.single-photo-info').find('div.single-photo-time').text() | |
| obj.likes = $('div.info-bottom').find('span.icon-thumbs-up-alt').text() | |
| obj.comments = $('div.info-bottom').find('span.icon-chat').text() | |
| obj.url = $('div.single-photo.owl-carousel.owl-theme > div.item').get().map((x) => $(x).find('img').attr('src') || $(x).find('video').attr('src')) | |
| if (!obj.url.length) obj.url = [$('div.single-photo').find('img').attr('src') || $('div.single-photo').find('video').attr('src')] | |
| return obj | |
| } | |
| let html = (await axios.get('https://www.picuki.com/profile/' + user, { headers: { 'Referer': 'https://www.picuki.com/', 'User-Agent': fakeua.mobile() }})).data | |
| let $ = cheerio.load(html), obj = {}, arr = [] | |
| let urlPost = $('div.content > ul > li').get().map((x) => $(x).find('a').attr('href')) | |
| for (let x of urlPost) { | |
| if (x) arr.push(await getDetailPost(x)) | |
| } | |
| obj.avatar = $('div.profile-avatar').find('a').attr('href') | |
| obj.username = $('div.profile-name > h1').text() | |
| obj.fullname = $('div.profile-name > h2').text() | |
| obj.description = $('div.profile-description').text().trim() | |
| obj.followers = $('div.content-title').find('span.followed_by').text() | |
| obj.following = $('div.content-title').find('span.follows').text() | |
| obj.post = arr | |
| return obj | |
| } |