Ini adalah kode sumber dari proyek saat ini. Gunakan ini sebagai konteks untuk melakukan perubahan yang diminta. // FILE: vercel.json {} --- // FILE: tailwind.config.js /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./app/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", "./public/**/*.html", ], theme: { extend: {}, }, plugins: [], } --- // FILE: postcss.config.js module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } --- // FILE: package.json { "name": "NextA-API", "version": "1.0.0", "description": "Proyek API Publik modular dengan fitur Fast Update via AI - Next.js Version.", "scripts": { "dev": "NODE_PATH=/root/.picoclaw/workspace/scraper-collection/node_modules next dev -p 8080", "build": "NODE_PATH=/root/.picoclaw/workspace/scraper-collection/node_modules next build", "build:full": "node scripts/generate-docs.js && NODE_PATH=/root/.picoclaw/workspace/scraper-collection/node_modules next build", "vercel:build": "node scripts/generate-docs.js && next build", "start": "NODE_PATH=/root/.picoclaw/workspace/scraper-collection/node_modules next start", "lint": "next lint" }, "dependencies": { "axios": "^1.7.2", "axios-cookiejar-support": "^5.0.0", "cheerio": "^1.0.0-rc.12", "cloudscraper": "^4.6.0", "crypto-js": "^4.2.0", "fast-xml-parser": "^4.3.2", "ffmpeg-static": "^5.2.0", "form-data": "^4.0.0", "fs-extra": "^11.2.0", "glob": "^10.5.0", "mime-types": "^2.1.35", "next": "14.2.3", "nprogress": "^0.2.0", "pg": "^8.11.5", "qs": "^6.11.0", "react": "^18", "react-dom": "^18", "react-markdown": "^9.0.1", "react-virtuoso": "^4.7.11", "remark-gfm": "^4.0.0", "tough-cookie": "^4.1.3", "uuid": "^9.0.1", "openai": "^4.0.0" }, "devDependencies": { "autoprefixer": "^10.4.19", "eslint": "^8", "eslint-config-next": "14.2.3", "postcss": "^8.4.38", "tailwindcss": "^3.4.4" } } --- // FILE: next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: false, // Nonaktifkan strict mode untuk menghindari double-invocation pada useEffect di dev (opsional) serverComponentsExternalPackages: ['ffmpeg-static'], experimental: { serverComponentsExternalPackages: ['ffmpeg-static'], // Fallback: beberapa versi Next.js membutuhkan outputFileTracingIncludes di dalam experimental outputFileTracingIncludes: { '/api/chess/stockfish': ['./lib/stockfish/**/*'], 'app/api/chess/stockfish/route': ['./lib/stockfish/**/*'], }, }, // Pastikan stockfish.wasm dan stockfish.js ikut tercopy saat deploy (top-level, Next.js 14+) outputFileTracingIncludes: { // URL path pattern '/api/chess/stockfish': ['./lib/stockfish/**/*'], // File path pattern (untuk beberapa versi Next.js) 'app/api/chess/stockfish/route': ['./lib/stockfish/**/*'], // Wildcard pattern '/api/**': ['./lib/stockfish/**/*'], }, images: { remotePatterns: [ { protocol: 'https', hostname: 'avatars.githubusercontent.com', }, { protocol: 'https', hostname: 'images.unsplash.com', }, { protocol: 'https', hostname: 'cdn.pixabay.com', }, { protocol: 'https', hostname: 'i.pinimg.com', }, { protocol: 'https', hostname: 'raw.githubusercontent.com', }, { protocol: 'https', hostname: 'api.dicebear.com', }, { protocol: 'https', hostname: 'picoclaw.io', }, ], }, async headers() { return [ { // Terapkan header CORS dan Contact ke semua rute API source: "/api/:path*", headers: [ { key: "Access-Control-Allow-Credentials", value: "true" }, { key: "Access-Control-Allow-Origin", value: "*" }, // Izinkan akses dari semua domain { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" }, { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" }, { key: "Contact", value: "https://t.me/puruboy_hub" } // Header kontak tambahan ] } ] }, async rewrites() { return [ { source: '/admin', destination: '/admin.html', }, { source: '/fastupdate', destination: '/fastupdate.html', }, // Mapping endpoint lama agar kompatibel dengan frontend { source: '/download', destination: '/api/fastupdate/download', }, { source: '/update', destination: '/api/fastupdate/update', }, // Fix Favicon untuk Search Engine (Map .ico request ke .jpg) { source: '/favicon.ico', destination: '/favicon.jpg', }, ]; }, }; module.exports = nextConfig; --- // FILE: middleware.js /** * Middleware Global — Next.js 14 (Edge Runtime) * * Meng-intercept SEMUA response API non-200 dan mengirim report ke Telegram. * Juga menangkap error yang terlewat dari try-catch di route handlers. * * Cocok untuk: route yang return non-200 tanpa throw exception * (validasi 400, auth 401, not found 404, dll) * * Runtime: Edge (otomatis oleh Next.js untuk middleware) */ // Rate limiter sederhana (in-memory, reset tiap deploy) const rateLimitMap = new Map(); const RATE_LIMIT_WINDOW = 5 * 60 * 1000; // 5 menit const BOT_TOKEN = '8757256180:AAEFM7NpH1eWRNsV9gTU6s2Vbsg2OdvKFfI'; const CHAT_ID = '7004559855'; /** * Escape HTML untuk Telegram parse_mode */ function escapeHtml(text) { if (!text) return ''; return String(text) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } /** * Kirim pesan ke Telegram via fetch (Edge-compatible) */ async function sendTelegram(message) { try { const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`; const resp = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: CHAT_ID, text: message, parse_mode: 'HTML', disable_web_page_preview: true, }), }); return resp.ok; } catch (err) { console.error('[Middleware] Gagal kirim ke Telegram:', err.message); return false; } } /** * Format pesan error untuk non-200 response */ function formatErrorMessage(status, statusText, endpoint, method, body) { const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19); const emoji = status >= 500 ? 'šŸ”“' : status >= 400 ? '🟔' : '⚪'; let bodyStr = body ? JSON.stringify(body).substring(0, 200) : 'null'; return [ `${emoji} Non-200 Response — Na-api`, ``, `ā± Waktu: ${timestamp}`, `šŸ“ Endpoint: ${escapeHtml(endpoint)}`, `šŸ”§ Method: ${escapeHtml(method)}`, `šŸ“Š Status: ${status} ${escapeHtml(statusText || '')}`, bodyStr !== 'null' ? `\nšŸ“¦ Body:\n
${escapeHtml(bodyStr)}
` : '', ``, `āš ļø Response non-200 terdeteksi oleh middleware`, ].filter(Boolean).join('\n'); } /** * Check rate limit untuk mencegah spam * Key: endpoint + status code */ function isRateLimited(endpoint, status) { const key = `${endpoint}:${status}`; const now = Date.now(); const lastReport = rateLimitMap.get(key); if (lastReport && (now - lastReport) < RATE_LIMIT_WINDOW) { return true; // Still within rate limit window } rateLimitMap.set(key, now); return false; } export async function middleware(request) { const url = request.nextUrl; const pathname = url.pathname; // Hanya intercept API routes if (!pathname.startsWith('/api/')) { return; } // Skip route yang berdurasi panjang (download/konversi video / chess engine) if (pathname.includes('/temp/') || pathname.includes('/media/') || pathname.includes('/chess/')) { return; } // Skip jika method OPTIONS (CORS preflight) if (request.method === 'OPTIONS') { return; } // Clone request untuk dibaca bodynya let requestBody = null; if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method)) { try { const cloned = request.clone(); requestBody = await cloned.json().catch(() => null); } catch (e) { // ignore } } // Lanjutkan request ke handler const response = await fetch(request); // Jika response OK (2xx), tidak perlu report if (response.status >= 200 && response.status < 300) { return response; } // --- Non-200 response --- // Rate limiting: jangan spam untuk error yang sama if (isRateLimited(pathname, response.status)) { return response; // Skip report, return response as-is } // Ambil response body untuk context let responseBody = null; let isHtmlResponse = false; try { const cloned = response.clone(); const contentType = cloned.headers.get('content-type') || ''; isHtmlResponse = contentType.includes('text/html'); if (isHtmlResponse) { // HTML response (default Next.js error page) → baca sebagai text responseBody = await cloned.text().then(t => t.substring(0, 300)); } else { responseBody = await cloned.json().catch(() => null); } } catch (e) { // ignore } // Format & kirim ke Telegram (fire-and-forget) const message = formatErrorMessage( response.status, response.statusText, pathname, request.method, requestBody || responseBody ); // Fire and forget — jangan blokir response sendTelegram(message).catch(() => {}); // Log ke console console.error(`[Middleware] Non-200: ${pathname} | ${request.method} | ${response.status}`); // šŸŽÆ Jika response berupa HTML (default Next.js error page), // konversi ke JSON biar API selalu konsisten if (isHtmlResponse) { const statusTextMap = { 400: 'Bad Request', 401: 'Unauthorized', 403: 'Forbidden', 404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable', 408: 'Request Timeout', 409: 'Conflict', 410: 'Gone', 411: 'Length Required', 413: 'Payload Too Large', 415: 'Unsupported Media Type', 422: 'Unprocessable Entity', 429: 'Too Many Requests', 500: 'Internal Server Error', 502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout', }; const hint = response.status === 405 ? `This endpoint does not support ${request.method}. Check the documentation for supported methods.` : null; return new Response(JSON.stringify({ success: false, error: statusTextMap[response.status] || `HTTP ${response.status}`, ...(hint ? { hint } : {}), status: response.status, }), { status: response.status, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, }); } return response; } // Hanya aktif untuk /api/* routes export const config = { matcher: '/api/:path*', }; --- // FILE: instrumentation.js /** * Instrumentation — Next.js server-side initialization * Auto-load error monitor untuk global error catching */ export async function register() { // Only run on server if (typeof window !== 'undefined') return; try { const { reportError } = await import('./lib/errorLogger'); // Unhandled Promise rejections process.on('unhandledRejection', (reason) => { const error = reason instanceof Error ? reason : new Error(String(reason)); reportError(error, { endpoint: 'GLOBAL/unhandledRejection', method: 'PROMISE', }); }); // Uncaught exceptions process.on('uncaughtException', (error) => { reportError(error, { endpoint: 'GLOBAL/uncaughtException', method: 'UNCAUGHT', }); }); console.log('[Instrumentation] Error monitor registered āœ…'); } catch (err) { console.error('[Instrumentation] Gagal register error monitor:', err.message); } } --- // FILE: git-push.js const { execSync } = require('child_process'); const fs = require('fs'); const dir = '/root/.picoclaw/workspace/na-api'; const memoryRaw = fs.readFileSync('/root/.picoclaw/workspace/memory/MEMORY.md', 'utf8'); const tokenMatch = memoryRaw.match(/\| github_token_na_api \| (.+?) \|/); const token = tokenMatch ? tokenMatch[1] : null; if (!token) { console.error('Token not found'); process.exit(1); } execSync('git add -A', { cwd: dir }); execSync('git -c user.name=picoclaw -c user.email=picoclaw@users.noreply.github.com commit -m "feat: tambah endpoint loadtest stockfish untuk debugging"', { cwd: dir }); execSync(`git remote set-url origin "https://picoclaw:${token}@github.com/purujawa06-bot/Na-api.git"`, { cwd: dir }); execSync('git push origin main', { cwd: dir, stdio: 'inherit' }); execSync('git remote set-url origin https://github.com/purujawa06-bot/Na-api.git', { cwd: dir }); console.log('Push selesai!'); --- // FILE: scripts/rebuild-docs.js const { scanDocs } = require('/root/.picoclaw/workspace/Na-api/lib/docsService'); const path = require('path'); const fse = require('fs-extra'); scanDocs().then(async (spec) => { const outputPath = '/root/.picoclaw/workspace/Na-api/public/docs.json'; await fse.ensureDir(path.dirname(outputPath)); await fse.writeJson(outputPath, spec, { spaces: 2 }); console.log('āœ… docs.json regenerated successfully!'); console.log('šŸ“Š Categories:', Object.keys(spec).length); // Show gemini-v3 entry for (const [cat, eps] of Object.entries(spec)) { for (const ep of eps) { if (ep.path && ep.path.includes('gemini-v3')) { console.log('\n=== Gemini V3 Docs Entry ==='); console.log(JSON.stringify(ep, null, 2)); } } } }).catch(e => console.error('āŒ Error:', e)); Updated `vercel:build` script in `Na-api/package.json` āœ… --- // FILE: scripts/patch-routes.js #!/usr/bin/env node /** * Patch Routes — Auto-inject errorLogger ke semua API route files * * Cara pakai: node scripts/patch-routes.js */ const fs = require('fs'); const path = require('path'); const API_DIR = path.join(__dirname, '..', 'app', 'api'); /** * Hitung jumlah "../" untuk import dari route.js ke lib/errorLogger * Formula: jumlah folder dari 'app/api/' ke file + 2 (untuk app/ dan api/) */ function getImportDepth(routePath) { // routePath relative to API_DIR, misal: "search/youtube/route.js" atau "blogs/route.js" const normalized = routePath.replace(/\\/g, '/'); const parts = normalized.split('/'); // parts = ["search", "youtube", "route.js"] // jumlah folder (exclude route.js) = parts.length - 1 const folderCount = parts.length - 1; // exclude route.js return folderCount + 2; // +2 untuk app/ dan api/ } function getImportPath(routePath) { const depth = getImportDepth(routePath); return '../'.repeat(depth) + 'lib/errorLogger'; } /** * Dapatkan nama endpoint dari path relatif */ function getEndpointName(routePath) { let name = '/' + routePath.replace(/\/route\.js$/, ''); // Convert [param] ke :param name = name.replace(/\[(.+?)\]/g, ':$1'); return name; } async function patchFile(filePath) { let content = fs.readFileSync(filePath, 'utf-8'); const original = content; // Skip if already patched if (content.includes("from '") && content.includes("errorLogger")) { console.log(` ā­ļø Already patched: ${path.relative(API_DIR, filePath)}`); return false; } const relPath = path.relative(API_DIR, filePath); const importPath = getImportPath(relPath); const endpointName = getEndpointName(relPath); const importLine = `import { reportError } from '${importPath}';`; // 1. Add import after the last import statement const lines = content.split('\n'); let lastImportIdx = -1; for (let i = 0; i < lines.length; i++) { if (lines[i].trim().startsWith('import ')) { lastImportIdx = i; } } if (lastImportIdx >= 0) { lines.splice(lastImportIdx + 1, 0, importLine); } else { lines.unshift(importLine); } content = lines.join('\n'); // 2. Find all catch blocks and inject reportError // We'll find patterns like: catch (error) { ... return NextResponse.json ... // And inject reportError right after the opening brace let result = ''; let remaining = content; let catchCount = 0; while (remaining.length > 0) { const catchMatch = remaining.match(/catch\s*\(\s*(\w+)\s*\)\s*\{/); if (!catchMatch) { result += remaining; break; } const catchVar = catchMatch[1]; const beforeCatch = remaining.substring(0, catchMatch.index); // Find the HTTP method for this catch block (look backwards) const beforeText = beforeCatch; const methodRegex = /export\s+async\s+function\s+(GET|POST|PUT|DELETE|PATCH)\s*\(/g; let methodMatch; let method = 'UNKNOWN'; while ((methodMatch = methodRegex.exec(beforeText)) !== null) { method = methodMatch[1]; } // Count braces from catch { to find the matching } let braceCount = 1; let pos = catchMatch.index + catchMatch[0].length; while (braceCount > 0 && pos < remaining.length) { if (remaining[pos] === '{') braceCount++; else if (remaining[pos] === '}') braceCount--; pos++; } const catchBlockEnd = pos - 1; // position of the closing } const catchBlockContent = remaining.substring(catchMatch.index + catchMatch[0].length, catchBlockEnd); // Build the modified catch block const reportCall = `\n // Auto-report error ke Telegram\n reportError(${catchVar}, { endpoint: '${endpointName}', method: '${method}' }).catch(() => {});\n`; const newCatchBlock = `catch (${catchVar}) {${reportCall}${catchBlockContent}}`; result += beforeCatch + newCatchBlock; remaining = remaining.substring(catchBlockEnd + 1); catchCount++; } content = result; // 3. Write if changed if (content !== original) { fs.writeFileSync(filePath, content, 'utf-8'); // Get method names const methods = []; const methodNames = content.match(/export\s+async\s+function\s+(GET|POST|PUT|DELETE|PATCH)/g); if (methodNames) { methodNames.forEach(m => { const match = m.match(/(GET|POST|PUT|DELETE|PATCH)/); if (match) methods.push(match[1]); }); } console.log(` āœ… [${methods.join(',')}] ${relPath}`); return true; } console.log(` āš ļø No changes: ${relPath}`); return false; } async function main() { console.log('šŸ”§ Na-api Error Logger Patcher\n'); console.log(`šŸ“ API Directory: ${API_DIR}\n`); // Find all route.js files const routeFiles = []; function walkDir(dir) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { walkDir(fullPath); } else if (entry.name === 'route.js') { routeFiles.push(fullPath); } } } walkDir(API_DIR); console.log(`šŸ“¦ Found ${routeFiles.length} route files\n`); let patched = 0; let skipped = 0; for (const filePath of routeFiles) { try { const changed = await patchFile(filePath); if (changed) patched++; else skipped++; } catch (err) { console.error(` āŒ Error: ${path.relative(API_DIR, filePath)} - ${err.message}`); } } console.log(`\n✨ Done! ${patched} files patched, ${skipped} files skipped.`); } main().catch(console.error); --- // FILE: scripts/generate-docs.js const { scanDocs } = require('../lib/docsService'); const fse = require('fs-extra'); const path = require('path'); (async () => { console.log('šŸš€ Starting API Documentation Generation...'); try { const spec = await scanDocs(); // Output ke folder public agar bisa diakses/dibaca di runtime production const outputPath = path.join(process.cwd(), 'public', 'docs.json'); await fse.ensureDir(path.dirname(outputPath)); await fse.writeJson(outputPath, spec, { spaces: 2 }); console.log(`āœ… Success! docs.json generated at: ${outputPath}`); console.log(`šŸ“Š Stats: Found ${Object.keys(spec).length} categories.`); } catch (err) { console.error('āŒ Failed to generate docs:', err); process.exit(1); } })(); --- // FILE: public/manifest.json { "name": "PuruBoy API", "short_name": "PuruBoy API", "description": "Platform REST API gratis untuk developer Indonesia dengan fitur AI, Downloader, Anime, dan Tools.", "start_url": "/", "display": "standalone", "background_color": "#09090b", "theme_color": "#ec4899", "icons": [ { "src": "/favicon.jpg", "sizes": "192x192", "type": "image/jpeg" }, { "src": "/favicon.jpg", "sizes": "512x512", "type": "image/jpeg" } ], "categories": ["developer tools", "web services", "api"], "lang": "id", "orientation": "any" } --- // FILE: public/google41f3f05fef8cd977.html google-site-verification: google41f3f05fef8cd977.html --- // FILE: public/fastupdate.html System Updater

Fast Update

AI-Powered Code Implementation

1
2
3

Context Extraction

Download the latest source code to give full context to the AI.

Download Context

Prompt Generation

Apply Changes

--- // FILE: public/docs.json { "ai": [ { "title": "ChatBotChatApp AI", "summary": "Chat AI via ChatBotChatApp.com.", "description": "Berinteraksi dengan model AI melalui layanan scraping ChatBotChatApp.", "method": "POST", "path": "/api/ai/chatbotchatapp", "responseType": "json", "example": "async function chat() {\n const res = await fetch('/api/ai/chatbotchatapp', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"message\": \"Halo, apa kabar?\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan yang ingin diajukan ke AI.", "required": true }, { "name": "model", "in": "body", "type": "string", "description": "Model AI (auto, gpt5, gpt_oss, deepseek_r1, deepseek_v3, qwen_35, mistral_large3, pixtral, devstral2).", "required": false } ] }, { "title": "Chat Espanyol", "summary": "Chat AI (ChatEspanyol).", "description": "Melakukan percakapan dengan AI dari ChatEspanyolGratis. Mendukung percakapan berkelanjutan dengan menyertakan `sessionId` dan `conversationUuid`.", "method": "POST", "path": "/api/ai/chatespanyol", "responseType": "json", "example": "async function chat() {\n try {\n const response = await fetch('/api/ai/chatespanyol', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"message\": \"Halo Kawanku\" \n })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error);\n }\n }\n \n chat();", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan yang ingin dikirim ke AI.", "required": true }, { "name": "sessionId", "in": "body", "type": "string", "description": "ID sesi untuk menjaga konteks percakapan (opsional).", "required": false }, { "name": "conversationUuid", "in": "body", "type": "string", "description": "UUID percakapan (opsional).", "required": false } ] }, { "title": "DeepSeek R1 - AI Chat Legacy", "summary": "Chat dengan model DeepSeek R1 (legacy, via chatgot.io).", "description": "DeepSeek R1 dengan reasoning, menggunakan proxy chatgot.io. Streaming SSE, support reasoning + content.", "method": "POST", "path": "/api/ai/deepseek", "responseType": "json", "example": "fetch('https://puruboy-api.vercel.app/api/ai/deepseek', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n prompt: 'Jelaskan teori relativitas secara singkat'\n })\n }).then(res => res.json()).then(console.log);", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Pertanyaan untuk AI (wajib).", "required": true } ] }, { "title": "DeepSeek V4 - Free AI Chat", "summary": "Chat AI gratis via deep-seek.ai (proxy OpenRouter).", "description": "Mengirim pesan ke DeepSeek AI secara gratis melalui deep-seek.ai. Mendukung model DeepSeek V4 Flash, R1, dan V3. Semua response menggunakan SSE (Server-Sent Events) dengan reasoning visible.", "method": "POST", "path": "/api/ai/deepseek/v4", "responseType": "json", "example": "fetch('https://puruboy-api.vercel.app/api/ai/deepseek/v4', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n message: 'Buatkan saya kalkulator sederhana di Python',\n model: 'deepseek/deepseek-v4-flash',\n history: []\n })\n }).then(res => res.json()).then(console.log);", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan untuk AI (wajib).", "required": true }, { "name": "model", "in": "body", "type": "string", "description": "Model yang digunakan. (opsional)", "required": false, "choices": [ { "value": "deepseek/deepseek-v4-flash", "label": "DeepSeek V4 Flash (Cepat & Efisien)" }, { "value": "deepseek/deepseek-r1", "label": "DeepSeek R1 (Reasoning Mendalam)" }, { "value": "deepseek/deepseek-v3.2", "label": "DeepSeek V3 (Balanced)" } ] }, { "name": "history", "in": "body", "type": "array", "description": "Riwayat percakapan [{role, content}] (opsional)", "required": false } ] }, { "title": "Dracin TTS (SSE)", "summary": "AI Voice gaya Drama China (Dracin) dengan SSE fakta unik.", "description": "Mengubah teks menjadi suara dengan nada ala narator drama China. Menggunakan SSE (Server-Sent Events) untuk mengirim fakta unik random selama proses generating audio.", "method": "POST", "path": "/api/ai/dracin", "responseType": "json", "example": "// Contoh request\n const res = await fetch('/api/ai/dracin', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n \"text\": \"Halo, selamat datang di dunia drama China.\",\n \"music\": true,\n \"speed\": 1.0,\n \"volume\": 0.3\n })\n });\n // Response berupa SSE Stream:\n // event: status { \"message\": \"Memproses teks menjadi suara...\" }\n // event: fact { \"fact\": \"Kumis kucing...\" }\n // event: status { \"message\": \"Mengupload audio...\" }\n // event: result { \"success\": true, \"result\": { \"text\": \"...\", \"audio\": \"...\" } }", "params": [ { "name": "text", "in": "body", "type": "string", "description": "Teks yang akan diubah menjadi suara.", "required": true }, { "name": "music", "in": "body", "type": "boolean", "description": "Menggunakan musik latar? Default: true.", "required": false }, { "name": "speed", "in": "body", "type": "number", "description": "Kecepatan bicara (0.5 - 2.0). Default: 1.0.", "required": false }, { "name": "volume", "in": "body", "type": "number", "description": "Volume musik latar (0.1 - 1.0). Default: 0.3.", "required": false } ] }, { "title": "Flux V2 - Image Generator", "summary": "Generate Gambar Flux (HF Space).", "description": "Menghasilkan gambar menggunakan model FLUX Pro dari HF Space (llamameta-fake-flux-pro-unlimited). Gratis tanpa API key, menggunakan antrian Gradio. Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/ai/flux-v2", "responseType": "json", "example": "// Contoh penggunaan (Membaca stream SSE di client)\n async function generateImage() {\n const response = await fetch('/api/ai/flux-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"prompt\": \"Kucing lucu pakai topi, realistik\",\n \"model\": \"turbo\"\n })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n console.log(\"Stream:\", text);\n \n if(text.includes('[true]')) {\n const resultUrl = text.replace('[true]', '').trim();\n console.log(\"Result JSON URL:\", resultUrl);\n // fetch(resultUrl).then(res => res.json()).then(console.log);\n }\n }\n }\n \n generateImage();", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Deskripsi gambar yang ingin dibuat (wajib).", "required": true }, { "name": "model", "in": "body", "type": "string", "description": "Model yang digunakan. (opsional)", "required": false, "choices": [ { "value": "turbo", "label": "Turbo (Cepat)" }, { "value": "standard", "label": "Standard (Detail)" }, { "value": "hd", "label": "HD (High Quality)" } ] } ] }, { "title": "Gemini AI Chat", "summary": "Chat via Google Gemini (Proxy).", "description": "Berinteraksi dengan Google Gemini menggunakan browser automation.", "method": "POST", "path": "/api/ai/gemini", "responseType": "json", "example": "async function chatGemini() {\n const response = await fetch('/api/ai/gemini', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"prompt\": \"Halo Gemini!\" })\n });\n \n const data = await response.json();\n console.log(data);\n }", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Pertanyaan yang ingin diajukan ke Gemini.", "required": true } ] }, { "title": "Gemini AI V2", "summary": "Chat via Google Gemini (BatchExecute).", "description": "Berinteraksi dengan Google Gemini menggunakan metode BatchExecute yang lebih stabil untuk pertanyaan tunggal.", "method": "POST", "path": "/api/ai/gemini-v2", "responseType": "json", "example": "async function chatGemini() {\n const response = await fetch('/api/ai/gemini-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"prompt\": \"Halo Gemini!\" })\n });\n \n const data = await response.json();\n console.log(data);\n }", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Pertanyaan yang ingin diajukan ke Gemini.", "required": true } ] }, { "title": "Gemini AI V3", "summary": "Chat via Google Gemini (Hybrid V2+V1 Fallback) — format payload standar Gemini API.", "description": "Menerima format payload standar Google Gemini API dan mengembalikan response JSON murni dari Gemini SDK. Menggabungkan metode V2 (BatchExecute) dan V1 (StreamGenerate) dengan fallback otomatis. Maksimal 3 kali percobaan. Response adalah data ASLI dari Gemini (raw JSON SDK), bukan wrapper buatan.", "method": "POST", "path": "/api/ai/gemini-v3", "responseType": "json", "example": "# RAW Format — Langsung executable via curl:\n curl -X POST \"https://puruboy-api.vercel.app/api/ai/gemini-v3\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n { \"text\": \"Halo! Siapa presiden Indonesia pertama?\" }\n ]\n }\n ],\n \"systemInstruction\": {\n \"parts\": [\n { \"text\": \"Kamu adalah asisten AI yang cerdas, ramah, dan menjawab dengan singkat.\" }\n ]\n },\n \"generationConfig\": {\n \"temperature\": 0.7,\n \"topP\": 0.9,\n \"topK\": 40\n }\n }'", "params": [ { "name": "contents", "in": "body", "type": "Array", "description": "Array of content objects (role + parts). Riwayat percakapan. Minimal 1 item.", "required": true }, { "name": "systemInstruction", "in": "body", "type": "Object", "description": "System instruction untuk mengatur perilaku AI. Berisi `parts` array.", "required": false }, { "name": "generationConfig", "in": "body", "type": "Object", "description": "Konfigurasi generation (temperature, topP, topK, dll).", "required": false } ], "guide": "## Format Payload (RAW — Standar Gemini API)\n \n Kirim payload **RAW JSON** langsung ke endpoint. Contoh siap eksekusi:\n \n ### šŸ”¹ Single-turn (pertanyaan tunggal)\n \n ```bash\n curl -X POST \"https://puruboy-api.vercel.app/api/ai/gemini-v3\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"contents\": [\n {\n \"role\": \"user\",\n \"parts\": [\n { \"text\": \"Halo! Siapa presiden Indonesia pertama?\" }\n ]\n }\n ],\n \"systemInstruction\": {\n \"parts\": [\n { \"text\": \"Kamu adalah asisten AI yang cerdas, ramah, dan menjawab dengan singkat.\" }\n ]\n },\n \"generationConfig\": {\n \"temperature\": 0.7,\n \"topP\": 0.9,\n \"topK\": 40\n }\n }'\n ```\n \n ### šŸ”¹ Multi-turn (percakapan dengan konteks)\n \n ```bash\n curl -X POST \"https://puruboy-api.vercel.app/api/ai/gemini-v3\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"contents\": [\n { \"role\": \"user\", \"parts\": [{ \"text\": \"Halo, nama saya Budi\" }] },\n { \"role\": \"model\", \"parts\": [{ \"text\": \"Halo Budi! Ada yang bisa saya bantu?\" }] },\n { \"role\": \"user\", \"parts\": [{ \"text\": \"Siapa nama saya?\" }] }\n ],\n \"generationConfig\": {\n \"temperature\": 0.3\n }\n }'\n ```\n \n ---\n \n ## ⚔ RAW Internal RPC Payload (batchexecute)\n \n Di belakang layar, endpoint ini mengirim request ke Google Gemini via protokol **batchexecute** dengan format RAW berikut:\n \n ```\n POST https://gemini.google.com/_/BardChatUi/data/batchexecute\n Content-Type: application/x-www-form-urlencoded;charset=UTF-8\n \n f.req=[[[\"q4uTj\",\"[null,\\\"{\\\\\\\"contents\\\\\\\":[...]}\\\",1,\\\"caea8d35955a\\\"]\",null,\"generic\"]]]&at=\n ```\n \n ### Struktur RPC Array:\n \n | Level | Data | Keterangan |\n |-------|------|------------|\n | 1 | `f.req` | Array RPC eksternal (`[[[\"q4uTj\", ...]]]`) |\n | 2 | `q4uTj` | Method identifier untuk Gemini chat |\n | 3 | Inner array | `[null, stringifiedRequestBody, 1, \"caea8d35955a\"]` |\n | 4 | `at` | Token `SNlM0e` (kosong/tidak diperlukan) |\n \n ---\n \n ## Response Format (RAW Gemini SDK)\n \n Response adalah **JSON murni dari Gemini SDK** — bukan wrapper buatan. Contoh:\n \n ```json\n {\n \"candidates\": [\n {\n \"content\": {\n \"parts\": [\n { \"text\": \"Presiden pertama Indonesia adalah Ir. Soekarno.\" }\n ],\n \"role\": \"model\"\n },\n \"finishReason\": \"STOP\",\n \"index\": 0,\n \"safetyRatings\": [\n { \"category\": \"HARM_CATEGORY_HARASSMENT\", \"probability\": \"NEGLIGIBLE\" },\n { \"category\": \"HARM_CATEGORY_HATE_SPEECH\", \"probability\": \"NEGLIGIBLE\" }\n ]\n }\n ],\n \"usageMetadata\": {\n \"promptTokenCount\": 15,\n \"candidatesTokenCount\": 25,\n \"totalTokenCount\": 40\n }\n }\n ```\n \n ## Catatan Penting\n \n - **Field `contents` wajib** diisi minimal 1 item dengan `role: \"user\"`.\n - **Format sudah standar Gemini API** — bisa pakai SDK Google langsung.\n - **Auto retry** 3x dengan fallback V2 → V1 → V2 jika salah satu metode gagal.\n - **Tidak perlu API key** — gratis." }, { "title": "Grok-4 Chat", "summary": "Chat AI Grok-4 Fast.", "description": "Berinteraksi dengan model Grok-4 Fast melalui ToolBaz. Model ini dikenal cepat dalam memberikan respons.", "method": "POST", "path": "/api/ai/grok", "responseType": "json", "example": "async function chat() {\n try {\n const response = await fetch('/api/ai/grok', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"message\": \"Siapa pencipta bahasa pemrograman JavaScript?\" \n })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error);\n }\n }\n \n chat();", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan yang ingin dikirim ke AI.", "required": true } ] }, { "title": "LetMeGPT AI", "summary": "Chat AI via LetMeGPT.", "description": "Berinteraksi dengan model AI melalui layanan scraping LetMeGPT.", "method": "POST", "path": "/api/ai/letmegpt", "responseType": "json", "example": "async function chat() {\n const res = await fetch('/api/ai/letmegpt', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"message\": \"Siapa namamu?\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan yang ingin diajukan ke AI.", "required": true } ] }, { "title": "Monica AI Chat (Simplified)", "summary": "Chat AI Monica — cukup kirim prompt saja.", "description": "Endpoint chat Monica AI yang sudah disederhanakan.\n Hanya menerima prompt, sisanya otomatis.", "method": "POST", "path": "/api/ai/monica", "responseType": "json", "example": "fetch('/api/ai/monica', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"prompt\": \"Halo, apa kabar?\" })\n })", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Pesan yang ingin dikirim ke AI (wajib).", "required": true } ] }, { "title": "NoteGPT AI", "summary": "NoteGPT Multi-Model AI Chat.", "description": "Berinteraksi dengan berbagai model AI melalui NoteGPT (Gemini, DeepSeek, GPT). Mendukung fitur \"Deep Think\" (Reasoning) dan IP Spoofing untuk melewati limitasi. Endpoint ini menggunakan Server-Sent Events (SSE) untuk streaming output.", "method": "POST", "path": "/api/ai/notegpt", "responseType": "json", "example": "async function askNoteGPT() {\n const response = await fetch('/api/ai/notegpt', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"prompt\": \"Jelaskan cara kerja kuantum komputer secara sederhana\",\n \"model\": \"TA/deepseek-ai/DeepSeek-R1\",\n \"chat_mode\": \"deep_think\"\n })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n // Format SSE: data: {\"reasoning\": \"...\", \"text\": \"...\"}\n console.log(text);\n }\n }", "params": [ { "name": "prompt", "in": "body", "type": "string", "description": "Pertanyaan atau instruksi untuk AI.", "required": true }, { "name": "model", "in": "body", "type": "string", "description": "Pilihan model: 'gemini-3-flash-preview' (default), 'TA/deepseek-ai/DeepSeek-R1', 'gpt-5-mini'.", "required": false }, { "name": "chat_mode", "in": "body", "type": "string", "description": "Mode percakapan: 'standard' (default), 'deep_think', 'guided_learning'.", "required": false } ] }, { "title": "Quillbot AI Chat", "summary": "Chat via Quillbot AI (Stream).", "description": "Berinteraksi dengan model AI Quillbot yang mendukung streaming response. Berguna untuk menjawab pertanyaan, melakukan parafrase, atau riset teks. Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/ai/quillbot", "responseType": "json", "example": "// Contoh penggunaan SSE di Client\n async function askQuillbot() {\n const response = await fetch('/api/ai/quillbot', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"message\": \"Apa itu pemrograman fungsional?\"\n })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n console.log(text);\n }\n }", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan atau perintah yang ingin dikirim ke AI.", "required": true } ] }, { "title": "ScreenApp Vision", "summary": "AI Image Analysis (Gemini).", "description": "Menganalisis gambar dan menjawab pertanyaan terkait gambar tersebut menggunakan model Gemini 2.0 Flash via ScreenApp proxy. Mendukung analisis visual yang detail.", "method": "POST", "path": "/api/ai/screenapp", "responseType": "json", "example": "async function askImage() {\n const res = await fetch('/api/ai/screenapp', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n \"url\": \"https://puruboy-api.vercel.app/favicon.jpg\",\n \"question\": \"Jelaskan gambar ini dengan detail\"\n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik gambar yang akan dianalisis.", "required": true }, { "name": "question", "in": "body", "type": "string", "description": "Pertanyaan tentang gambar tersebut.", "required": true } ] }, { "title": "Svara TTS", "summary": "Membuat audio dari teks (TTS) dengan Svara AI.", "description": "Menghasilkan file audio dari teks yang diberikan menggunakan berbagai pilihan suara. Credit: Daffa dari nbscript.", "method": "POST", "path": "/api/ai/svara", "responseType": "json", "example": "// Contoh penggunaan\n async function generateSpeech() {\n try {\n const response = await fetch('/api/ai/svara', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"text\": \"Halo, selamat datang di NextA API.\",\n \"voice\": \"bella\" \n })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error(\"Gagal melakukan permintaan:\", error.message);\n }\n }", "params": [ { "name": "text", "in": "body", "type": "string", "description": "Teks yang akan diubah menjadi suara (maksimal 300 karakter).", "required": true }, { "name": "voice", "in": "body", "type": "string", "description": "Nama suara yang akan digunakan. Contoh: 'bella', 'adam', 'arjun'.", "required": true } ] }, { "title": "Translapp AI", "summary": "AI Text Processing dengan Translapp.", "description": "Memproses teks dengan berbagai modul AI seperti ringkasan, parafrase, terjemahan, penyesuaian nada, dll.", "method": "POST", "path": "/api/ai/translapp", "responseType": "json", "example": "async function processText() {\n try {\n const response = await fetch('/api/ai/translapp', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"text\": \"Hello, how are you?\",\n \"module\": \"TRANSLATE\", \n \"to\": \"jawa\"\n })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error);\n }\n }\n \n processText();", "params": [ { "name": "text", "in": "body", "type": "string", "description": "Teks yang akan diproses.", "required": true }, { "name": "module", "in": "body", "type": "string", "description": "Modul pemrosesan: SUMMARIZE, PARAPHRASE, EXPAND, TONE, TRANSLATE, REPLY, GRAMMAR.", "required": true }, { "name": "to", "in": "body", "type": "string", "description": "Parameter tambahan tergantung modul (bahasa target untuk TRANSLATE, nada untuk TONE, dll).", "required": false }, { "name": "customTone", "in": "body", "type": "string", "description": "Nada kustom jika memilih TONE dengan opsi \"Other\".", "required": false } ] }, { "title": "Tsundere TTS", "summary": "AI Voice dengan gaya Tsundere.", "description": "Mengubah teks menjadi suara dengan nada Tsundere (ketus/malu-malu) menggunakan model Gemini TTS. Mengembalikan URL audio hasil proses.", "method": "POST", "path": "/api/ai/tsundere", "responseType": "json", "example": "async function speakTsundere() {\n const res = await fetch('/api/ai/tsundere', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"text\": \"Bukannya aku menyukaimu ya, dasar baka!\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "text", "in": "body", "type": "string", "description": "Teks yang akan diubah menjadi suara.", "required": true } ] }, { "title": "Unlimited AI", "summary": "Unlimited AI Chat.", "description": "Berinteraksi dengan model AI Unlimited (Reasoning) yang mendukung streaming response. Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/ai/unlimited", "responseType": "json", "example": "async function chat() {\n const response = await fetch('/api/ai/unlimited', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"message\": \"Buatkan cerita pendek\"\n })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n console.log(text);\n }\n }", "params": [ { "name": "message", "in": "body", "type": "string", "description": "Pesan yang ingin dikirim ke AI.", "required": true } ] } ], "anime": [ { "title": "Anichin Detail", "summary": "Detail Donghua Anichin.", "description": "Mengambil informasi lengkap seri donghua dari Anichin, termasuk sinopsis, genre, link batch, dan daftar episode.", "method": "GET", "path": "/api/anime/anichin/detail", "responseType": "json", "example": "async function getDetail() {\n const res = await fetch('/api/anime/anichin/detail?url=/seri/battle-through-the-heavens-season-5/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "Path atau URL donghua (contoh: /seri/battle-through-the-heavens-season-5/).", "required": true } ] }, { "title": "Anichin By Genre", "summary": "Donghua By Genre.", "description": "Mengambil daftar donghua berdasarkan slug genre tertentu dari Anichin. Mendukung pagination.", "method": "GET", "path": "/api/anime/anichin/genre", "responseType": "json", "example": "async function getByGenre() {\n const res = await fetch('/api/anime/anichin/genre?slug=fantasy');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "slug", "in": "query", "type": "string", "description": "Slug genre (contoh: \"fantasy\", \"action\").", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false } ] }, { "title": "Anichin Genre List", "summary": "Daftar Genre Anichin.", "description": "Mengambil daftar semua genre donghua yang tersedia di Anichin beserta slug-nya.", "method": "GET", "path": "/api/anime/anichin/genres", "responseType": "json", "example": "async function getGenres() {\n const res = await fetch('/api/anime/anichin/genres');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Anichin Home", "summary": "Beranda Anichin.", "description": "Mengambil data dari halaman utama Anichin, mencakup featured slider, populer hari ini, rilis terbaru, dan update sidebar.", "method": "GET", "path": "/api/anime/anichin/home", "responseType": "json", "example": "async function getHome() {\n const res = await fetch('/api/anime/anichin/home');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Anichin Schedule", "summary": "Jadwal Rilis Anichin.", "description": "Mengambil jadwal rilis donghua mingguan di Anichin.", "method": "GET", "path": "/api/anime/anichin/schedule", "responseType": "json", "example": "async function getSchedule() {\n const res = await fetch('/api/anime/anichin/schedule');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Anichin Search", "summary": "Pencarian Anichin.", "description": "Mencari seri donghua di Anichin berdasarkan kata kunci.", "method": "GET", "path": "/api/anime/anichin/search", "responseType": "json", "example": "async function search() {\n const res = await fetch('/api/anime/anichin/search?q=Btth');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"Btth\").", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false } ] }, { "title": "Anichin Stream", "summary": "Link Streaming Anichin.", "description": "Mengekstrak link streaming (iframe), link download per resolusi, dan navigasi (prev/next) episode dari Anichin.", "method": "GET", "path": "/api/anime/anichin/stream", "responseType": "json", "example": "async function getStream() {\n const res = await fetch('/api/anime/anichin/stream?url=/battle-through-the-heavens-season-5-episode-01-subtitle-indonesia/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "Path atau URL episode (contoh: /battle-through-the-heavens-season-5-episode-01-subtitle-indonesia/).", "required": true } ] }, { "title": "Komiku Detail", "summary": "Detail Komik.", "description": "Mengambil informasi detail dan daftar chapter dari komik tertentu.", "method": "GET", "path": "/api/anime/komiku/detail", "responseType": "json", "example": "async function getDetail() {\n const res = await fetch('/api/anime/komiku/detail?url=https://komiku.org/manga/solo-leveling-id/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Komik (contoh: https://komiku.org/manga/solo-leveling-id/).", "required": true } ] }, { "title": "Komiku Home", "summary": "Update Terbaru Komiku.", "description": "Mengambil daftar update manga/manhwa/manhua terbaru dari Komiku.", "method": "GET", "path": "/api/anime/komiku/home", "responseType": "json", "example": "async function getUpdates() {\n const res = await fetch('/api/anime/komiku/home');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Komiku Image Proxy", "summary": "Proxy gambar komiku behind Cloudflare.", "description": "Mengambil gambar dari CDN Komiku via server-side (cloudscraper) biar client gak kena CF block.", "method": "GET", "path": "/api/anime/komiku/image-proxy", "responseType": "json", "example": "async function getImage() {\\r const res = await fetch('/api/anime/komiku/image-proxy?url=https://img.komiku.org/upload5/solo-leveling-ragnarok/68/2026-01-08/1_a1bc02.webp');\\r const blob = await res.blob();\\r console.log('Image fetched, size:', blob.size);\\r }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL gambar asli dari komiku.", "required": true } ] }, { "title": "Komiku Populer", "summary": "Daftar Komik Populer.", "description": "Mengambil daftar komik paling populer/hot dari Komiku. Mendukung paginasi melalui parameter page.", "method": "GET", "path": "/api/anime/komiku/popular", "responseType": "json", "example": "async function getPopular() {\n const res = await fetch('/api/anime/komiku/popular?page=1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false } ] }, { "title": "Komiku Read", "summary": "Baca Chapter Komik.", "description": "Mengambil daftar gambar dari chapter tertentu.", "method": "GET", "path": "/api/anime/komiku/read", "responseType": "json", "example": "async function readChapter() {\n const res = await fetch('/api/anime/komiku/read?url=https://komiku.org/solo-leveling-ragnarok-chapter-68/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Chapter (contoh: https://komiku.org/solo-leveling-ragnarok-chapter-68/).", "required": true } ] }, { "title": "Komiku Search", "summary": "Pencarian Komik.", "description": "Mencari komik di Komiku berdasarkan kata kunci.", "method": "GET", "path": "/api/anime/komiku/search", "responseType": "json", "example": "async function searchKomik() {\n const res = await fetch('/api/anime/komiku/search?q=Solo Leveling');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"Solo Leveling\").", "required": true } ] }, { "title": "MAL Genre", "summary": "MyAnimeList Genre Search.", "description": "Mencari anime berdasarkan ID Genre di MyAnimeList. ID Genre bisa didapatkan dari dokumentasi Jikan atau MAL (misal: 1 = Action).", "method": "GET", "path": "/api/anime/mal/genre", "responseType": "json", "example": "async function getByGenre() {\n const res = await fetch('/api/anime/mal/genre?genreId=1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "genreId", "in": "query", "type": "number", "description": "ID Genre (contoh: 1 untuk Action, 2 untuk Adventure).", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false }, { "name": "limit", "in": "query", "type": "number", "description": "Jumlah item per halaman (default: 10).", "required": false } ] }, { "title": "MAL Ongoing", "summary": "MyAnimeList Ongoing Anime.", "description": "Mengambil daftar anime yang sedang tayang (Season Now) dari MyAnimeList via Jikan API.", "method": "GET", "path": "/api/anime/mal/ongoing", "responseType": "json", "example": "async function getOngoing() {\n const res = await fetch('/api/anime/mal/ongoing?page=1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false }, { "name": "limit", "in": "query", "type": "number", "description": "Jumlah item per halaman (default: 10).", "required": false } ] }, { "title": "MAL Popular", "summary": "MyAnimeList Popular Anime.", "description": "Mengambil daftar anime populer (Top Anime) dari MyAnimeList via Jikan API.", "method": "GET", "path": "/api/anime/mal/popular", "responseType": "json", "example": "async function getPopular() {\n const res = await fetch('/api/anime/mal/popular?page=1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false }, { "name": "limit", "in": "query", "type": "number", "description": "Jumlah item per halaman (default: 10).", "required": false } ] }, { "title": "MAL Search", "summary": "MyAnimeList Search.", "description": "Mencari anime di MyAnimeList berdasarkan kata kunci.", "method": "GET", "path": "/api/anime/mal/search", "responseType": "json", "example": "async function searchMAL() {\n const res = await fetch('/api/anime/mal/search?q=Naruto');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian.", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman (default: 1).", "required": false }, { "name": "limit", "in": "query", "type": "number", "description": "Jumlah item per halaman (default: 10).", "required": false } ] }, { "title": "Oploverz Detail", "summary": "Oploverz Anime Detail.", "description": "Mengambil informasi detail anime Oploverz berdasarkan URL atau Path. Termasuk daftar episode dengan link yang disesuaikan ke API.", "method": "GET", "path": "/api/anime/oploverz/detail", "responseType": "json", "example": "async function getDetail() {\n // Gunakan path relatif (lebih stabil) atau full URL\n const res = await fetch('/api/anime/oploverz/detail?url=/series/spy-x-family-s3');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Oploverz (original link) atau Path (contoh: /series/spy-x-family-s3).", "required": true } ] }, { "title": "Oploverz Home", "summary": "Oploverz Home.", "description": "Mengambil data halaman utama Oploverz, termasuk Carousel, Trending, Rilis Terbaru, dan Tambahan Baru. Link yang dihasilkan telah disesuaikan agar mengarah kembali ke API ini.", "method": "GET", "path": "/api/anime/oploverz/home", "responseType": "json", "example": "async function getHome() {\n const res = await fetch('/api/anime/oploverz/home');\n const data = await res.json();\n console.log(data);\n }\n \n getHome();", "params": [] }, { "title": "Oploverz Schedule", "summary": "Jadwal Rilis Anime.", "description": "Mengambil jadwal rilis anime mingguan dari Oploverz.", "method": "GET", "path": "/api/anime/oploverz/schedule", "responseType": "json", "example": "async function getSchedule() {\n const res = await fetch('/api/anime/oploverz/schedule');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Oploverz Search", "summary": "Oploverz Search.", "description": "Mencari anime di Oploverz berdasarkan kata kunci menggunakan API backend resmi mereka.", "method": "GET", "path": "/api/anime/oploverz/search", "responseType": "json", "example": "async function search() {\n const res = await fetch('/api/anime/oploverz/search?q=Naruto');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"Naruto\").", "required": true } ] }, { "title": "Oploverz Stream", "summary": "Oploverz Stream & Download.", "description": "Mengambil link streaming dan download untuk episode anime Oploverz berdasarkan URL atau Path.", "method": "GET", "path": "/api/anime/oploverz/stream", "responseType": "json", "example": "async function getStream() {\n // Gunakan path relatif\n const res = await fetch('/api/anime/oploverz/stream?url=/series/spy-x-family-s3/episode/1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Episode Oploverz atau Path (contoh: /series/spy-x-family-s3/episode/1).", "required": true } ] }, { "title": "Samehadaku Detail", "summary": "Detail Anime Samehadaku.", "description": "Mengambil informasi detail anime Samehadaku berdasarkan URL atau Path. Mengembalikan metadata, sinopsis, daftar genre, rekomendasi, dan list episode.", "method": "GET", "path": "/api/anime/samehadaku/detail", "responseType": "json", "example": "async function getDetail() {\n const res = await fetch('/api/anime/samehadaku/detail?url=/anime/golden-kamuy-final-season/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Samehadaku (original link) atau Path relatif.", "required": true } ] }, { "title": "Samehadaku Embed URL", "summary": "Get Embed Iframe URL.", "description": "Mengambil link embed video (iframe) asli dari Samehadaku berdasarkan data post, nume, dan type.", "method": "GET", "path": "/api/anime/samehadaku/embed", "responseType": "json", "example": "async function getEmbed() {\n const res = await fetch('/api/anime/samehadaku/embed?post=47702&nume=2&type=schtml');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "post", "in": "query", "type": "string", "description": "ID Post episode.", "required": true }, { "name": "nume", "in": "query", "type": "string", "description": "Nomor server (nume).", "required": true }, { "name": "type", "in": "query", "type": "string", "description": "Tipe embed (misal: schtml).", "required": true }, { "name": "url", "in": "query", "type": "string", "description": "URL halaman episode sebagai referer (opsional).", "required": false } ] }, { "title": "Samehadaku Home", "summary": "Beranda Samehadaku.", "description": "Mengambil data dari halaman utama Samehadaku, mencakup anime Top 10 minggu ini, update episode terbaru, dan daftar project movies. Link sudah di-proxy ke API ini.", "method": "GET", "path": "/api/anime/samehadaku/home", "responseType": "json", "example": "async function getHome() {\n const res = await fetch('/api/anime/samehadaku/home');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Samehadaku Anime List", "summary": "Daftar Semua Anime.", "description": "Mengambil halaman daftar anime terbaru di Samehadaku. Mendukung paginasi dan mengembalikan meta pagination untuk request halaman selanjutnya.", "method": "GET", "path": "/api/anime/samehadaku/list", "responseType": "json", "example": "async function getList() {\n const res = await fetch('/api/anime/samehadaku/list?page=1');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "page", "in": "query", "type": "number", "description": "Nomor halaman yang ingin diambil (default: 1).", "required": false } ] }, { "title": "Samehadaku Schedule", "summary": "Jadwal Rilis Mingguan.", "description": "Mengambil jadwal rilis anime mingguan (Senin - Minggu) dengan menembak API internal Samehadaku secara langsung. Data yang dihasilkan lebih lengkap dan cepat.", "method": "GET", "path": "/api/anime/samehadaku/schedule", "responseType": "json", "example": "async function getSchedule() {\n const res = await fetch('/api/anime/samehadaku/schedule');\n const data = await res.json();\n console.log(data);\n }", "params": [] }, { "title": "Samehadaku Search", "summary": "Pencarian Anime Samehadaku.", "description": "Mencari judul anime di Samehadaku. Mengembalikan daftar anime relevan lengkap dengan skor, status, dan genre yang diekstrak dari meta tooltip.", "method": "GET", "path": "/api/anime/samehadaku/search", "responseType": "json", "example": "async function search() {\n const res = await fetch('/api/anime/samehadaku/search?q=Boruto');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"Boruto\").", "required": true } ] }, { "title": "Samehadaku Stream", "summary": "Streaming & Download Samehadaku.", "description": "Mengambil data episode lengkap dari Samehadaku berdasarkan URL. Otomatis melakukan bypass AJAX untuk mendapatkan URL embed iframe server streaming, dan mengambil daftar link download file asli.", "method": "GET", "path": "/api/anime/samehadaku/stream", "responseType": "json", "example": "async function getStream() {\n const res = await fetch('/api/anime/samehadaku/stream?url=/golden-kamuy-final-season-episode-1/');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Episode Samehadaku atau Path relatif.", "required": true } ] } ], "chart": [ { "title": "Billboard Indonesia Chart", "summary": "Mendapatkan chart musik Indonesia terbaru dari Billboard", "description": "Mengambil data 30 lagu terpopuler di Indonesia dari Billboard Indonesia Songs chart (Hot Week)", "method": "GET", "path": "/api/chart/billboard", "responseType": "json", "example": "// Request\n GET /api/chart/billboard\n // Response\n {\n \"success\": true,\n \"author\": \"PuruBoy\",\n \"result\": [\n {\n \"rank\": 1,\n \"title\": \"Example Song\",\n \"artist\": \"Example Artist\",\n \"lastWeek\": \"1\",\n \"peakPos\": \"1\",\n \"weeksOnChart\": \"10\",\n \"image\": \"https://...\"\n }\n ]\n }", "params": [] }, { "title": "TikTok Indonesia Chart", "summary": "Mendapatkan 30 lagu trending TikTok Indonesia dari Soundcharts", "description": "Mengambil data chart TikTok Indonesia terbaru dari Soundcharts.com. Menampilkan 30 lagu terpopuler minggu ini dengan posisi, judul, dan artis.", "method": "GET", "path": "/api/chart/tiktok", "responseType": "json", "example": "// Request\n GET /api/chart/tiktok\n // Response\n {\n \"success\": true,\n \"author\": \"PuruBoy\",\n \"result\": [\n {\n \"position\": 1,\n \"title\": \"DJ LIA ADE NONA MAKIN\",\n \"artist\": \"DJ Alexandre Da Gloria\",\n \"songId\": \"50d47f08-f5fe-4cce-be21-09e1934648d9\"\n }\n ]\n }", "params": [] } ], "downloader": [ { "title": "Facebook Downloader", "summary": "Download video Facebook (Reel/Watch/Video/Share).", "description": "Mendownload video Facebook menggunakan Embed Plugin Facebook + fallback fsave.io. Mendukung format Reel, Watch, Video, dan Share. Menghasilkan link HD, SD, thumbnail, subtitles, dan daftar kualitas video.", "method": "POST", "path": "/api/downloader/fb", "responseType": "json", "example": "async function downloadFB() {\n try {\n const response = await fetch('/api/downloader/fb', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://www.facebook.com/reel/2195585950845288\" \n })\n });\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error.message);\n }\n }\n \n downloadFB();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lengkap video Facebook (reel, watch, videos, share).", "required": true } ] }, { "title": "Facebook DL", "summary": "Download video Facebook.", "description": "Mengunduh video dari Facebook menggunakan layanan fsave.io. Mengembalikan thumbnail dan link download video dalam kualitas SD dan HD.", "method": "POST", "path": "/api/downloader/fbdl", "responseType": "json", "example": "async function downloadFB() {\n try {\n const response = await fetch('/api/downloader/fbdl', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://www.facebook.com/reel/861262849136029/\" \n })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error.message);\n }\n }\n \n downloadFB();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lengkap dari video Facebook yang ingin diunduh.", "required": true } ] }, { "title": "Instagram Downloader", "summary": "Download Instagram Media (Reels/Photo/Carousel) + Metadata.", "description": "Mengunduh konten Instagram (Video Reels, Foto, Carousel) lengkap dengan metadata seperti caption, author, thumbnail, dan link download.", "method": "POST", "path": "/api/downloader/instagram", "responseType": "json", "example": "async function downloadIg() {\n const res = await fetch('/api/downloader/instagram', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.instagram.com/reel/DV5hrHUEg4U/\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL media Instagram.", "required": true } ] }, { "title": "Savetube (YouTube DL)", "summary": "Mendownload video/audio YouTube dengan cepat menggunakan Savetube API.", "description": "Mendukung berbagai format kualitas video dan audio dari YouTube. Cukup kirim URL video, dan dapatkan link download langsung beserta metadata seperti judul, thumbnail, durasi, dan format yang tersedia.", "method": "POST", "path": "/api/downloader/savetube", "responseType": "json", "example": "// Contoh penggunaan\n async function downloadYouTube() {\n try {\n const response = await fetch('/api/downloader/savetube', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\", \"quality\": \"720\" })\n });\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error.message);\n }\n }\n downloadYouTube();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lengkap video YouTube yang ingin diunduh.", "required": true }, { "name": "quality", "in": "body", "type": "string", "description": "Kualitas video/audio yang diinginkan. Jika tidak diisi, akan mengembalikan semua format yang tersedia.", "required": false, "choices": [ { "value": "360", "label": "360p Video" }, { "value": "480", "label": "480p Video" }, { "value": "720", "label": "720p Video (HD)" }, { "value": "1080", "label": "1080p Video (Full HD)" }, { "value": "128", "label": "128kbps Audio" } ] }, { "name": "type", "in": "body", "type": "string", "description": "Tipe unduhan.", "required": false, "choices": [ { "value": "video", "label": "Format video (default)" }, { "value": "audio", "label": "Format audio saja" } ] } ] }, { "title": "Snaptik TikTok DL", "summary": "Unduh Video TikTok (Snaptik).", "description": "Mengunduh video TikTok tanpa watermark menggunakan scraping Snaptik.app. Mendukung berbagai link unduhan termasuk HD.", "method": "POST", "path": "/api/downloader/snaptik", "responseType": "json", "example": "async function download() {\n const res = await fetch('/api/downloader/snaptik', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.tiktok.com/@brilionet/video/7483341650115267847\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL video TikTok.", "required": true } ] }, { "title": "SoundCloud DL V2", "summary": "SoundCloud Downloader V2 (Direct).", "description": "Mengunduh lagu dari SoundCloud menggunakan metode direct scraping (Client ID Extraction). Lebih stabil dan cepat.", "method": "POST", "path": "/api/downloader/soundcloud-v2", "responseType": "json", "example": "async function downloadSC() {\n const res = await fetch('/api/downloader/soundcloud-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://soundcloud.com/tyo-rizki-413604039/dj-ya-odna-x-the-drum-breakbeat-andra-fvnky-rmx\" \n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lagu SoundCloud yang valid.", "required": true } ] }, { "title": "Spotify Downloader V2", "summary": "Spotify to MP3 via savevideoraw.", "description": "Mengunduh lagu dari Spotify dan mengubahnya menjadi format MP3 menggunakan API savevideoraw.com. Tanpa login, gratis, cepat.", "method": "POST", "path": "/api/downloader/spotify-v2", "responseType": "json", "example": "async function dlSpotifyV2() {\n const res = await fetch('/api/downloader/spotify-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n \"url\": \"https://open.spotify.com/intl-id/track/0d9Odqdel9VeeDEYuPjm6x\"\n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL Track Spotify (contoh: https://open.spotify.com/intl-id/track/... atau https://open.spotify.com/track/...).", "required": true } ] }, { "title": "TikTok DL", "summary": "Mengunduh video TikTok tanpa watermark.", "description": "Memproses URL video TikTok dan mengembalikan informasi video beserta link unduhan langsung (tanpa watermark) dan link audio dalam format JSON.", "method": "POST", "path": "/api/downloader/tiktok", "responseType": "json", "example": "// Contoh penggunaan\n async function downloadTikTok() {\n try {\n const response = await fetch('/api/downloader/tiktok', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n // PENTING: Gunakan format JSON valid (key dengan kutip ganda) agar Auto Fill berfungsi\n body: JSON.stringify({ \"url\": \"https://www.tiktok.com/@brilionet/video/7483341650115267847\" })\n });\n \n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error.message);\n }\n }\n \n downloadTikTok();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lengkap dari video TikTok yang ingin diunduh.", "required": true } ] }, { "title": "TikTok DL V2", "summary": "TikTok Downloader (TikDownloader.io).", "description": "Mengunduh video TikTok tanpa watermark atau slide foto menggunakan provider TikDownloader.io. Credit: Yabes.", "method": "POST", "path": "/api/downloader/tiktok-v2", "responseType": "json", "example": "async function download() {\n const res = await fetch('/api/downloader/tiktok-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.tiktok.com/@alenkainventra/video/7351044913112321288\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL video TikTok.", "required": true } ] }, { "title": "X Downloader", "summary": "X/Twitter Video Downloader.", "description": "Mengunduh video dari platform X (Twitter) menggunakan layanan xsaver.io. Mengembalikan judul video dan daftar link download kualitas yang tersedia.", "method": "POST", "path": "/api/downloader/x", "responseType": "json", "example": "async function downloadX() {\n const res = await fetch('/api/downloader/x', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://x.com/elsyandria/status/1218385778880831488\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL video X/Twitter yang ingin diunduh.", "required": true } ] }, { "title": "YouTube DL", "summary": "YouTube Downloader (YTDown).", "description": "Mengunduh video dan audio dari YouTube menggunakan layanan YTDown. Mendukung berbagai resolusi (hingga 1080p FHD).", "method": "POST", "path": "/api/downloader/youtube", "responseType": "json", "example": "async function dl() {\n const res = await fetch('/api/downloader/youtube', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.youtube.com/watch?v=Fmf-G9fpwto\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL video YouTube yang valid.", "required": true } ] }, { "title": "YouTube Downloader", "summary": "Download video YouTube menggunakan YoutubeSave.io.", "description": "Mendownload video dan audio dari YouTube menggunakan layanan YoutubeSave.io. Mendukung berbagai resolusi (1080p, 720p, 480p, 360p, MP3 Audio). Mengembalikan metadata lengkap termasuk judul, thumbnail, durasi, dan link download untuk semua format yang tersedia.", "method": "POST", "path": "/api/downloader/youtube", "responseType": "json", "example": "async function downloadVideo() {\n try {\n const res = await fetch('/api/downloader/youtube', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' })\n });\n const data = await res.json();\n console.log(JSON.stringify(data, null, 2));\n } catch (err) {\n console.error('Error:', err.message);\n }\n }\n downloadVideo();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL lengkap video YouTube yang ingin diunduh (wajib).", "required": true } ] }, { "title": "YTMP3 Audio", "summary": "YouTube to MP3.", "description": "Mengonversi dan mengunduh audio YouTube dalam format MP3 menggunakan layanan YTMP3.mobi.", "method": "POST", "path": "/api/downloader/ytmp3", "responseType": "json", "example": "async function downloadMp3() {\n const res = await fetch('/api/downloader/ytmp3', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL Video YouTube yang ingin diunduh.", "required": true } ] } ], "main": [ { "title": "Server Ping", "summary": "Memeriksa status server.", "description": "Endpoint ini mengembalikan status sukses beserta timestamp untuk memverifikasi bahwa server aktif dan merespons.", "method": "GET", "path": "/api/main/ping", "responseType": "json", "params": [ { "name": "echo", "in": "query", "type": "string", "description": "Teks opsional yang akan dikembalikan dalam respons.", "required": false } ] } ], "meme": [ { "title": "Lahelu Feed", "summary": "Get Fresh Memes.", "description": "Mengambil feed meme terbaru (Fresh) dari Lahelu. Mendukung paginasi menggunakan cursor.", "method": "GET", "path": "/api/meme/lahelu", "responseType": "json", "example": "async function getMemes() {\n const res = await fetch('/api/meme/lahelu');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "page", "in": "query", "type": "number", "description": "Cursor halaman (integer). Default: 0. Gunakan 'nextCursor' dari respons sebelumnya untuk halaman berikutnya.", "required": false } ] }, { "title": "Ubur Ubur", "summary": "Generator Video Meme.", "description": "Membuat video meme promosi/lucu dengan latar belakang kustom, karakter manusia, dan teks. Endpoint ini menggunakan Server-Sent Events (SSE) karena proses rendering video membutuhkan waktu. Hasil akhir diunggah ke penyimpanan sementara.", "method": "POST", "path": "/api/meme/uburubur", "responseType": "json", "example": "async function generateMeme() {\n const res = await fetch('/api/meme/uburubur', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n \"bgUrl\": \"https://www.puruboy.kozow.com/favicon.jpg\",\n \"humanUrl\": \"https://png.pngtree.com/png-clipart/20240412/original/pngtree-prabowo-subianto-png-image_14789437.png\",\n \"brand\": \"INFO PENTING\",\n \"title\": \"UBUR UBUR\",\n \"slogan\": \"Ikan hiu makan tomat.\",\n \"promo\": \"Makan nasi | Rp5.000\\nMakan angin | Gratis\",\n \"wm\": \"@PuruBoy-API\"\n })\n });\n \n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n console.log(decoder.decode(value));\n }\n }", "params": [ { "name": "bgUrl", "in": "body", "type": "string", "description": "URL gambar background.", "required": true }, { "name": "humanUrl", "in": "body", "type": "string", "description": "URL gambar karakter manusia (transparan disarankan).", "required": true }, { "name": "brand", "in": "body", "type": "string", "description": "Teks brand/merk (atas).", "required": true }, { "name": "title", "in": "body", "type": "string", "description": "Judul utama.", "required": true }, { "name": "slogan", "in": "body", "type": "string", "description": "Slogan di bawah judul.", "required": true }, { "name": "promo", "in": "body", "type": "string", "description": "Detail teks/daftar harga (mendukung newline).", "required": true }, { "name": "wm", "in": "body", "type": "string", "description": "Teks watermark (kanan bawah).", "required": true } ] } ], "play": [ { "title": "SoundCloud Play", "summary": "Play SoundCloud Audio.", "description": "Mencari lagu di SoundCloud, memfilter durasi (1-10 menit), dan mengambil URL download langsung. Menggabungkan fungsi pencarian dan pengunduhan dalam satu request untuk mendapatkan audio yang bisa diputar/diunduh.", "method": "GET", "path": "/api/play/soundcloud", "responseType": "json", "example": "async function play() {\n const res = await fetch('/api/play/soundcloud?q=dj+ya+odna');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Judul lagu atau kata kunci pencarian.", "required": true } ] } ], "search": [ { "title": "Lahelu Search", "summary": "Cari Meme Lahelu.", "description": "Mencari meme di Lahelu berdasarkan kata kunci.", "method": "GET", "path": "/api/search/lahelu", "responseType": "json", "example": "async function searchMemes() {\n const res = await fetch('/api/search/lahelu?q=kucing');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian.", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Cursor halaman (integer). Default: 0.", "required": false } ] }, { "title": "Lyrics Search", "summary": "Search Song Lyrics.", "description": "Mencari lirik lagu berdasarkan judul atau artis menggunakan LRCLIB. Mengembalikan lirik biasa (plain) dan tersinkronisasi (synced/LRC) jika tersedia.", "method": "GET", "path": "/api/search/lyrics", "responseType": "json", "example": "async function getLyrics() {\n const res = await fetch('/api/search/lyrics?q=Alan Walker Faded');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Judul lagu atau nama artis.", "required": true } ] }, { "title": "Pinterest Search", "summary": "Search Pinterest Pins.", "description": "Mencari gambar atau pin di Pinterest berdasarkan kata kunci. Mengambil sesi dan token secara otomatis untuk mengakses API internal Pinterest.", "method": "GET", "path": "/api/search/pinterest", "responseType": "json", "example": "async function pinterestSearch() {\n try {\n const res = await fetch('/api/search/pinterest?q=Anime Wallpaper');\n const data = await res.json();\n console.log(data);\n } catch (e) {\n console.error(e);\n }\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"Anime Wallpaper\").", "required": true } ] }, { "title": "SoundCloud Search", "summary": "Search SoundCloud Tracks.", "description": "Melakukan pencarian lagu di SoundCloud berdasarkan kata kunci. Endpoint ini mengembalikan daftar lagu yang cocok beserta metadata seperti durasi dan jumlah pemutaran.", "method": "GET", "path": "/api/search/soundcloud", "responseType": "json", "example": "// Contoh penggunaan\n async function searchSoundCloud() {\n try {\n const response = await fetch('/api/search/soundcloud?q=lofi&limit=5');\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error('Error:', error);\n }\n }\n \n searchSoundCloud();", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (judul lagu/artis).", "required": true }, { "name": "limit", "in": "query", "type": "string", "description": "Batas jumlah hasil yang ditampilkan (default: 10).", "required": false } ] }, { "title": "SoundCloud Playlist", "summary": "Get SoundCloud Playlist Tracks.", "description": "Mengambil daftar lagu lengkap dari sebuah playlist SoundCloud menggunakan scraping dinamis Client ID.", "method": "GET", "path": "/api/search/soundcloud-playlist", "responseType": "json", "example": "async function getPlaylist() {\n const res = await fetch('/api/search/soundcloud-playlist?url=https://soundcloud.com/mhd-rayyan/sets/lagu-pop-indonesia-hits-2026');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "query", "type": "string", "description": "URL Playlist SoundCloud.", "required": true } ] }, { "title": "Spotify Search via Yahoo", "summary": "Mencari track Spotify menggunakan mesin pencari Yahoo.", "description": "Mencari lagu/track Spotify melalui Yahoo Search dengan format `site:spotify.com/intl-id/track`. Mengembalikan judul, track ID, dan URL Spotify. Cocok untuk mencari track yang mungkin tidak muncul di pencarian internal Spotify.", "method": "GET", "path": "/api/search/spotify", "responseType": "json", "example": "async function searchSpotify() {\n const res = await fetch('/api/search/spotify?q=DJ+ya+odna');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian (contoh: \"DJ ya odna\").", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Halaman hasil pencarian (default: 1).", "required": false } ] }, { "title": "Search Autocomplete", "summary": "Get search suggestions.", "description": "Mendapatkan daftar saran kata kunci pencarian (autocomplete) berdasarkan input pengguna. Fitur ini menggunakan engine Google Suggest.", "method": "GET", "path": "/api/search/suggest", "responseType": "json", "example": "async function getSuggestions() {\n const res = await fetch('/api/search/suggest?q=apa+itu');\n const data = await res.json();\n console.log(data.result);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci atau awalan kalimat.", "required": true } ] }, { "title": "Yahoo Search", "summary": "Search information on Yahoo.", "description": "Mencari informasi web secara langsung dari mesin pencari Yahoo. Mengembalikan judul, link, dan cuplikan konten.", "method": "GET", "path": "/api/search/yahoo", "responseType": "json", "example": "async function searchYahoo() {\n const res = await fetch('/api/search/yahoo?q=berita+terkini');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian.", "required": true } ] }, { "title": "Yahoo SoundCloud Search", "summary": "Cari lagu/playlist SoundCloud via Yahoo.", "description": "Mencari konten SoundCloud (track atau playlist) menggunakan mesin pencari Yahoo. Menghasilkan output yang bersih dengan ekstraksi URL asli.", "method": "GET", "path": "/api/search/yahoo-soundcloud", "responseType": "json", "example": "async function search() {\n const res = await fetch('/api/search/yahoo-soundcloud?q=dj+ya+odna');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian.", "required": true }, { "name": "page", "in": "query", "type": "number", "description": "Offset hasil pencarian (default: 1).", "required": false } ] }, { "title": "YouTube Search", "summary": "Search YouTube Videos.", "description": "Mencari video di YouTube berdasarkan kata kunci menggunakan provider pihak ketiga. Mengembalikan judul, link video, channel, durasi, dan thumbnail.", "method": "GET", "path": "/api/search/youtube", "responseType": "json", "example": "async function searchYouTube() {\n const res = await fetch('/api/search/youtube?q=DJ ya odna');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Kata kunci pencarian.", "required": true } ] } ], "tools": [ { "title": "Audio to Text (MMS) - SSE", "summary": "Transkripsi Audio ke Teks (1000+ Bahasa) via Server-Sent Events.", "description": "Mengonversi file suara/audio menjadi teks menggunakan Meta MMS (Massively Multilingual Speech) model. Mendukung 1000+ bahasa. Response dalam format SSE (Server-Sent Events). Saat menunggu hasil, server mengirim ping event berisi fakta unik.", "method": "POST", "path": "/api/tools/audio2text", "responseType": "json", "example": "// Via fetch + ReadableStream (rekomendasi)\n const res = await fetch('https://puruboy-api.vercel.app/api/tools/audio2text', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n url: 'https://puruboy-api.vercel.app/example.mp3',\n lang: 'ind'\n })\n });\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = decoder.decode(value);\n // Parse SSE events: start, submit, submitted, processing, ping, result, done\n console.log(chunk);\n }\n\n// EventSource (browser) — gunakan POST proxy atau library seperti @microsoft/fetch-event-source\n // Karena EventSource tidak support POST, gunakan fetch + manual parse:\n const res = await fetch('/api/tools/audio2text', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ url: 'https://puruboy-api.vercel.app/example.mp3', lang: 'ind' })\n });\n // Baca stream, setiap event \"ping\" berisi fakta unik sambil menunggu \"result\"", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file audio (WAV/MP3/FLAC/OGG, dll).", "required": true }, { "name": "lang", "in": "body", "type": "string", "description": "Kode/nama bahasa target. Contoh: 'ind', 'Indonesia', 'Indonesian (ind)'. Default: 'Indonesian (ind)'.", "required": false } ] }, { "title": "Voice & Audio Editor", "summary": "Ubah efek suara video/audio.", "description": "Menerapkan efek suara ke file video atau audio (MP3). Pilihan efek: bass, deep, chipmunk, echo, radio, nightcore.", "method": "POST", "path": "/api/tools/audioedit", "responseType": "json", "example": "async function editAudio() {\n const res = await fetch('/api/tools/audioedit', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://puruboy-api.vercel.app/example.mp4\",\n \"effect\": \"nightcore\"\n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file media (MP4/MP3).", "required": true }, { "name": "effect", "in": "body", "type": "string", "description": "Jenis efek (bass, deep, chipmunk, echo, radio, nightcore). Default: bass.", "required": false } ] }, { "title": "AI Auto Clipper", "summary": "Ubah Video Panjang Jadi Klip Viral.", "description": "Menggunakan kecerdasan buatan untuk menganalisis video panjang dan memotong bagian paling menarik secara otomatis untuk konten TikTok/Reels/Shorts. Mendukung video dengan durasi bebas selama ukuran file tidak melebihi 200MB.", "method": "POST", "path": "/api/tools/autoclip", "responseType": "json", "example": "async function generateClip() {\n const res = await fetch('/api/tools/autoclip', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://github.com/purujawa06-bot/My-db/raw/refs/heads/main/video/videoplayback.mp4\" \n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file video MP4 (contoh: https://github.com/purujawa06-bot/My-db/raw/refs/heads/main/video/videoplayback.mp4).", "required": true } ] }, { "title": "Brat Generator", "summary": "Brat Generator (Text to Image).", "description": "Membuat meme teks gaya \"Brat\" berdasarkan input teks menggunakan API eksternal yang cepat. Mengembalikan URL gambar hasil (PNG) yang sudah diproses menjadi URL publik.", "method": "POST", "path": "/api/tools/brat", "responseType": "json", "example": "async function createBrat() {\n const res = await fetch('/api/tools/brat', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"text\": \"hai kamu siapa sih😈\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "text", "in": "body", "type": "string", "description": "Teks yang akan ditampilkan pada gambar.", "required": true } ] }, { "title": "AI Video Dubbing", "summary": "Terjemahkan Suara Video (Dubbing).", "description": "Mengubah suara asli dalam video ke bahasa lain menggunakan AI dengan tetap mempertahankan nuansa suara aslinya. Mendukung bahasa Indonesia (id-ID), Inggris (en-US), dan Jepang (ja-JP).", "method": "POST", "path": "/api/tools/dubbing", "responseType": "json", "example": "async function startDubbing() {\n const res = await fetch('/api/tools/dubbing', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://github.com/purujawa06-bot/My-db/raw/refs/heads/main/video/english-conversation-have-a-coffee-with-tim-shorts-ytshorts.savetube.vip.mp4\",\n \"voice\": \"id-ID\",\n \"prompt\": \"Santai Dan Gaul Bro\"\n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file video (MP4) yang ingin di-dubbing.", "required": true }, { "name": "voice", "in": "body", "type": "string", "description": "Kode bahasa target: 'id-ID', 'en-US', 'ja-JP'. Default: 'id-ID'.", "required": false }, { "name": "prompt", "in": "body", "type": "string", "description": "Instruksi tambahan untuk AI (misal: \"Gaya bicara santai\").", "required": false } ] }, { "title": "Ghibli Style", "summary": "Transform Image to Ghibli Style.", "description": "Mengubah foto menjadi gaya seni anime Studio Ghibli. Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/tools/ghibli", "responseType": "json", "example": "// Contoh penggunaan SSE\n async function ghibliTransform() {\n const response = await fetch('/api/tools/ghibli', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://puruboy-api.vercel.app/example.jpg\",\n \"prompt\": \"Jadikan ghibli\"\n })\n });\n \n const reader = response.body.getReader();\n // Read stream...\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL gambar sumber.", "required": true }, { "name": "prompt", "in": "body", "type": "string", "description": "Prompt kustom (opsional).", "required": false } ] }, { "title": "HD Video 60FPS", "summary": "AI Video Enhancer.", "description": "Mempertajam dan membuat video menjadi sangat mulus (60 FPS) menggunakan AI. Endpoint ini akan mengembalikan job ID dan polling URL untuk memeriksa status pemrosesan.", "method": "POST", "path": "/api/tools/hdvideo", "responseType": "json", "example": "async function makeHD() {\n const res = await fetch('/api/tools/hdvideo', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://puruboy-api.vercel.app/example.mp4\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file video (MP4) yang ingin di-HD-kan.", "required": true } ] }, { "title": "ImgBB Uploader", "summary": "Upload Gambar ke ImgBB.", "description": "Mengupload gambar ke ImgBB dan mendapatkan direct link secara gratis. Mendukung format JPG, PNG, BMP, GIF, TIF, WEBP, HEIC, PDF.", "method": "POST", "path": "/api/tools/imgbb", "responseType": "json", "example": "// Contoh penggunaan dengan FormData (Browser)\n const formData = new FormData();\n formData.append('image', fileInput.files[0]);\n \n const res = await fetch('/api/tools/imgbb', {\n method: 'POST',\n body: formData\n });\n \n const data = await res.json();\n console.log(data);", "params": [ { "name": "image", "in": "formData", "type": "file", "description": "File gambar yang akan diupload.", "required": true } ] }, { "title": "Media Job Status", "summary": "Cek Status Pemrosesan Media.", "description": "Memeriksa status pekerjaan untuk HD Video, atau Audio Edit. Jika selesai, akan mengembalikan URL file hasil.", "method": "GET", "path": "/api/tools/media-status", "responseType": "json", "example": "async function checkStatus() {\n const res = await fetch('/api/tools/media-status?jobId=12345abcde');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "jobId", "in": "query", "type": "string", "description": "ID Job yang didapat dari request sebelumnya.", "required": true } ] }, { "title": "MLBB Region Checker", "summary": "Cek Region & Nickname MLBB.", "description": "Mengecek region ID, nickname, dan metadata akun Mobile Legends: Bang Bang berdasarkan User ID dan Zone ID menggunakan layanan PizzoShop.", "method": "POST", "path": "/api/tools/mlbb", "responseType": "json", "example": "async function checkML() {\n const res = await fetch('/api/tools/mlbb', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"userId\": \"2002113712\", \n \"zoneId\": \"19417\" \n })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "userId", "in": "body", "type": "string", "description": "User ID Mobile Legends.", "required": true }, { "name": "zoneId", "in": "body", "type": "string", "description": "Zone ID Mobile Legends.", "required": true } ] }, { "title": "MP4 to MP3 Converter", "summary": "Konversi Video MP4 ke Audio MP3.", "description": "Mengekstrak audio dari file video MP4 dan mengubahnya menjadi format MP3. Endpoint ini menggunakan Server-Sent Events (SSE) untuk memberikan update status proses konversi secara real-time.", "method": "POST", "path": "/api/tools/mp4tomp3", "responseType": "json", "example": "async function convert() {\n const res = await fetch('/api/tools/mp4tomp3', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://puruboy-api.vercel.app/example.mp4\" })\n });\n \n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n console.log(decoder.decode(value));\n }\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file MP4 yang ingin dikonversi.", "required": true } ] }, { "title": "Preview HTML Uploader", "summary": "Upload konten HTML ke puruboy-preview.freehosting.dev via JSON string.", "description": "Mengupload konten HTML (string) ke server preview dan mendapatkan link akses publik. Melakukan bypass AES-CBC JavaScript challenge, mengambil CSRF token, dan mengirim multipart form secara otomatis.", "method": "POST", "path": "/api/tools/preview-upload", "responseType": "json", "example": "// Contoh penggunaan dengan JSON\n const res = await fetch('/api/tools/preview-upload', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n content: '

Halo Dunia

Ini preview HTML

',\n filename: 'promo-hari-ini'\n })\n });\n \n const data = await res.json();\n console.log(data);", "params": [ { "name": "content", "in": "body", "type": "string", "description": "(Wajib) Konten HTML yang akan diupload, bisa berupa string HTML biasa", "required": true }, { "name": "filename", "in": "body", "type": "string", "description": "(Opsional) Nama file tanpa ekstensi .html (default: \"preview\")", "required": true } ] }, { "title": "Al-Quran Digital", "summary": "Al-Quran Digital Kemenag.", "description": "Mengambil data ayat-ayat suci Al-Quran beserta terjemahan dan teks latin langsung dari sumber web-api Kemenag. Respons telah dirapikan dan dibersihkan dari properti bernilai null untuk efisiensi data.", "method": "GET", "path": "/api/tools/quran", "responseType": "json", "example": "async function getQuran() {\n const res = await fetch('/api/tools/quran?surah=10&ayah=1,2');\n const data = await res.json();\n console.log(data.result.data);\n }", "params": [ { "name": "surah", "in": "query", "type": "string", "description": "Nomor surah (1-114).", "required": true }, { "name": "ayah", "in": "query", "type": "string", "description": "Nomor ayat spesifik atau daftar ayat dipisah koma (contoh: \"1,2,3\"). Default: \"all\".", "required": false } ] }, { "title": "Remove BG", "summary": "Hapus Background Gambar.", "description": "Menghapus latar belakang gambar menggunakan API Pixelcut dan mengupload hasilnya ke penyimpanan sementara. Mengembalikan URL gambar hasil (PNG).", "method": "POST", "path": "/api/tools/removebg", "responseType": "json", "example": "// Contoh penggunaan\n async function removeBg() {\n try {\n const response = await fetch('/api/tools/removebg', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://puruboy-api.vercel.app/example.jpg\" \n })\n });\n \n const data = await response.json();\n console.log(data); \n // Output: { status: 'success', url: 'https://domain.com/api/media/...' }\n } catch (error) {\n console.error('Error:', error.message);\n }\n }\n \n removeBg();", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik dari gambar yang ingin diproses.", "required": true } ] }, { "title": "Remove BG V2", "summary": "Hapus Background V2 (ILoveIMG).", "description": "Menghapus latar belakang gambar menggunakan layanan ILoveIMG. Alternatif handal untuk menghapus background dengan presisi tinggi.", "method": "POST", "path": "/api/tools/removebg-v2", "responseType": "json", "example": "// Contoh penggunaan\n async function removeBg() {\n try {\n const response = await fetch('/api/tools/removebg-v2', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://puruboy-api.vercel.app/example.jpg\" \n })\n });\n \n const data = await response.json();\n console.log(data); \n } catch (error) {\n console.error('Error:', error.message);\n }\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik dari gambar yang ingin diproses.", "required": true } ] }, { "title": "Colorize Image", "summary": "Colorize Image (AI Engine V2).", "description": "Mewarnai gambar hitam putih menggunakan AI Engine terbaru yang lebih akurat. Endpoint ini menggunakan Server-Sent Events (SSE). Hasil akhir disimpan sementara dalam database selama 30 menit.", "method": "POST", "path": "/api/tools/reviva", "responseType": "json", "example": "async function colorizeImage() {\n const response = await fetch('/api/tools/reviva', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://puruboy-api.vercel.app/example.jpg\" \n })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n \n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n if(text.includes('[true]')) {\n const retrieveUrl = text.replace('[true]', '').trim();\n console.log(\"Data tersedia di:\", retrieveUrl);\n }\n }\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL gambar (hitam putih) yang ingin diwarnai.", "required": true } ] }, { "title": "Jadwal Sholat", "summary": "Jadwal Sholat Bulanan.", "description": "Mengambil jadwal sholat bulanan berdasarkan nama kota di Indonesia. Dilengkapi dengan algoritma similarity untuk menangani kesalahan penulisan (tyo) nama kota.", "method": "GET", "path": "/api/tools/sholat", "responseType": "json", "example": "async function getSholat() {\n const res = await fetch('/api/tools/sholat?q=jakarta');\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "q", "in": "query", "type": "string", "description": "Nama kota (contoh: \"Jakarta\", \"Bandung\", \"Subang\").", "required": true } ] }, { "title": "AI Video Stabilizer", "summary": "Menstabilkan Video Shaky.", "description": "Memperbaiki guncangan (shake) pada video menggunakan teknologi AI Stabilizer. Endpoint ini akan mengembalikan job ID dan polling URL untuk memeriksa status pemrosesan.", "method": "POST", "path": "/api/tools/stabilizer", "responseType": "json", "example": "async function stabilize() {\n const res = await fetch('/api/tools/stabilizer', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://puruboy-api.vercel.app/example.mp4\" })\n });\n const data = await res.json();\n console.log(data);\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL publik file video (MP4) yang ingin distabilkan.", "required": true } ] }, { "title": "AI Unblur", "summary": "AI Image Unblur (UnblurImage.ai).", "description": "Memperbaiki gambar yang buram (blur) agar menjadi lebih tajam dan jernih menggunakan teknologi AI. Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/tools/unblur", "responseType": "json", "example": "// Contoh penggunaan SSE di client\n async function unblurImage() {\n const response = await fetch('/api/tools/unblur', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://puruboy-api.vercel.app/example.jpg\" })\n });\n \n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const text = decoder.decode(value);\n if(text.includes('[true]')) {\n const url = text.replace('[true]', '').trim();\n console.log(\"Success:\", url);\n }\n }\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL gambar yang ingin diperbaiki.", "required": true } ] }, { "title": "AI Upscale", "summary": "AI Image Upscale.", "description": "Meningkatkan resolusi dan kualitas gambar menggunakan AI (via Cloudinary). Endpoint ini menggunakan Server-Sent Events (SSE).", "method": "POST", "path": "/api/tools/upscale", "responseType": "json", "example": "// Contoh penggunaan SSE\n async function upscaleImage() {\n const response = await fetch('/api/tools/upscale', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"url\": \"https://puruboy-api.vercel.app/example.jpg\" })\n });\n \n const reader = response.body.getReader();\n // Read stream...\n }", "params": [ { "name": "url", "in": "body", "type": "string", "description": "URL gambar yang ingin di-upscale.", "required": true } ] } ] } --- // FILE: public/admin.html Admin Console
šŸ”

Admin Access

Masukkan kredensial untuk melanjutkan

--- // FILE: lib/ytsearch.js const axios = require('axios'); const BASE_URL = 'https://inv.nadeko.net'; const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'; /** * YouTube Search via Invidious (inv.nadeko.net) — without cheerio * * @param {string} query - Kata kunci pencarian * @param {object} [options] * @param {number} [options.page] - Halaman (default: 1) * @param {string} [options.sort] - Sort: 'relevance' | 'views' | 'rating' | 'date' * @param {string} [options.duration] - Durasi: 'short' | 'medium' | 'long' * @param {string} [options.type] - Tipe: 'video' | 'channel' | 'playlist' | 'movie' | 'show' * @param {string} [options.date] - Upload: 'hour' | 'today' | 'week' | 'month' | 'year' * @returns {Promise} */ async function search(query, options = {}) { if (!query || typeof query !== 'string') { throw new Error('Query is required.'); } const page = options.page || 1; const params = new URLSearchParams({ q: query, page }); if (options.sort) params.set('sort', options.sort); if (options.duration) params.set('duration', options.duration); if (options.type) params.set('type', options.type); if (options.date) params.set('date', options.date); if (options.features) { const features = Array.isArray(options.features) ? options.features : [options.features]; features.forEach((f) => params.append('features[]', f)); } const url = `${BASE_URL}/search?${params.toString()}`; const { data } = await axios.get(url, { headers: { 'User-Agent': USER_AGENT, Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9', }, timeout: 15000, }); const results = []; // Split by card: each card starts with