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": "next dev",
"build": "node scripts/generate-docs.js && next build",
"start": "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",
"form-data": "^4.0.0",
"fs-extra": "^11.2.0",
"glob": "^10.3.10",
"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"
},
"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)
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com',
},
],
},
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: "wa.me/6283894391287" } // 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: 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/google41f3f05fef8cd977.html
google-site-verification: google41f3f05fef8cd977.html
---
// FILE: public/fastupdate.html
System Updater
Fast Update
AI-Powered Code Implementation
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": "Blackbox AI",
"summary": "AI Chat dengan Konteks (History).",
"description": "Berinteraksi dengan Blackbox AI yang mendukung percakapan berkelanjutan. Riwayat percakapan disimpan per user di Firebase dan otomatis dibersihkan jika tidak ada aktivitas selama 3 hari.",
"method": "POST",
"path": "/api/ai/blackbox",
"responseType": "json",
"example": "async function chat() {\n const res = await fetch('/api/ai/blackbox', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"message\": \"Halo, siapa namamu?\",\n \"userId\": \"user-123\",\n \"system\": \"Kamu adalah asisten yang ramah.\"\n })\n });\n const data = await res.json();\n console.log(data.result.answer);\n }",
"params": [
{
"name": "message",
"in": "body",
"type": "string",
"description": "Pesan dari pengguna.",
"required": true
},
{
"name": "userId",
"in": "body",
"type": "string",
"description": "ID unik pengguna (DeviceId/Username) untuk menyimpan riwayat chat.",
"required": false
},
{
"name": "system",
"in": "body",
"type": "string",
"description": "Instruksi sistem kustom untuk AI.",
"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": "DeepSearch Chat",
"summary": "DeepSeek R1 / Deep Thinking Chat.",
"description": "Berinteraksi dengan model DeepSearch (DeepSeek R1/V3) yang mendukung kemampuan \"Reasoning\" atau berpikir mendalam sebelum menjawab. Endpoint ini menggunakan Server-Sent Events (SSE) untuk streaming output proses berpikir (reasoning) dan jawaban akhir.",
"method": "POST",
"path": "/api/ai/deepsearch",
"responseType": "json",
"example": "async function askDeepSearch() {\n const response = await fetch('/api/ai/deepsearch', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"prompt\": \"Jelaskan tentang Black Hole secara sederhana\",\n \"modelType\": \"reasoner\"\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: {\"type\": \"reasoning\"|\"text\", \"content\": \"...\"}\n console.log(text);\n }\n }",
"params": [
{
"name": "prompt",
"in": "body",
"type": "string",
"description": "Pertanyaan atau instruksi.",
"required": true
},
{
"name": "modelType",
"in": "body",
"type": "string",
"description": "Tipe model: 'reasoner' (Deep Thinking) atau 'chat' (Fast). Default: 'reasoner'.",
"required": false
}
]
},
{
"title": "DeepSeek R1",
"summary": "DeepSeek R1 via ChatGot.",
"description": "Berinteraksi dengan model DeepSeek R1 yang memiliki kemampuan reasoning (berpikir). Endpoint ini menggunakan Server-Sent Events (SSE) untuk streaming output proses berpikir (reasoning) dan jawaban akhir.",
"method": "POST",
"path": "/api/ai/deepseek",
"responseType": "json",
"example": "async function askDeepSeek() {\n const response = await fetch('/api/ai/deepseek', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"prompt\": \"Jelaskan kenapa langit berwarna biru?\"\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 // Output berupa SSE event: data: {...}\n console.log(text);\n }\n }",
"params": [
{
"name": "prompt",
"in": "body",
"type": "string",
"description": "Pertanyaan atau instruksi.",
"required": true
}
]
},
{
"title": "Dracin TTS",
"summary": "AI Voice gaya Drama China (Dracin).",
"description": "Mengubah teks menjadi suara dengan nada ala narator drama China. Mengembalikan URL audio hasil proses.",
"method": "POST",
"path": "/api/ai/dracin",
"responseType": "json",
"example": "async function speakDracin() {\n const res = await fetch('/api/ai/dracin', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"text\": \"Halo di sini soume\",\n \"music\": true \n })\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
},
{
"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 Image",
"summary": "Generate Gambar Flux AI.",
"description": "Menghasilkan gambar berkualitas tinggi menggunakan model Flux melalui proxy worker. Endpoint ini menggunakan Server-Sent Events (SSE).",
"method": "POST",
"path": "/api/ai/flux",
"responseType": "json",
"example": "// Contoh penggunaan (Membaca stream SSE di client)\n async function generateImage() {\n const response = await fetch('/api/ai/flux', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"prompt\": \"Cyberpunk city with neon lights, realistic style\" \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.",
"required": true
}
]
},
{
"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": "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": "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": "Claude Haiku AI",
"summary": "Claude Haiku Chat (Overchat).",
"description": "Berinteraksi dengan model Claude Haiku melalui provider Overchat.ai. Memberikan jawaban cerdas dan cepat. Credit: Hazel.",
"method": "POST",
"path": "/api/ai/overchat",
"responseType": "json",
"example": "async function askClaude() {\n const res = await fetch('/api/ai/overchat', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \"question\": \"Halo Claude!\" })\n });\n const data = await res.json();\n console.log(data.result);\n }",
"params": [
{
"name": "question",
"in": "body",
"type": "string",
"description": "Pertanyaan atau pesan untuk AI.",
"required": true
}
]
},
{
"title": "puruAI (Time Aware)",
"summary": "Advanced AI Gateway by PuruBoy.",
"description": "Model AI yang menyadari waktu dan urutan pesan. Mendukung persistensi riwayat (history) per UserID menggunakan Node-cache.",
"method": "POST",
"path": "/api/ai/puruai",
"responseType": "json",
"example": "async function chat() {\n const res = await fetch('/api/ai/puruai', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"userid\": \"user-session-001\", \n \"prompt\": \"Halo, siapa namamu?\",\n \"model\": \"puruboy-flash\",\n \"system\": \"Kamu adalah AI asisten dari PuruBoy yang ramah.\"\n })\n });\n const data = await res.json();\n console.log(data);\n }",
"params": [
{
"name": "userid",
"in": "body",
"type": "string",
"description": "Session ID untuk riwayat pesan persisten.",
"required": true
},
{
"name": "prompt",
"in": "body",
"type": "string",
"description": "Pesan dari pengguna.",
"required": true
},
{
"name": "model",
"in": "body",
"type": "string",
"description": "Pilihan model: 'puruboy-flash' atau 'puruboy-pro'.",
"required": true
},
{
"name": "system",
"in": "body",
"type": "string",
"description": "(Opsional) Instruksi kepribadian dasar AI.",
"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": "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 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
}
]
}
],
"downloader": [
{
"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 DL",
"summary": "Download Instagram (Video/Reels).",
"description": "Mengunduh konten dari Instagram (Video, Reels, Post) menggunakan AllInOneDownloader.",
"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/DOxOvd9jz6f/\" })\n });\n const data = await res.json();\n console.log(data);\n }",
"params": [
{
"name": "url",
"in": "body",
"type": "string",
"description": "URL konten Instagram.",
"required": true
}
]
},
{
"title": "Savetube Downloader",
"summary": "YouTube Video/Audio Downloader (Savetube).",
"description": "Mengunduh video atau audio dari YouTube menggunakan provider Savetube. Mendukung metadata lengkap dan pemilihan kualitas (720p, 1080p, MP3).",
"method": "POST",
"path": "/api/downloader/savetube",
"responseType": "json",
"example": "async function download() {\n const res = await fetch('/api/downloader/savetube', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://www.youtube.com/watch?v=Fmf-G9fpwto\",\n \"quality\": \"128\",\n \"type\": \"audio\"\n })\n });\n const data = await res.json();\n console.log(data);\n }",
"params": [
{
"name": "url",
"in": "body",
"type": "string",
"description": "URL Video YouTube.",
"required": true
},
{
"name": "quality",
"in": "body",
"type": "string",
"description": "Kualitas target (contoh: '1080', '720', '128' untuk MP3). Jika kosong, akan mengembalikan semua metadata.",
"required": false
},
{
"name": "type",
"in": "body",
"type": "string",
"description": "Tipe konten: 'video' atau 'audio'. Default: 'video'.",
"required": false
}
]
},
{
"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",
"summary": "Download lagu dari SoundCloud.",
"description": "Mengunduh file audio (MP3) dari SoundCloud menggunakan layanan pihak ketiga. Endpoint ini mengembalikan judul lagu dan URL unduhan langsung.",
"method": "POST",
"path": "/api/downloader/soundcloud",
"responseType": "json",
"example": "async function downloadSC() {\n try {\n const response = await fetch('/api/downloader/soundcloud', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"url\": \"https://soundcloud.com/marissa-puteri/dj-the-drum-x-ya-odna-tik-tok\" \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 downloadSC();",
"params": [
{
"name": "url",
"in": "body",
"type": "string",
"description": "URL lagu SoundCloud yang ingin diunduh.",
"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": "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": "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": "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": "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": "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": "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": "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://files.catbox.moe/1w27hq.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": "OnePage Host",
"summary": "Buat halaman web instan.",
"description": "Membuat dan meng-host halaman HTML statis secara gratis menggunakan layanan 1page. Berguna untuk membuat landing page sementara atau berbagi kode HTML hasil render.",
"method": "POST",
"path": "/api/tools/onepage",
"responseType": "json",
"example": "async function createPage() {\n const res = await fetch('/api/tools/onepage', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ \n \"name\": \"promo-today\", \n \"html\": \"Selamat Datang
Ini halaman otomatis.
\" \n })\n });\n const data = await res.json();\n console.log(data);\n }",
"params": [
{
"name": "name",
"in": "body",
"type": "string",
"description": "Nama atau slug halaman (contoh: 'halaman-saya').",
"required": true
},
{
"name": "html",
"in": "body",
"type": "string",
"description": "Konten kode HTML lengkap.",
"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 (Kolorize).",
"description": "Mewarnai gambar hitam putih menggunakan AI Kolorize. Endpoint ini menggunakan Server-Sent Events (SSE). Hasil akhir disimpan sementara dalam database selama 30 menit dan URL pengambilan data dikirim melalui stream.",
"method": "POST",
"path": "/api/tools/reviva",
"responseType": "json",
"example": "// Contoh penggunaan (Membaca stream SSE di client)\n 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 console.log(\"Received:\", text);\n \n // Cek sinyal sukses\n if(text.includes('[true]')) {\n const retrieveUrl = text.replace('[true]', '').trim();\n console.log(\"Data tersedia di:\", retrieveUrl);\n // fetch(retrieveUrl)...\n } else if (text.includes('[false]')) {\n const errorMsg = text.replace('[false]', '').trim();\n console.error(\"Error:\", errorMsg);\n }\n }\n }\n \n colorizeImage();",
"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 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
New Blog Post
---
// FILE: lib/ytsearch.js
const axios = require('axios');
/**
* Fungsi untuk mencari lagu di devers-en-geste.fr dan menampilkan Link YouTube
* @param {string} query - Kata kunci pencarian
*/
async function search(query) {
if (!query) throw new Error("Query is required.");
const baseURL = 'https://www.devers-en-geste.fr/search';
try {
const response = await axios.get(baseURL, {
params: {
q: query
},
headers: {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'Referer': 'https://www.devers-en-geste.fr/'
}
});
const data = response.data;
if (!data.items) return [];
return data.items.map(item => ({
title: item.title,
url: `https://www.youtube.com/watch?v=${item.id}`,
videoId: item.id,
channel: item.channelTitle,
duration: item.duration,
size: item.size,
thumbnail: `https://i.ytimg.com/vi/${item.id}/hqdefault.jpg`
}));
} catch (error) {
throw new Error(error.message);
}
}
module.exports = { search };
---
// FILE: lib/ytmp3.js
const axios = require('axios');
const vm = require('vm');
// ==========================================
// MOCK DOM (Minimalist)
// ==========================================
function createMockDOM() {
const noop = () => {};
const mockElement = {
style: {},
setAttribute: noop,
getAttribute: () => '',
appendChild: () => mockElement,
innerHTML: '',
value: '',
click: noop
};
return {
window: {},
document: {
getElementById: () => mockElement,
createElement: () => mockElement,
querySelector: () => mockElement,
querySelectorAll: () => [mockElement],
cookie: '',
body: mockElement,
head: mockElement,
location: { href: 'https://id.ytmp3.mobi/' }
},
navigator: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/121.0.0.0 Safari/537.36',
serviceWorker: { register: () => Promise.resolve() }
},
location: { href: 'https://id.ytmp3.mobi/' },
console: { log: noop, error: noop },
String: String, Math: Math, Date: Date, parseInt: parseInt,
setTimeout: (cb) => cb(), setInterval: noop, clearTimeout: noop
};
}
// ==========================================
// CONFIG FETCHER
// ==========================================
async function getFreshConfig() {
try {
const homeRes = await axios.get('https://id.ytmp3.mobi/v1/');
const jsMatch = homeRes.data.match(/src="(\/js\/ytmp3\.js\?t=[0-9]+)"/);
if (!jsMatch) throw new Error('JS File not found');
const jsUrl = `https://id.ytmp3.mobi${jsMatch[1]}`;
const jsRes = await axios.get(jsUrl);
const code = jsRes.data;
// --- STEP 1: VM Execution ---
const sandbox = createMockDOM();
sandbox.window = sandbox;
const context = vm.createContext(sandbox);
try { vm.runInContext(code, context); } catch (e) {}
let backend = sandbox.backend;
// --- STEP 2: FIX BACKEND ---
if (!backend || backend === '.ymcdn.org' || backend.startsWith('https:.') || backend.startsWith('.')) {
const subMatch = code.match(/['"](https:\/\/[a-z])['"]/);
if (subMatch) {
backend = `${subMatch[1]}.ymcdn.org`;
} else {
backend = 'https://d.ymcdn.org';
}
} else {
if (backend.startsWith('//')) backend = 'https:' + backend;
if (!backend.startsWith('http')) backend = 'https://' + backend;
}
// --- STEP 3: DECODE INIT PARAMS ---
let initQuery = 'it?p=y&23=';
let initToken = '1llum1n471';
const decoderMatch = code.match(/var\s+(_0x[a-f0-9]+)\s*=\s*_0x[a-f0-9]+;/);
if (decoderMatch) {
const decoder = sandbox[decoderMatch[1]];
if (typeof decoder === 'function') {
for (let i = 0; i < 800; i++) {
try {
const val = decoder(i);
if (val && typeof val === 'string') {
if (val.includes('it?p=')) initQuery = val;
if (val.length === 10 && /\d.*[a-z]/.test(val)) initToken = val;
}
} catch (e) {}
}
}
}
return { BASE_DOMAIN: backend, INIT_QUERY: initQuery, INIT_TOKEN: initToken };
} catch (error) {
return {
BASE_DOMAIN: 'https://d.ymcdn.org',
INIT_QUERY: 'it?p=y&23=',
INIT_TOKEN: '1llum1n471'
};
}
}
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/121.0.0.0 Safari/537.36',
'Referer': 'https://id.ytmp3.mobi/',
'Origin': 'https://id.ytmp3.mobi'
};
const getRandom = () => Math.random().toString();
async function download(url) {
if (!url) throw new Error("URL wajib diisi.");
// Extract Video ID (Support standard & short links)
const idMatch = url.match(/(?:v=|\/)([0-9A-Za-z_-]{11})/);
if (!idMatch) throw new Error("URL YouTube tidak valid.");
const videoId = idMatch[1];
try {
// 1. Config
const config = await getFreshConfig();
// 2. Init
const cleanQuery = config.INIT_QUERY.replace('it?', 'init?').replace('/api/v1/', '');
const initUrl = `${config.BASE_DOMAIN}/api/v1/${cleanQuery}${config.INIT_TOKEN}&_=${getRandom()}`;
const initRes = await axios.get(initUrl, { headers: HEADERS });
if (initRes.data.error) throw new Error(initRes.data.error);
// 3. Convert
const doConvert = async (targetUrl) => {
const prefix = targetUrl.includes('?') ? '&' : '?';
const res = await axios.get(`${targetUrl}${prefix}v=${videoId}&f=mp3&_=${getRandom()}`, { headers: HEADERS });
if (res.data.redirectURL) return doConvert(res.data.redirectURL);
return res.data;
};
const convertData = await doConvert(initRes.data.convertURL);
// 4. Progress
let result = null;
for (let i = 0; i < 40; i++) {
const res = await axios.get(`${convertData.progressURL}&_=${getRandom()}`, { headers: HEADERS });
if (res.data.progress == 3) {
result = res.data;
break;
}
await new Promise(r => setTimeout(r, 1500));
}
if (!result) throw new Error('Timeout saat konversi.');
return {
title: result.title,
download_url: convertData.downloadURL,
source: 'ytmp3.mobi'
};
} catch (e) {
throw new Error(e.message || "Gagal mengunduh MP3.");
}
}
module.exports = { download };
---
// FILE: lib/ytdown.js
const axios = require('axios');
const qs = require('qs');
/**
* YTDown.to Automation Fix
* Berdasarkan hasil intercept AJAX & HAR Terbaru
*/
class YTDown {
constructor() {
this.baseUrl = 'https://app.ytdown.to';
this.session = axios.create({
baseURL: this.baseUrl,
headers: {
'authority': 'app.ytdown.to',
'accept': '*/*',
'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'origin': this.baseUrl,
'referer': `${this.baseUrl}/id2/`,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'x-requested-with': 'XMLHttpRequest'
},
withCredentials: true
});
this.cookie = "";
}
async download(youtubeUrl) {
try {
// --- STEP 1: INITIAL VISIT (Get Session Cookie) ---
const init = await this.session.get('/id2/');
this.cookie = init.headers['set-cookie'] ? init.headers['set-cookie'][0].split(';')[0] : "";
// Update header dengan cookie yang didapat
const headers = { 'Cookie': this.cookie };
// --- STEP 2: COOLDOWN CHECK (Handshake) ---
const check = await this.session.post('/cooldown.php', qs.stringify({ action: 'check' }), { headers });
if (!check.data.can_download) {
throw new Error("Server Cooldown: Silakan tunggu beberapa saat.");
}
// --- STEP 3: GET VIDEO INFO & FORMATS ---
const info = await this.session.post('/proxy.php', qs.stringify({ url: youtubeUrl }), { headers });
if (!info.data.api || info.data.api.status !== 'ok') {
throw new Error("Gagal mengambil info video. Pastikan URL benar.");
}
const videoData = info.data.api;
// Pilih kualitas (Default: HD/720p atau pertama tersedia)
const selectedMedia = videoData.mediaItems.find(m => m.mediaQuality === 'HD') || videoData.mediaItems[0];
// --- STEP 4: RECORD ACTION ---
await this.session.post('/cooldown.php', qs.stringify({ action: 'record' }), { headers });
// --- STEP 5: POLLING CONVERSION ---
let isReady = false;
let downloadLink = "";
let attempts = 0;
while (!isReady && attempts < 30) {
const convert = await this.session.post('/proxy.php', qs.stringify({ url: selectedMedia.mediaUrl }), { headers });
const result = convert.data.api;
if (result.status === 'completed') {
isReady = true;
downloadLink = result.fileUrl;
return {
success: true,
title: videoData.title,
quality: selectedMedia.mediaQuality,
size: result.fileSize,
downloadUrl: downloadLink,
thumbnail: videoData.imagePreviewUrl
};
} else if (result.status === 'queued' || result.status === 'processing') {
attempts++;
await new Promise(r => setTimeout(r, 3000)); // Tunggu 3 detik
} else {
throw new Error("Terjadi kesalahan saat konversi.");
}
}
throw new Error("Timeout: Proses terlalu lama.");
} catch (err) {
throw new Error(err.message);
}
}
}
module.exports = new YTDown();
---
// FILE: lib/xdownloader.js
const axios = require('axios');
const cheerio = require('cheerio');
/**
* X/Twitter Video Downloader for xsaver.io
* @param {string} twitterUrl - URL video dari X (Twitter)
*/
async function getXVideoInfo(twitterUrl) {
try {
const baseUrl = 'https://www.xsaver.io/x-downloader/';
const targetUrl = `${baseUrl}download.php?url=${encodeURIComponent(twitterUrl)}`;
const response = await axios.get(targetUrl, {
headers: {
'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',
'Referer': 'https://www.xsaver.io/x-downloader/id/',
'Accept-Language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7'
}
});
const $ = cheerio.load(response.data);
const results = [];
// 1. Ambil Judul Video
const title = $('.video-title').text().trim();
// 2. Iterasi setiap item media yang ditemukan
$('.media-item').each((index, element) => {
const thumb = $(element).find('.media-thumb img').attr('src');
// Mencari link download video (save-url.php)
const downloadLinkRaw = $(element).find('a[href^="save-url.php"]').attr('href');
if (downloadLinkRaw) {
// Ekstraksi URL asli dari parameter query 'url'
const urlParams = new URLSearchParams(downloadLinkRaw.split('?')[1]);
const directVideoUrl = urlParams.get('url');
results.push({
id: index + 1,
type: 'video',
thumbnail: thumb,
url: directVideoUrl,
proxy_link: baseUrl + downloadLinkRaw
});
}
});
return {
success: true,
title: title || 'X Video',
results: results
};
} catch (error) {
return {
success: false,
message: error.message
};
}
}
module.exports = { getXVideoInfo };
---
// FILE: lib/upscale.js
const axios = require('axios');
const FormData = require('form-data');
const { uploadToTmp } = require('./uploader');
// --- KONFIGURASI CONSTANTS ---
const TARGET_URL = 'https://cloudinary.com/tools/image-upscale';
const SIGNER_URL = 'https://cloudinary-tools.netlify.app/.netlify/functions/sign-upload-params';
// --- FALLBACK CONFIG ---
const FALLBACK_CONFIG = {
cloudName: 'dtz0urit6',
apiKey: '985946268373735',
uploadPreset: 'cloudinary-tools'
};
const client = axios.create({
headers: {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Referer': TARGET_URL
}
});
/**
* 1. DYNAMIC CONFIG EXTRACTOR
*/
async function getDynamicConfig() {
try {
const htmlParams = await client.get(TARGET_URL);
const scriptMatch = htmlParams.data.match(/src="([^"]*\/app\.js[^"]*)"/);
if (!scriptMatch) throw new Error("Path app.js tidak ditemukan.");
const appJsUrl = new URL(scriptMatch[1], TARGET_URL).href;
const jsParams = await client.get(appJsUrl);
const jsContent = jsParams.data;
const cloudNameMatch = jsContent.match(/cloudName\s*=\s*\(isLocal\)\s*\?\s*'[^']+'\s*:\s*'([^']+)'/);
const apiKeyMatch = jsContent.match(/api_key\s*=\s*\(isLocal\)\s*\?\s*'[^']+'\s*:\s*'([^']+)'/);
const presetMatch = jsContent.match(/uploadPreset\s*=\s*\(isLocal\)\s*\?\s*'[^']+'\s*:\s*'([^']+)'/);
if (cloudNameMatch && apiKeyMatch && presetMatch) {
return {
cloudName: cloudNameMatch[1],
apiKey: apiKeyMatch[1],
uploadPreset: presetMatch[1]
};
}
throw new Error("Gagal regex config.");
} catch (error) {
return FALLBACK_CONFIG;
}
}
/**
* 2. SIGNATURE GENERATOR
*/
async function getSignature(config, timestamp) {
try {
const payload = {
paramsToSign: {
source: 'uw',
timestamp: timestamp,
upload_preset: config.uploadPreset
}
};
const response = await client.post(SIGNER_URL, payload, {
headers: { 'Content-Type': 'application/json' }
});
if (!response.data.signature) throw new Error("Signature kosong.");
return response.data.signature;
} catch (error) {
throw new Error(`Gagal get signature: ${error.message}`);
}
}
/**
* 3. UPLOADER (Buffer Support)
*/
async function uploadImage(config, signature, timestamp, imageBuffer) {
const form = new FormData();
form.append('file', imageBuffer, { filename: 'input.jpg' });
form.append('api_key', config.apiKey);
form.append('timestamp', timestamp);
form.append('upload_preset', config.uploadPreset);
form.append('signature', signature);
form.append('source', 'uw');
const uploadUrl = `https://api.cloudinary.com/v1_1/${config.cloudName}/auto/upload`;
try {
const response = await client.post(uploadUrl, form, {
headers: { ...form.getHeaders() }
});
return response.data;
} catch (error) {
throw new Error(`Upload gagal: ${error.response?.data?.error?.message || error.message}`);
}
}
const upscale = {
process: async (url) => {
try {
// 1. Download source image
const imgRes = await axios.get(url, { responseType: 'arraybuffer' });
const imgBuffer = Buffer.from(imgRes.data);
// 2. Get Config
const config = await getDynamicConfig();
// 3. Auth
const timestamp = Math.floor(Date.now() / 1000);
const signature = await getSignature(config, timestamp);
// 4. Upload to Cloudinary
const uploadResult = await uploadImage(config, signature, timestamp, imgBuffer);
// 5. Construct URL
// Parameter Transformasi Cloudinary: e_upscale, q_auto, f_auto
const transformation = 'e_upscale,q_auto,f_auto';
const cloudinaryUrl = `https://res.cloudinary.com/${config.cloudName}/image/upload/${transformation}/${uploadResult.public_id}`;
// 6. Download Result
const resultRes = await axios.get(cloudinaryUrl, { responseType: 'arraybuffer' });
const resultBuffer = Buffer.from(resultRes.data);
// 7. Upload to Public Server (Puruh2o / tmp)
const publicUrl = await uploadToTmp(resultBuffer, `upscale-${Date.now()}.jpg`);
return {
success: true,
image: publicUrl
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
};
module.exports = { upscale };
---
// FILE: lib/uploader.js
const axios = require('axios');
const FormData = require('form-data');
const { encrypt } = require('./crypto');
/**
* Upload file ke layanan sementara (tmpfiles.org).
* Mengembalikan URL Proxy terenkripsi (/api/media/...).
*/
async function uploadToTmp(buffer, filename = 'image.png') {
if (!Buffer.isBuffer(buffer)) {
throw new Error('Input harus berupa Buffer.');
}
const form = new FormData();
form.append("file", buffer, filename);
try {
const response = await axios.post("https://tmpfiles.org/api/v1/upload", form, {
headers: {
...form.getHeaders(),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
}
});
if (response.data.status !== 'success') {
throw new Error('Gagal mengupload ke tmpfiles.org');
}
const rawUrl = response.data.data.url;
// Perbaikan Regex: Pastikan menyisipkan /dl/ tepat setelah domain tmpfiles.org
// Mendukung variasi http/https dan www.
const realUrl = rawUrl.replace(/https?:\/\/(www\.)?tmpfiles\.org\//, 'https://tmpfiles.org/dl/');
// Encrypt URL dan kembalikan Path Proxy relatif
const encrypted = encrypt(realUrl);
const proxyUrl = `/api/media/${encrypted}`;
return proxyUrl;
} catch (error) {
if (error.response) {
throw new Error(`Uploader Error: Upload failed with status ${error.response.status}`);
}
throw new Error(`Uploader Error: ${error.message}`);
}
}
module.exports = { uploadToTmp };
---
// FILE: lib/unlimited.js
const axios = require('axios');
const { v4: uuidv4 } = require('uuid');
const TARGET_URL = 'https://app.unlimitedai.chat/';
const ACTION_ID = '40713570958bf1accf30e8d3ddb17e7948e6c379fa'; // ID Fungsi Server
const CHAT_MODEL = 'chat-model-reasoning'; // Model default
function parseNextJsStream(chunk) {
const lines = chunk.toString().split('\n');
let cleanText = '';
for (const line of lines) {
if (line.includes('"diff":[0,')) {
try {
const jsonStartIndex = line.indexOf('{');
if (jsonStartIndex !== -1) {
const jsonStr = line.substring(jsonStartIndex);
const data = JSON.parse(jsonStr);
if (data.diff && Array.isArray(data.diff) && data.diff[0] === 0) {
cleanText += data.diff[1];
}
}
} catch (e) {
// Abaikan error parsing
}
}
}
return cleanText;
}
async function* chatStream(message) {
const HEADERS = {
'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',
'Content-Type': 'text/plain;charset=UTF-8',
'Next-Action': ACTION_ID,
'Next-Router-State-Tree': '%5B%22%22%2C%7B%22children%22%3A%5B%22(chat)%22%2C%7B%22children%22%3A%5B%22page%22%2C%7B%7D%5D%7D%5D%7D%2Cnull%2Cnull%2Ctrue%5D',
'Origin': 'https://app.unlimitedai.chat',
'Referer': 'https://app.unlimitedai.chat/',
};
const chatId = uuidv4();
const messageId = uuidv4();
const now = new Date();
const messages = [
{
id: messageId,
role: "user",
content: message,
parts: [{ type: "text", text: message }],
createdAt: now
}
];
const payloadArg = {
chatId: chatId,
messages: messages,
selectedChatModel: CHAT_MODEL,
selectedCharacter: null,
selectedStory: null,
turnstileToken: undefined
};
const payload = JSON.stringify([payloadArg]);
try {
const response = await axios.post(TARGET_URL, payload, {
headers: HEADERS,
responseType: 'stream'
});
for await (const chunk of response.data) {
const text = parseNextJsStream(chunk);
if (text) yield text;
}
} catch (error) {
throw new Error(error.response?.data ? 'API Unlimited Error' : error.message);
}
}
module.exports = { chatStream };
---
// FILE: lib/tsundere.js
const axios = require('axios');
function generateFakeIP() {
return Array.from({ length: 4 }, () => Math.floor(Math.random() * 255)).join('.');
}
async function generateTsundereTTS(text) {
const url = 'https://api.screenapp.io/v2/proxy/google/tts';
const fakeIP = generateFakeIP();
const payload = {
"input": text,
"model": "gemini-2.5-flash-tts",
"voice": "Kore",
"language_code": "id-ID",
"response_format": "mp3",
"speaking_rate": 1.1,
"pitch": 2.5,
"volume_gain_db": 0
};
const headers = {
'authority': 'api.screenapp.io',
'accept': '*/*',
'content-type': 'application/json',
'origin': 'https://screenapp.io',
'referer': 'https://screenapp.io/',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
'x-forwarded-for': fakeIP,
'client-ip': fakeIP,
'via': '1.1 google',
};
try {
const response = await axios({
method: 'post',
url: url,
data: payload,
headers: headers,
responseType: 'arraybuffer'
});
return Buffer.from(response.data);
} catch (error) {
throw new Error(error.response?.data ? `TTS Error: ${error.response.status}` : error.message);
}
}
module.exports = { generateTsundereTTS };
---
// FILE: lib/tiktokV2.js
/***
*** ᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁
*** - TikTok Downloader
*** - Base URL: https://tikdownloader.io
*** - Note: Jangan lupa install cloudscraper
***
*** - Dev: 𝖸𝖺𝖻𝖾𝗌
*** - Contact: t.me/Yabes_Desu
*** - Gmail: yabeskun@gmail.com
*** ᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁᠁
***/
const cloudscraper = require('cloudscraper');
const tiktokDL = async (url, retries = 5) => {
if (!url?.trim()) return { success: false, result: 'URL kosong' };
const req = async (opts) => {
for (let i = 0; i < retries; i++) {
try {
const r = await cloudscraper({ ...opts, cloudflareTimeout: 7000, followAllRedirects: true });
return typeof r === 'string' ? JSON.parse(r) : r;
} catch (e) {
if (i === retries - 1) throw e;
await new Promise(r => setTimeout(r, 2 ** i * 1000));
}
}
};
try {
const { status, data, statusCode, msg } = await req({
uri: 'https://tikdownloader.io/api/ajaxSearch',
method: 'POST',
form: { q: url }
});
if (statusCode === 326) return { success: false, result: msg || 'Link invalid' };
if (status !== 'ok' || !data) return { success: false, result: 'Gagal ambil data' };
const html = data.replace(/&(?:amp|lt|gt|quot|#x27|#39|#x2F|nbsp|#xA0|#160|#(\d+)|#x([0-9a-fA-F]+));/gi,
(_, dec, hex) => dec ? String.fromCharCode(dec) : hex ? String.fromCharCode(parseInt(hex, 16)) :
{ '&':'&','<':'<','>':'>','"':'"',''':"'",''':"'",'/':'/',' ':' ',' ':' ',' ':' ' }[_] || _);
const $ = s => (html.match(s) || [])[1]?.trim();
const isPhoto = html.includes('photo-list');
const downloads = isPhoto
? [...html.matchAll(/href="([^"]+)"[^>]*btn-premium[^>]*>[\s\S]*?Download Image/g)].map((m, i) => ({ type: `Image ${i+1}`, url: m[1] }))
.concat((html.match(/href="([^"]+dl\.snapcdn\.app[^"]+)".*?Download MP3/) || []).slice(1).map(u => ({ type: 'MP3', url: u })))
: [...html.matchAll(/href="([^"]+)"[^>]*tik-button-dl[^>]*>([\s\S]*?)<\/a>/g)].map(m => ({
type: m[2].replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim(),
url: m[1]
}));
if (!downloads.length) return { success: false, result: 'Tidak ada link download' };
return {
success: true,
result: {
type: isPhoto ? 'photo' : 'video',
title: $(/]*>([^<]+)<\/h3>/),
thumbnail: $(/
]*(?:class="[^"]*image-tik[^"]*"|)/),
downloads
}
};
} catch (e) {
return { success: false, result: e.message };
}
};
module.exports = { tiktokDL };
---
// FILE: lib/tiktok.js
// Memindahkan file dari server/api/lib/tiktok.js ke lib/tiktok.js
const axios = require('axios');
const TIKTOK_API_BASE = 'https://www.tikwm.com';
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function download(url) {
if (!url || typeof url !== 'string') {
throw new Error('URL TikTok tidak valid.');
}
const submitResponse = await axios.post(`${TIKTOK_API_BASE}/api/video/task/submit`, new URLSearchParams({
url: url,
web: '1'
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
});
if (submitResponse.data.code !== 0 || !submitResponse.data.data.task_id) {
throw new Error(`Gagal memulai tugas unduhan: ${submitResponse.data.msg || 'Respons tidak valid'}`);
}
const taskId = submitResponse.data.data.task_id;
const maxAttempts = 15;
for (let i = 0; i < maxAttempts; i++) {
await sleep(1000);
const resultResponse = await axios.get(`${TIKTOK_API_BASE}/api/video/task/result`, {
params: { task_id: taskId }
});
const resultData = resultResponse.data;
if (resultData.code !== 0) {
continue;
}
if (resultData.data && resultData.data.status === 2) {
return resultData.data;
}
if (resultData.data && resultData.data.status > 2) {
throw new Error(`Proses unduhan gagal dengan status: ${resultData.data.msg || 'Tidak diketahui'}`);
}
}
throw new Error('Gagal mendapatkan hasil unduhan setelah beberapa kali percobaan (timeout).');
}
module.exports = { download };
---
// FILE: lib/tempService.js
const pool = require('./db');
const { v4: uuidv4 } = require('uuid');
// Ensure table exists
const ensureTable = async () => {
const query = `
CREATE TABLE IF NOT EXISTS temp_store (
id UUID PRIMARY KEY,
data JSONB NOT NULL,
expires_at TIMESTAMPTZ NOT NULL
);
`;
await pool.query(query);
};
const tempService = {
save: async (data, ttlMinutes = 30) => {
await ensureTable();
const id = uuidv4();
// Set expiry time
const expiresAt = new Date(Date.now() + ttlMinutes * 60000);
const query = 'INSERT INTO temp_store (id, data, expires_at) VALUES ($1, $2, $3)';
await pool.query(query, [id, data, expiresAt]);
return id;
},
get: async (id) => {
await ensureTable();
// Fetch only if not expired
const query = 'SELECT data FROM temp_store WHERE id = $1 AND expires_at > NOW()';
const result = await pool.query(query, [id]);
if (result.rows.length === 0) return null;
return result.rows[0].data;
}
};
module.exports = tempService;
---
// FILE: lib/svara.js
// Memindahkan file dari server/api/lib/svara.js ke lib/svara.js
// Credit: Daffa dari nbscript (https://whatsapp.com/channel/0029VbBmAXAHAdNWOpWN531c)
const axios = require('axios');
const svara = {
api: {
base: 'https://svara.aculix.net',
endpoint: {
generate: '/generate-speech',
},
},
headers: {
'user-agent': 'NB Android/1.0.0',
'accept-encoding': 'gzip',
'content-type': 'application/json',
},
cid: new Uint8Array([
0x24, 0x52, 0x43, 0x41, 0x6e, 0x6f, 0x6e, 0x79,
0x6d, 0x6f, 0x75, 0x73, 0x49, 0x44, 0x3a, 0x31,
0x33, 0x65, 0x38, 0x37, 0x35, 0x33, 0x61, 0x65,
0x36, 0x31, 0x39, 0x34, 0x63, 0x37, 0x62, 0x39,
0x32, 0x37, 0x33, 0x32, 0x64, 0x36, 0x36, 0x64,
0x37, 0x30, 0x32, 0x33, 0x30, 0x37, 0x32
]),
auth: new Uint8Array([
0x77, 0x76, 0x65, 0x62, 0x6e, 0x79, 0x75, 0x36, 0x36, 0x36, 0x38, 0x37, 0x35, 0x36, 0x68, 0x34,
0x35, 0x67, 0x66, 0x65, 0x63, 0x64, 0x66, 0x65, 0x67, 0x6e, 0x68, 0x6d, 0x75, 0x36, 0x6b, 0x6a,
0x35, 0x68, 0x36, 0x34, 0x67, 0x35, 0x33, 0x66, 0x76, 0x72, 0x62, 0x67, 0x6e, 0x79, 0x35
]),
voiceX: {
'alloy': 'af_alloy', 'aoede': 'af_aoede', 'bella': 'af_bella', 'heart': 'af_heart',
'jessica': 'af_jessica', 'kore': 'af_kore', 'nicole': 'af_nicole', 'nova': 'af_nova',
'river': 'af_river', 'sarah': 'af_sarah', 'sky': 'af_sky',
'adam': 'am_adam', 'echo': 'am_echo', 'eric': 'am_eric', 'fenrir': 'am_fenrir',
'liam': 'am_liam', 'michael': 'am_michael', 'onyx': 'am_onyx', 'puck': 'am_puck',
'santa': 'am_santa',
'alice': 'bf_alice', 'emma': 'bf_emma', 'isabella': 'bf_isabella', 'lily': 'bf_lily',
'daniel': 'bm_daniel', 'fable': 'bm_fable', 'george': 'bm_george', 'lewis': 'bm_lewis',
'anaya': 'hf_alpha', 'riya': 'hf_beta', 'arjun': 'hm_omega', 'kabir': 'hm_psi',
'dora': 'ef_dora',
'santiago': 'em_alex', 'noel': 'em_santa',
'siwis': 'ff_siwis',
'aiko': 'jf_alpha', 'gongitsune': 'jf_gongitsune', 'nezumi': 'jf_nezumi',
'tebukuro': 'jf_tebukuro', 'kumo': 'jm_kumo',
'sara': 'if_sara', 'nicola': 'im_nicola',
'doras': 'pf_dora',
'alex': 'pm_alex', 'antonio': 'pm_santa',
'xiaobei': 'zf_xiaobei', 'xiaoni': 'zf_xiaoni', 'xiaoxiao': 'zf_xiaoxiao',
'xiaoyi': 'zf_xiaoyi', 'yunjian': 'zm_yunjian', 'yunxi': 'zm_yunxi',
'yunxia': 'zm_yunxia', 'yunyang': 'zm_yunyang'
},
getVoiceId: function(vn) {
const i = vn.toLowerCase().trim();
return this.voiceX[i];
},
generate: async function(text, vn) {
if (!text?.trim()) {
return {
success: false,
code: 400,
author: 'PuruBoy x Daffa (nbscript)',
result: {
error: 'Parameter `text` tidak boleh kosong.'
},
};
}
if (text.length > 300) {
return {
success: false,
code: 413,
author: 'PuruBoy x Daffa (nbscript)',
result: {
error: 'Panjang `text` maksimal 300 karakter.'
},
};
}
const voiceId = this.getVoiceId(vn);
if (!voiceId) {
const av = Object.keys(this.voiceX).join(', ');
return {
success: false,
code: 422,
author: 'PuruBoy x Daffa (nbscript)',
result: {
error: `Nama voice "${vn}" tidak valid. Pilih salah satu dari: ${av}`
},
};
}
const decoder = new TextDecoder();
const ciu = decoder.decode(this.cid);
const toket = decoder.decode(this.auth);
const body = {
customerId: ciu,
text: text,
voice: voiceId,
};
try {
const res = await axios.post(
`${this.api.base}${this.api.endpoint.generate}`,
body,
{
headers: {
...this.headers,
authorization: toket
}
}
);
const { outputUrl } = res.data;
return {
success: true,
code: 200,
author: 'PuruBoy x Daffa (nbscript)',
result: {
audio: outputUrl,
voice: voiceId,
text_length: text.length,
},
};
} catch (err) {
return {
success: false,
code: err.response?.status || 500,
author: 'PuruBoy x Daffa (nbscript)',
result: {
error: err.message || 'Terjadi kesalahan internal.',
},
};
}
},
};
module.exports = { svara };
---
// FILE: lib/soundcloudSearch.js
const axios = require("axios");
const qs = require("querystring");
let cachedID = null;
// Step 1: Ambil client_id dengan cara modern
async function getClientID() {
if (cachedID) return cachedID;
const homepage = await axios.get("https://soundcloud.com");
const scriptUrls = [...homepage.data.matchAll(/