| 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"] |