FROM node:20-slim WORKDIR /app RUN cat <<'EOF' > /app/package.json { "name": "gemini-api-server", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "axios": "^1.6.8", "cors": "^2.8.5", "express": "^4.19.2" } } EOF RUN npm install --only=production RUN cat <<'EOF' > /app/index.js const express = require('express'); const cors = require('cors'); const axios = require('axios'); const crypto = require('crypto'); const app = express(); const PORT = 7860; const chatApiUrl = 'https://www.blackbox.ai/api/chat'; const userAgents = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', 'Mozilla/5.0 (Linux; Android 13; SM-S908B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36', 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0' ]; const firstNames = ['Adi', 'Budi', 'Citra', 'Dewi', 'Eka', 'Fajar', 'Gita', 'Hadi', 'Indah', 'Joko']; const lastNames = ['Santoso', 'Wijaya', 'Kusuma', 'Lestari', 'Pratama', 'Nugroho', 'Wahyuni', 'Setiawan']; const getRandomElement = (arr) => arr[Math.floor(Math.random() * arr.length)]; const generateRandomSession = () => { const firstName = getRandomElement(firstNames); const lastName = getRandomElement(lastNames); const name = `${firstName} ${lastName}`; const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}${Math.floor(Math.random() * 1000)}@gmail.com`; const id = (BigInt(10**20) + BigInt(Math.floor(Math.random() * 9 * 10**20))).toString(); const expires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(); return { user: { name, email, image: `https://ui-avatars.com/api/?name=${encodeURIComponent(name)}`, id }, expires, isNewUser: false }; }; const createHeaders = () => { const userAgent = getRandomElement(userAgents); const isMobile = userAgent.includes('Mobile') || userAgent.includes('Android') || userAgent.includes('iPhone'); const platform = userAgent.includes('Win') ? '"Windows"' : userAgent.includes('Mac') ? '"macOS"' : '"Android"'; const chromeVersion = userAgent.match(/Chrome\/(\d+)/)?.[1] || '125'; const headers = { 'Accept': '*/*', 'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7', 'Content-Type': 'application/json', 'Origin': 'https://www.blackbox.ai', 'Referer': 'https://www.blackbox.ai/', 'User-Agent': userAgent, 'Sec-Ch-Ua': `"Google Chrome";v="${chromeVersion}", "Not(A:Brand";v="8", "Chromium";v="${chromeVersion}"`, 'Sec-Ch-Ua-Mobile': isMobile ? '?1' : '?0', 'Sec-Ch-Ua-Platform': platform, 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'Cookie': `sessionId=${crypto.randomUUID()}` }; return { headers, isMobile }; }; const generateId = (size = 7) => { const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; return Array.from({ length: size }, () => alphabet[Math.floor(Math.random() * alphabet.length)]).join(''); }; const createPayload = (prompt, session, isMobile) => { return { messages: [{ role: "user", content: prompt, id: generateId() }], id: generateId(), previewToken: null, userId: crypto.randomUUID(), codeModelMode: true, trendingAgentMode: {}, isMicMode: false, userSystemPrompt: null, maxTokens: 1024, playgroundTopP: null, playgroundTemperature: null, isChromeExt: false, githubToken: "", clickedAnswer2: false, clickedAnswer3: false, clickedForceWebSearch: false, visitFromDelta: false, isMemoryEnabled: false, mobileClient: isMobile, userSelectedModel: null, userSelectedAgent: "VscodeAgent", validated: "a38f5889-8fef-46d4-8ede-bf4668b6a9bb", imageGenerationMode: false, imageGenMode: "autoMode", webSearchModePrompt: false, deepSearchMode: false, promptSelection: "", domains: null, vscodeClient: false, codeInterpreterMode: false, customProfile: { name: "", occupation: "", traits: [], additionalInfo: "", enableNewChats: false }, webSearchModeOption: { autoMode: true, webMode: false, offlineMode: false }, session: session, isPremium: false, subscriptionCache: { status: "FREE", customerId: null, expiryTimestamp: null, lastChecked: Date.now(), isTrialSubscription: false, hasPaymentVerificationFailure: false, verificationFailureTimestamp: null, requiresAuthentication: false }, beastMode: false, reasoningMode: false, designerMode: false, workspaceId: "", asyncMode: false, integrations: {}, isTaskPersistent: false, selectedElement: null }; }; const parseApiResponse = (data) => { const delimiter = '$~~~$'; if (typeof data === 'string' && data.includes(delimiter)) { const parts = data.split(delimiter); try { return parts[2] ? parts[2].trim() : data; } catch { return data; } } return data; }; app.use(cors()); app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ extended: true, limit: '50mb' })); app.post('/api/generate', async (req, res) => { const { prompt } = req.body; if (!prompt) { return res.status(400).json({ error: 'Request body harus menyertakan "prompt"' }); } try { const session = generateRandomSession(); const { headers, isMobile } = createHeaders(); const payload = createPayload(prompt, session, isMobile); const response = await axios.post(chatApiUrl, payload, { headers: headers }); const finalAnswer = parseApiResponse(response.data); res.setHeader('Content-Type', 'text/plain'); res.send(finalAnswer); } catch (error) { console.error("Error pada /api/generate:", error.message); res.status(500).send("Terjadi kesalahan pada server saat memproses permintaan."); } }); app.listen(PORT, () => { console.log(`Server berjalan di http://localhost:${PORT}`); console.log('Endpoint tersedia: POST /api/generate'); }); EOF EXPOSE 7860 CMD ["npm", "start"]