File size: 5,955 Bytes
6b60173
 
 
 
a4fe837
 
 
6b60173
 
 
 
 
d25296b
6b60173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a4fe837
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4d47368
44ed890
 
 
 
 
 
 
 
4d47368
a4fe837
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6b60173
 
 
 
 
 
 
 
 
 
a4fe837
6b60173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a4fe837
6b60173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a4fe837
 
6b60173
 
a4fe837
6b60173
a4fe837
6b60173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44ed890
6b60173
 
a4fe837
6b60173
 
 
 
 
 
 
 
 
a4fe837
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
const express = require('express');
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const AnonymizeUA = require('puppeteer-extra-plugin-anonymize-ua');
const QRCode = require('qrcode');
const Jimp = require('jimp');
const QrCodeReader = require('qrcode-reader');

puppeteer.use(StealthPlugin());
puppeteer.use(AnonymizeUA());

const app = express();
const port = 7860;

app.use(express.json());
app.get('/', async (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') {
			// Generate a QR code
			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)) {
			// Fetch the image and read the QR code
			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);

			// Preprocess the image to enhance QR code readability
			image
				.grayscale() // Convert to grayscale
				.contrast(1) // Increase contrast
				.normalize(); // Normalize the image

			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')
		const browser = await puppeteer.launch({
			headless: "new",
			args: ["--aggressive-tab-discard",
				"--disable-accelerated-2d-canvas",
				"--disable-application-cache",
				"--disable-cache",
				"--disable-dev-shm-usage",
				"--disable-gpu",
				"--disable-offline-load-stale-cache",
				"--disable-setuid-sandbox",
				"--disable-setuid-sandbox",
				"--disk-cache-size=0",
				"--ignore-certificate-errors",
				"--no-first-run",
				"--no-sandbox",
				"--no-zygote"
			]
		});
		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',
		});

		await page.goto(url, {
			waitUntil: 'networkidle2',
		});
		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,
			});
		} else if (type === 'mobile') {
			screenshotOptions = {
				fullPage: full,
				width: 375,
				height: 667
			};
			await page.setViewport({
				width: 375,
				height: 667,
			});
		} else if (type === 'tablet') {
			screenshotOptions = {
				fullPage: full,
				width: 768,
				height: 1024
			};
			await page.setViewport({
				width: 768,
				height: 1024,
			});
		} else if (type === 'iphone') {
			screenshotOptions = {
				fullPage: full,
				width: 375,
				height: 667
			};
			await page.setViewport({
				width: 375,
				height: 667,
			});
		} else if (type === 'custom') {
			if (width && height > 4096) {
				return res.json({
					"status": 400,
					"message": "Width and height values should not exceed 4096 pixels."
				});
				await browser.close();
			}
			if (width && height < 400) {
				return res.json({
					"status": 400,
					"message": "Width and height values should not be less than 400 pixels."
				});
				await browser.close();
			}
			screenshotOptions = {
				fullPage: full,
				width: width || 375,
				height: height || 667
			};
			await page.setViewport({
				width: Number(width) || 375,
				height: Number(height) || 667,
			});
		}

		// 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('process done');
		await browser.close();
	} catch (e) {
		log(e)
		return res.json({
			status: 400,
			message: 'error when take a screenshot'
		})
	}
}

app.listen(port, () => {
	console.log(`Server is running on port ${port}`);
});