andhikagg commited on
Commit
2572638
·
verified ·
1 Parent(s): 38872df

Create app2.js

Browse files
Files changed (1) hide show
  1. app2.js +172 -0
app2.js ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const { chromium, devices } = require('playwright');
3
+ const cors = require('cors');
4
+ const dotenv = require('dotenv');
5
+ const os = require('os');
6
+
7
+ dotenv.config();
8
+
9
+ const config = {
10
+ maxTextLength: 100,
11
+ viewport: { width: 1920, height: 1080 },
12
+ defaultUserAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
13
+ iPhoneUserAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1'
14
+ };
15
+
16
+ let defaultBrowser, defaultPage, iPhoneBrowser, iPhonePage;
17
+
18
+ const createBrowserContext = async (isIPhone = false) => {
19
+ const browser = await chromium.launch({ headless: true });
20
+ const contextOptions = isIPhone ? {
21
+ ...devices['iPhone 13'],
22
+ deviceScaleFactor: 2,
23
+ isMobile: true,
24
+ hasTouch: true,
25
+ userAgent: config.iPhoneUserAgent,
26
+ forcedColors: 'none',
27
+ viewport: { width: 390, height: 844 } // iPhone 13 dimensions
28
+ } : {
29
+ viewport: config.viewport,
30
+ userAgent: config.defaultUserAgent
31
+ };
32
+
33
+ const context = await browser.newContext(contextOptions);
34
+
35
+ // Block unnecessary resources
36
+ await context.route('**/*', (route) => {
37
+ const url = route.request().url();
38
+ if (url.endsWith('.png') || url.endsWith('.jpg') || url.includes('google-analytics')) {
39
+ return route.abort();
40
+ }
41
+ route.continue();
42
+ });
43
+
44
+ const page = await context.newPage();
45
+
46
+ // Add iPhone-specific styles for emoji if needed
47
+ if (isIPhone) {
48
+ await page.addStyleTag({
49
+ content: `
50
+ @font-face {
51
+ font-family: "Apple Color Emoji";
52
+ src: local("Apple Color Emoji");
53
+ }
54
+ * {
55
+ font-family: "Apple Color Emoji", -apple-system, BlinkMacSystemFont, "SF Pro", "SF Pro Display", system-ui, sans-serif !important;
56
+ -webkit-font-smoothing: antialiased;
57
+ text-rendering: optimizeLegibility;
58
+ }
59
+ #textInput, #textOverlay {
60
+ font-family: "Apple Color Emoji", -apple-system, BlinkMacSystemFont, "SF Pro", "SF Pro Display", system-ui, sans-serif !important;
61
+ }
62
+ `
63
+ });
64
+ }
65
+
66
+ await page.goto('https://www.bratgenerator.com/', {
67
+ waitUntil: 'networkidle',
68
+ timeout: 30000
69
+ });
70
+
71
+ try {
72
+ await page.click('#onetrust-accept-btn-handler', { timeout: 2000 });
73
+ } catch {}
74
+
75
+ await page.evaluate(() => setupTheme('white'));
76
+
77
+ return { browser, page };
78
+ };
79
+
80
+ const utils = {
81
+ async initialize() {
82
+ if (!defaultBrowser) {
83
+ const setup = await createBrowserContext(false);
84
+ defaultBrowser = setup.browser;
85
+ defaultPage = setup.page;
86
+ }
87
+ },
88
+
89
+ async generateBrat(text) {
90
+ await defaultPage.fill('#textInput', text);
91
+ await defaultPage.waitForTimeout(500); // Give time for text to render
92
+ const overlay = defaultPage.locator('#textOverlay');
93
+ return overlay.screenshot({ timeout: 5000 });
94
+ },
95
+
96
+ async close() {
97
+ if (defaultBrowser) await defaultBrowser.close();
98
+ }
99
+ };
100
+
101
+ const utils2 = {
102
+ async initialize() {
103
+ if (!iPhoneBrowser) {
104
+ const setup = await createBrowserContext(true);
105
+ iPhoneBrowser = setup.browser;
106
+ iPhonePage = setup.page;
107
+ }
108
+ },
109
+
110
+ async generateBrat(text) {
111
+ await iPhonePage.fill('#textInput', text);
112
+ await iPhonePage.waitForTimeout(500); // Give time for text to render
113
+ const overlay = iPhonePage.locator('#textOverlay');
114
+ return overlay.screenshot({ timeout: 5000 });
115
+ },
116
+
117
+ async close() {
118
+ if (iPhoneBrowser) await iPhoneBrowser.close();
119
+ }
120
+ };
121
+
122
+ const app = express();
123
+ app.use(express.json());
124
+ app.use(cors());
125
+ app.set('json spaces', 3);
126
+
127
+ app.get('*', async (req, res) => {
128
+ try {
129
+ const { q, type } = req.query;
130
+ if (!q) {
131
+ return res.status(200).json({
132
+ name: 'HD Bart Generator API',
133
+ message: 'Parameter q di perlukan',
134
+ version: '2.1.0',
135
+ runtime: {
136
+ os: os.type(),
137
+ platform: os.platform(),
138
+ architecture: os.arch(),
139
+ cpuCount: os.cpus().length,
140
+ uptime: `${os.uptime()} seconds`,
141
+ memoryUsage: `${Math.round((os.totalmem() - os.freemem()) / 1024 / 1024)} MB used of ${Math.round(os.totalmem() / 1024 / 1024)} MB`
142
+ }
143
+ });
144
+ }
145
+
146
+ const imageBuffer = type === "iphone"
147
+ ? await utils2.generateBrat(q)
148
+ : await utils.generateBrat(q);
149
+
150
+ res.set('Content-Type', 'image/png');
151
+ res.send(imageBuffer);
152
+ } catch (error) {
153
+ console.error(error);
154
+ res.status(500).json({
155
+ status: false,
156
+ message: 'Error generating image',
157
+ error: process.env.NODE_ENV === 'development' ? error.message : undefined
158
+ });
159
+ }
160
+ });
161
+
162
+ const PORT = process.env.PORT || 7860;
163
+
164
+ app.listen(PORT, async () => {
165
+ console.log(`Server running on port ${PORT}`);
166
+ await Promise.all([utils.initialize(), utils2.initialize()]);
167
+ });
168
+
169
+ process.on('SIGINT', async () => {
170
+ await Promise.all([utils.close(), utils2.close()]);
171
+ process.exit(0);
172
+ });