brat / app.js
siputzx's picture
Update app.js
b399b6c verified
raw
history blame
5.38 kB
import express from 'express';
import { chromium } from 'playwright';
import cors from 'cors';
import dotenv from 'dotenv';
import os from 'os';
import sharp from 'sharp';
import path from 'path';
import fs from 'fs';
import crypto from 'crypto';
import { tmpdir } from 'os';
import webp from 'node-webpmux';
dotenv.config();
const config = {
maxTextLength: 100,
viewport: { width: 1920, height: 1080 },
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
metadata: {
packname: "HD Bart Generator",
author: "API",
categories: ["meme"]
}
};
const utils = {
async addExifMetadata(buffer, metadata) {
const tmpFileIn = path.join(tmpdir(), `${crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
const tmpFileOut = path.join(tmpdir(), `${crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
fs.writeFileSync(tmpFileIn, buffer);
const img = new webp.Image();
const json = {
"sticker-pack-id": `https://github.com/DikaArdnt/Hisoka-Morou`,
"sticker-pack-name": metadata.packname,
"sticker-pack-publisher": metadata.author,
"emojis": metadata.categories || [""]
};
const exifAttr = Buffer.from([0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00]);
const jsonBuff = Buffer.from(JSON.stringify(json), "utf-8");
const exif = Buffer.concat([exifAttr, jsonBuff]);
exif.writeUIntLE(jsonBuff.length, 14, 4);
await img.load(tmpFileIn);
fs.unlinkSync(tmpFileIn);
img.exif = exif;
await img.save(tmpFileOut);
const finalBuffer = fs.readFileSync(tmpFileOut);
fs.unlinkSync(tmpFileOut);
return finalBuffer;
},
async createBrowserInstance() {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: config.viewport,
userAgent: config.userAgent
});
await context.route('**/*', (route) => {
const url = route.request().url();
if (url.endsWith('.png') || url.endsWith('.jpg') || url.includes('google-analytics')) {
return route.abort();
}
route.continue();
});
const page = await context.newPage();
await page.goto('https://www.bratgenerator.com/', { waitUntil: 'domcontentloaded', timeout: 10000 });
try {
await page.click('#onetrust-accept-btn-handler', { timeout: 2000 });
} catch { }
await page.evaluate(() => setupTheme('white'));
return { browser, page };
},
async generateBrat(text, metadata) {
const { browser, page } = await this.createBrowserInstance();
try {
await page.fill('#textInput', text);
const overlay = page.locator('#textOverlay');
// Take screenshot and convert to WebP
const pngBuffer = await overlay.screenshot({
timeout: 3000,
type: 'png'
});
const webpBuffer = await sharp(pngBuffer)
.webp({ quality: 80 })
.toBuffer();
// Add EXIF metadata
return await this.addExifMetadata(webpBuffer, metadata);
} finally {
await browser.close();
}
}
};
const app = express();
app.use(express.json());
app.use(cors());
app.get('*', async (req, res) => {
try {
const { q, packname, author } = req.query;
if (!q) {
return res.json({
name: 'HD Bart Generator API',
message: 'Parameter q diperlukan',
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`
},
parameters: {
q: "Teks yang akan ditampilkan (required)",
packname: "Nama pack sticker (optional)",
author: "Nama author sticker (optional)"
}
});
}
// Create metadata object using query parameters or defaults
const metadata = {
packname: packname || config.metadata.packname,
author: author || config.metadata.author,
categories: config.metadata.categories
};
const imageBuffer = await utils.generateBrat(q, metadata);
res.set('Content-Type', 'image/webp');
res.send(imageBuffer);
} catch (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, () => {
console.log(`Server running on port ${PORT}`);
});