|
const express = require('express'); |
|
const { chromium, devices } = require('playwright'); |
|
const cors = require('cors'); |
|
const dotenv = require('dotenv'); |
|
const os = require('os'); |
|
|
|
dotenv.config(); |
|
|
|
const config = { |
|
maxTextLength: 100, |
|
defaultViewport: { width: 1920, height: 1080 }, |
|
iPhoneViewport: { width: 390, height: 844 } |
|
}; |
|
|
|
let defaultBrowser, defaultPage, iPhoneBrowser, iPhonePage; |
|
|
|
const utils = { |
|
async initialize() { |
|
if (!defaultBrowser) { |
|
defaultBrowser = await chromium.launch({ headless: true }); |
|
const context = await defaultBrowser.newContext({ |
|
viewport: config.defaultViewport |
|
}); |
|
defaultPage = await context.newPage(); |
|
await defaultPage.goto('https://www.bratgenerator.com/', { |
|
waitUntil: 'networkidle' |
|
}); |
|
try { |
|
await defaultPage.click('#onetrust-accept-btn-handler', { timeout: 2000 }); |
|
} catch {} |
|
await defaultPage.evaluate(() => setupTheme('white')); |
|
} |
|
}, |
|
|
|
async generateBrat(text) { |
|
await defaultPage.fill('#textInput', text); |
|
await defaultPage.waitForTimeout(500); |
|
const overlay = defaultPage.locator('#textOverlay'); |
|
return overlay.screenshot({ timeout: 5000 }); |
|
}, |
|
|
|
async close() { |
|
if (defaultBrowser) await defaultBrowser.close(); |
|
} |
|
}; |
|
|
|
const utils2 = { |
|
async initialize() { |
|
if (!iPhoneBrowser) { |
|
iPhoneBrowser = await chromium.launch({ headless: true }); |
|
|
|
|
|
const context = await iPhoneBrowser.newContext({ |
|
...devices['iPhone 13 Pro'], |
|
locale: 'en-US', |
|
deviceScaleFactor: 3, |
|
isMobile: true, |
|
hasTouch: true, |
|
colorScheme: 'light', |
|
forcedColors: 'none', |
|
viewport: config.iPhoneViewport, |
|
userAgent: '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' |
|
}); |
|
|
|
iPhonePage = await context.newPage(); |
|
|
|
|
|
await iPhonePage.route('**/*', async route => { |
|
if (route.request().resourceType() === 'document') { |
|
const response = await route.fetch(); |
|
const text = await response.text(); |
|
const modifiedHtml = text.replace('</head>', |
|
`<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> |
|
<style> |
|
@font-face { |
|
font-family: 'Apple Color Emoji'; |
|
src: local('Apple Color Emoji'); |
|
unicode-range: U+1F300-1F9FF; |
|
} |
|
* { |
|
font-family: -apple-system !important; |
|
} |
|
#textInput, #textOverlay { |
|
font-family: -apple-system !important; |
|
-webkit-text-size-adjust: 100%; |
|
text-size-adjust: 100%; |
|
} |
|
.emoji { |
|
font-family: 'Apple Color Emoji' !important; |
|
} |
|
</style> |
|
</head>` |
|
); |
|
route.fulfill({ |
|
response, |
|
body: modifiedHtml, |
|
headers: { |
|
...response.headers(), |
|
'content-type': 'text/html' |
|
} |
|
}); |
|
} else { |
|
route.continue(); |
|
} |
|
}); |
|
|
|
await iPhonePage.goto('https://www.bratgenerator.com/', { |
|
waitUntil: 'networkidle', |
|
timeout: 30000 |
|
}); |
|
|
|
|
|
await iPhonePage.setViewportSize(config.iPhoneViewport); |
|
|
|
|
|
await iPhonePage.addScriptTag({ |
|
content: ` |
|
function replaceWithEmojiSpans() { |
|
const textInput = document.querySelector('#textInput'); |
|
const textOverlay = document.querySelector('#textOverlay'); |
|
|
|
if (textInput && textOverlay) { |
|
const emojiRegex = /[\u{1F300}-\u{1F9FF}]/gu; |
|
const wrapEmojisWithSpan = (text) => { |
|
return text.replace(emojiRegex, match => |
|
'<span class="emoji">' + match + '</span>' |
|
); |
|
}; |
|
|
|
const originalHandler = textInput.oninput; |
|
textInput.oninput = function(e) { |
|
if (originalHandler) originalHandler.call(this, e); |
|
textOverlay.innerHTML = wrapEmojisWithSpan(this.value); |
|
}; |
|
} |
|
} |
|
replaceWithEmojiSpans(); |
|
` |
|
}); |
|
|
|
try { |
|
await iPhonePage.click('#onetrust-accept-btn-handler', { timeout: 2000 }); |
|
} catch {} |
|
|
|
await iPhonePage.evaluate(() => setupTheme('white')); |
|
} |
|
}, |
|
|
|
async generateBrat(text) { |
|
await iPhonePage.fill('#textInput', text); |
|
|
|
|
|
await iPhonePage.waitForTimeout(1000); |
|
|
|
|
|
await iPhonePage.evaluate((text) => { |
|
const textOverlay = document.querySelector('#textOverlay'); |
|
const emojiRegex = /[\u{1F300}-\u{1F9FF}]/gu; |
|
const wrappedText = text.replace(emojiRegex, match => |
|
'<span class="emoji">' + match + '</span>' |
|
); |
|
textOverlay.innerHTML = wrappedText; |
|
}, text); |
|
|
|
await iPhonePage.waitForTimeout(500); |
|
|
|
const overlay = iPhonePage.locator('#textOverlay'); |
|
return overlay.screenshot({ |
|
timeout: 5000, |
|
scale: 'device' |
|
}); |
|
}, |
|
|
|
async close() { |
|
if (iPhoneBrowser) await iPhoneBrowser.close(); |
|
} |
|
}; |
|
|
|
const app = express(); |
|
app.use(express.json()); |
|
app.use(cors()); |
|
app.set('json spaces', 3); |
|
|
|
app.get('*', async (req, res) => { |
|
try { |
|
const { q, type } = req.query; |
|
if (!q) { |
|
return res.status(200).json({ |
|
name: 'HD Bart Generator API', |
|
message: 'Parameter q di perlukan', |
|
version: '2.1.0', |
|
runtime: { |
|
os: os.type(), |
|
platform: os.platform(), |
|
architecture: os.arch(), |
|
cpuCount: os.cpus().length, |
|
uptime: `${os.uptime()} seconds`, |
|
memoryUsage: `${Math.round((os.totalmem() - os.freemem()) / 1024 / 1024)} MB used of ${Math.round(os.totalmem() / 1024 / 1024)} MB` |
|
} |
|
}); |
|
} |
|
|
|
const imageBuffer = type === "iphone" |
|
? await utils2.generateBrat(q) |
|
: await utils.generateBrat(q); |
|
|
|
res.set('Content-Type', 'image/png'); |
|
res.send(imageBuffer); |
|
} catch (error) { |
|
console.error(error); |
|
res.status(500).json({ |
|
status: false, |
|
message: 'Error generating image', |
|
error: process.env.NODE_ENV === 'development' ? error.message : undefined |
|
}); |
|
} |
|
}); |
|
|
|
const PORT = process.env.PORT || 7860; |
|
|
|
app.listen(PORT, async () => { |
|
console.log(`Server running on port ${PORT}`); |
|
await Promise.all([utils.initialize(), utils2.initialize()]); |
|
}); |
|
|
|
process.on('SIGINT', async () => { |
|
await Promise.all([utils.close(), utils2.close()]); |
|
process.exit(0); |
|
}); |