eses / index.js
aseli's picture
Update index.js
f3a829e verified
raw
history blame
No virus
5.36 kB
const express = require('express');
const { chromium } = require('playwright');
const QRCode = require('qrcode');
const Jimp = require('jimp');
const QrCodeReader = require('qrcode-reader');
//const fetch = require('node-fetch');
const app = express();
const port = 7860;
// Global variable to hold the browser instance and context
let browser;
let browserContext;
app.use(express.json());
app.get('/', (req, res) => {
console.log('request to /');
res.send('halo kontol');
});
app.post('/screenshot', async (req, res) => {
console.log('request to /screenshot');
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)');
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 });
});
app.get('/qrcode', async (req, res) => {
try {
const { mode, url } = req.query;
if (!mode || !url) {
return res.status(400).send('what?');
}
if (mode === 'create') {
QRCode.toDataURL(url, (err, src) => {
if (err) return res.send({ error: 'Error generating QR code' });
res.type('png').send(Buffer.from(src.split(",")[1], "base64"));
});
} else if (['read', 'scan'].includes(mode)) {
const rts = await fetch(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' });
const buffer = Buffer.from(await rts.arrayBuffer());
const image = await Jimp.read(buffer);
image.grayscale().contrast(1).normalize();
const qrCodeReader = new QrCodeReader();
qrCodeReader.callback = (err, value) => {
if (err) return res.send({ error: 'Error reading QR code' });
res.json({ result: value.result });
};
const bitmap = image.bitmap;
qrCodeReader.decode({ width: bitmap.width, height: bitmap.height, data: bitmap.data });
} else {
QRCode.toDataURL(url, (err, src) => {
if (err) return res.send({ error: 'Error generating QR code' });
res.type('png').send(Buffer.from(src.split(",")[1], "base64"));
});
}
} catch (error) {
console.error(error);
res.send({ error: 'Internal Server Error' });
}
});
async function processScreenshot(req, res, { ua, url, type, width, height, language, fullpage }) {
try {
console.log('process screenshot');
// Launch browser and create a context if it doesn't exist
if (!browser) {
browser = await chromium.launch({
headless: true,
args: ["--no-sandbox", "--disable-setuid-sandbox"]
});
}
// Reuse or create a new context
if (!browserContext) {
browserContext = await browser.newContext({
userAgent: ua || 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
viewport: { width: width || 1280, height: height || 800 },
deviceScaleFactor: 2
});
}
const page = await browserContext.newPage();
if (language) {
await page.emulateMedia({ colorScheme: language });
}
await page.goto(url, { waitUntil: 'networkidle' });
// Handle JavaScript challenges
await page.waitForLoadState('networkidle');
let screenshotOptions = {
fullPage: fullpage == 1 ? true : false,
type: 'png',
omitBackground: false
};
if (type === 'desktop') {
await page.setViewportSize({
width: 1920,
height: 1080,
});
} else if (type === 'mobile') {
await page.setViewportSize({
width: 375,
height: 667,
});
} else if (type === 'tablet') {
await page.setViewportSize({
width: 768,
height: 1024,
});
} else if (type === 'iphone') {
await page.setViewportSize({
width: 375,
height: 667,
});
} else if (type === 'custom') {
if (width && height > 4096) {
await page.close();
return res.json({
"status": 400,
"message": "Width and height values should not exceed 4096 pixels."
});
}
if (width && height < 400) {
await page.close();
return res.json({
"status": 400,
"message": "Width and height values should not be less than 400 pixels."
});
}
await page.setViewportSize({
width: Number(width) || 375,
height: Number(height) || 667,
});
}
await page.waitForTimeout(5000);
const screenshot = await page.screenshot(screenshotOptions);
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': screenshot.length,
});
res.end(screenshot);
console.log('process done');
await page.close(); // Close the tab instead of the browser
// Periodically close and reopen the browser to avoid memory bloat
if (browserContext.pages().length > 10) { // Arbitrary threshold
await browserContext.close();
browserContext = await browser.newContext();
}
// Trigger garbage collection
if (global.gc) {
global.gc();
}
} catch (e) {
console.error(e);
return res.json({
status: 400,
message: 'error when take a screenshot'
});
}
}
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});