const express = require('express'); const puppeteer = require('puppeteer-extra'); const StealthPlugin = require('puppeteer-extra-plugin-stealth'); const AnonymizeUA = require('puppeteer-extra-plugin-anonymize-ua'); var jimp = require("jimp"); var qrCode = require('qrcode-reader'); puppeteer.use(StealthPlugin()); puppeteer.use(AnonymizeUA()); const app = express(); const port = 5000; app.use(express.json()); app.get('/', async (req, res) => { console.log('request to /') console.log('IP => ' + req.headers['x-real-ip']) console.log('User Agent => ' + req.headers['user-agent']) res.send({message: 'halo kontol'}) }) app.post('/screenshot', async (req, res) => { console.log('request to /screenshot') console.log('IP => ' + req.headers['x-real-ip']) console.log('User Agent => ' + req.headers['user-agent']) const { ua, url, type, width, height, language, fullpage } = req.body; if (!url) return res.send('please input url') await processScreenshot(req, res, { ua, url, type, width, height, language, fullpage }); }); app.get('/screenshot', async (req, res) => { console.log('request to /screenshot (get)') console.log('IP => ' + req.headers['x-real-ip']) console.log('User Agent => ' + req.headers['user-agent']) const { ua, url, type, width, height, language, fullpage } = req.query; if (!url) return res.send('please input url') await processScreenshot(req, res, { ua, url, type, width, height, language, fullpage }); }); async function processScreenshot(req, res, { ua, url, type, width, height, language, fullpage }) { console.log('process screenshot') const browser = await puppeteer.launch({ headless: "new", executablePath:"/usr/bin/chromium", protocolTimeout: 0, args: [ "--fast-start", "--disable-extensions", "--no-sandbox", "--disable-setuid-sandbox", "--no-gpu", "--disable-background-timer-throttling", "--disable-renderer-backgrounding", "--override-plugin-power-saver-for-testing=never", "--disable-extensions-http-throttling", "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.3" ] }); const page = await browser.newPage(); // Set language and user agent await page.setExtraHTTPHeaders({ 'Accept-Language': language || 'id-ID', 'User-Agent': ua || 'Mozilla/5.0 (Linux; Android 13; Pixel Build/RPB1.210523.001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36', }); try { await page.goto(url); let full = fullpage == 1 ? true : false let screenshotOptions = { fullPage: true }; if (type === 'desktop') { screenshotOptions = { fullPage: full, width: 1280, height: 800 }; await page.setViewport({ width: 1280, height: 800,deviceScaleFactor: 2 }); } else if (type === 'mobile') { screenshotOptions = { fullPage: full, width: 375, height: 667 }; await page.setViewport({ width: 375, height: 667,deviceScaleFactor: 2 }); } else if (type === 'tablet') { screenshotOptions = { fullPage: full, width: 768, height: 1024 }; await page.setViewport({ width: 768, height: 1024,deviceScaleFactor: 2 }); } else if (type === 'iphone') { screenshotOptions = { fullPage: full, width: 375, height: 667 }; await page.setViewport({ width: 375, height: 667,deviceScaleFactor: 2 }); } else if (type === 'custom') { if (width && height > 4096) { await browser.close(); return res.json({ "status": 400, "message": "Width and height values should not exceed 4096 pixels." }); } if (width && height < 90) { await browser.close(); return res.json({ "status": 400, "message": "Width and height values should not be less than 90 pixels." }); } screenshotOptions = { fullPage: full, width: width || 375, height: height || 667 }; await page.setViewport({ width: Number(width) || 375, height: Number(height) || 667,deviceScaleFactor: 2 }); } // Wait for a few seconds to mimic more natural behavior await page.waitForTimeout(3000); const screenshot = await page.screenshot(screenshotOptions); res.writeHead(200, { 'Content-Type': 'image/png', 'Content-Length': screenshot.length, }); res.end(screenshot); console.log('screenshot successfully') await browser.close(); } catch (e) { console.log(e) await browser.close(); return res.json({ status: 400, message: 'error when take a screenshot' }) } } const PORT = process.env.PORT || 7860 function restartSpace() { const { SPACE_ID, HF_TOKEN } = process.env return fetch(`https://huggingface.co/api/spaces/${SPACE_ID}/restart`, { method: 'POST', headers: { Authorization: `Bearer ${HF_TOKEN}` } }) } function keepAlive() { var url = `https://${process.env.SPACE_HOST}` if (/(\/\/|\.)undefined\./.test(url)) return setInterval(() => { fetch(url, { headers: { Authorization: "Bearer " + process.env.HF_TOKEN}}) .then(response => { if (!response.ok) { restartSpace().catch(console.error) } }) .catch(console.error) }, 5 * 1000 * 60) } app.get("/qrcode", async (req, res) => { if (!req.query.url) return res.send({status: 400}) if (!req.query.mode) return res.send({status: 400}) const readQRCode = async (buffer) => { try { const img = await jimp.read(buffer); const qr = new qrCode(); const value = await new Promise((resolve, reject) => { qr.callback = (err, v) => err != null ? reject(err) : resolve(v); qr.decode(img.bitmap); }); return value.result; } catch (error) { return error.message } } if (req.query.mode == "scan") { let rts = await fetch(req.query.url) if (!rts.ok || rts.status !== 200) return res.send({ status: 400, message: 'Can\'t buffer url' }) if (!/image/.test(rts.headers.get('content-type'))) return res.send({ status: 400, message: 'Only image type' }) return res.send({ result: await readQRCode(await rts.arrayBuffer()) || null }) } else { var { toDataURL } = require("qrcode"); let me = await toDataURL(req.query.url); res.type('png').send(Buffer.from(me.split("base64,")[1], "base64")); } }) app.listen(PORT, async () => { console.log('App running on port', PORT) console.log(fetch) console.log(process.env['HF_TOKEN']) keepAlive() })