| const axios = require('axios'); |
| const dns = require('dns').promises; |
|
|
| const PROXY_URL = 'http://pnode1.danbot.host:1271'; |
| const API_BASE_URL = 'https://api.bylo.ai'; |
| const keyGua = process.env.KEYGUA |
| dns.setServers(['1.1.1.1', '8.8.8.8', '8.8.4.4']); |
|
|
| function generateUniqueId() { |
| return Array.from({ length: 32 }, () => |
| Math.floor(Math.random() * 16).toString(16) |
| ).join(''); |
| } |
|
|
| function generatePassword() { |
| const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; |
| let password = ''; |
| for (let i = 0; i < 12; i++) { |
| password += chars.charAt(Math.floor(Math.random() * chars.length)); |
| } |
| return password; |
| } |
|
|
| function randomDelay(min = 1000, max = 3000) { |
| const delay = Math.floor(Math.random() * (max - min + 1)) + min; |
| return new Promise(resolve => setTimeout(resolve, delay)); |
| } |
|
|
| function generateRandomIP() { |
| return `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`; |
| } |
|
|
| async function proxyRequest(path, options = {}) { |
| const apiPath = path.startsWith('http') ? path : path; |
| const fakeIP = generateRandomIP(); |
| |
| const headers = { |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', |
| 'Accept': 'application/json, text/plain, */*', |
| 'Accept-Language': 'en-US,en;q=0.9', |
| 'X-Forwarded-For': fakeIP, |
| 'X-Real-IP': fakeIP, |
| 'Content-Type': 'application/json', |
| ...(options.headers || {}) |
| }; |
| |
| await randomDelay(300, 800); |
| |
| const axiosConfig = { |
| url: PROXY_URL, |
| method: options.method || 'GET', |
| params: { |
| url: apiPath |
| }, |
| headers: headers, |
| timeout: 60000, |
| validateStatus: function (status) { |
| return status >= 200 && status < 600; |
| } |
| }; |
| |
| if (options.data && (options.method === 'POST' || options.method === 'PUT')) { |
| axiosConfig.data = options.data; |
| } |
| |
| let lastError = null; |
| |
| for (let attempt = 1; attempt <= 3; attempt++) { |
| try { |
| console.log(`[${new Date().toISOString()}] Attempt ${attempt}: ${apiPath}`); |
| |
| const response = await axios(axiosConfig); |
| |
| console.log(`[${new Date().toISOString()}] Status ${response.status}`); |
| |
| if (response.data && response.data.error) { |
| const errorMsg = response.data.message || 'Unknown error'; |
| throw new Error(`API error (${response.data.status || 400}): ${errorMsg}`); |
| } |
| |
| if (response.status === 403) { |
| console.log('Got 403, waiting...'); |
| await randomDelay(3000, 5000); |
| throw new Error('403 Forbidden'); |
| } |
| |
| if (response.status === 429) { |
| console.log('Got 429, waiting...'); |
| await randomDelay(5000, 8000); |
| if (attempt < 3) continue; |
| throw new Error('Rate limit exceeded'); |
| } |
| |
| if (response.status >= 200 && response.status < 300) { |
| if (!response.data) { |
| throw new Error('Empty response'); |
| } |
| return response; |
| } |
| |
| if (response.status >= 400) { |
| const errorMsg = response.data?.msg || response.data?.message || 'Unknown error'; |
| throw new Error(`API error (${response.status}): ${errorMsg}`); |
| } |
| |
| if (attempt < 3) { |
| await randomDelay(2000, 3000); |
| } |
| |
| } catch (error) { |
| lastError = error; |
| console.error(`[${new Date().toISOString()}] Attempt ${attempt} failed:`, error.message); |
| |
| if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) { |
| console.error('Timeout error detected'); |
| } |
| |
| if (error.response) { |
| console.error(`Response status: ${error.response.status}`); |
| console.error(`Response data:`, JSON.stringify(error.response.data).substring(0, 200)); |
| } |
| |
| if (attempt < 3) { |
| const waitTime = 2000 * attempt; |
| console.log(`Retrying in ${waitTime/1000}s...`); |
| await randomDelay(waitTime, waitTime + 1000); |
| } |
| } |
| } |
| |
| throw new Error(`Proxy request failed: ${lastError?.message || 'Unknown error'}`); |
| } |
|
|
| async function createTempEmail() { |
| console.log('Creating temporary email...'); |
| const { data } = await axios.post('https://api.internal.temp-mail.io/api/v3/email/new', { |
| min_name_length: 10, |
| max_name_length: 10 |
| }, { |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Application-Name': 'web', |
| 'Application-Version': '4.0.0', |
| 'X-CORS-Header': 'iaWg3pchvFx48fY' |
| }, |
| timeout: 20000 |
| }); |
| |
| console.log(`Email created: ${data.email}`); |
| return data; |
| } |
|
|
| async function getHcaptchaToken() { |
| console.log('Getting hCaptcha token...'); |
| |
| const apis = [ |
| { |
| name: 'Anabot', |
| url: `https://anabot.my.id/api/tools/bypass?url=https%3A%2F%2Fbylo.ai%2Ffeatures%2Fsora-2&siteKey=6f70c0f2-3ef6-4972-9fb6-c0b4bade3af8&type=hcaptcha-invisible&apikey=${keyGua}`, |
| extract: (data) => data.data.result.token |
| }, |
| { |
| name: 'NopeCHA', |
| url: 'https://api.nopecha.com/token', |
| method: 'POST', |
| data: { |
| type: 'hcaptcha', |
| sitekey: '6f70c0f2-3ef6-4972-9fb6-c0b4bade3af8', |
| url: 'https://bylo.ai/features/sora-2' |
| }, |
| extract: (data) => data.token |
| } |
| ]; |
| |
| for (const api of apis) { |
| try { |
| console.log(`Trying ${api.name}...`); |
| |
| const config = { |
| url: api.url, |
| method: api.method || 'GET', |
| timeout: 15000 |
| }; |
| |
| if (api.data) { |
| config.data = api.data; |
| config.headers = { 'Content-Type': 'application/json' }; |
| } |
| |
| const { data } = await axios(config); |
| |
| if (data.success !== false) { |
| const token = api.extract(data); |
| if (token) { |
| console.log(`hCaptcha token obtained from ${api.name}`); |
| return token; |
| } |
| } |
| } catch (error) { |
| console.log(`${api.name} failed:`, error.message); |
| continue; |
| } |
| } |
| |
| throw new Error('All hCaptcha bypass services failed'); |
| } |
|
|
| async function sendVerificationEmail(email) { |
| console.log(`Sending verification email to ${email}...`); |
| |
| await randomDelay(500, 1000); |
| |
| let hcaptchaToken = ''; |
| try { |
| hcaptchaToken = await getHcaptchaToken(); |
| } catch (error) { |
| console.log('hCaptcha bypass failed, trying without token...'); |
| hcaptchaToken = ''; |
| } |
| |
| const encodedEmail = encodeURIComponent(email); |
| |
| await randomDelay(300, 700); |
| |
| const { data } = await proxyRequest( |
| `/api/auth/send-captcha?email=${encodedEmail}&type=register`, |
| { |
| method: 'GET', |
| headers: { |
| 'Accept': 'application/json, text/plain, */*', |
| 'hcaptcha-token': hcaptchaToken, |
| 'uniqueId': generateUniqueId() |
| } |
| } |
| ); |
| |
| if (data.code !== 200) { |
| throw new Error(`Failed to send verification email: ${data.msg || 'Unknown error'}`); |
| } |
| |
| console.log('Verification email sent successfully'); |
| await randomDelay(2000, 3000); |
| return true; |
| } |
|
|
| async function getVerificationCode(email) { |
| console.log('Waiting for verification code...'); |
| let attempts = 0; |
| const maxAttempts = 25; |
| |
| while (attempts < maxAttempts) { |
| try { |
| await new Promise(resolve => setTimeout(resolve, 4000)); |
| |
| const { data } = await axios.get( |
| `https://api.internal.temp-mail.io/api/v3/email/${email}/messages`, |
| { |
| headers: { |
| 'Content-Type': 'application/json', |
| 'Application-Name': 'web', |
| 'Application-Version': '4.0.0', |
| 'X-CORS-Header': 'iaWg3pchvFx48fY' |
| }, |
| timeout: 15000 |
| } |
| ); |
| |
| if (data.length > 0) { |
| const bodyText = data[0].body_text; |
| const codeMatch = bodyText.match(/Verification Code:\s*(\d{6})/); |
| |
| if (codeMatch) { |
| console.log(`Verification code received: ${codeMatch[1]}`); |
| return codeMatch[1]; |
| } |
| } |
| |
| attempts++; |
| console.log(`Checking code... ${attempts}/${maxAttempts}`); |
| } catch (error) { |
| console.log(`Email check failed:`, error.message); |
| attempts++; |
| } |
| } |
| |
| throw new Error('Verification code not received'); |
| } |
|
|
| async function registerAccount(email, password, verificationCode) { |
| console.log('Registering account...'); |
| const { data } = await proxyRequest('/api/auth/register', { |
| method: 'POST', |
| headers: { |
| 'Accept': 'application/json, text/plain, */*', |
| 'Content-Type': 'application/json', |
| 'uniqueId': generateUniqueId() |
| }, |
| data: { |
| email: email, |
| password: password, |
| confirmPassword: password, |
| verificationCode: verificationCode, |
| referDomain: '' |
| } |
| }); |
| |
| if (data.code !== 200) { |
| throw new Error(`Registration failed: ${data.msg || 'Unknown error'}`); |
| } |
| |
| console.log('Account registered successfully'); |
| |
| return { |
| token: data.data.token, |
| email: email, |
| password: password |
| }; |
| } |
|
|
| async function createVideoTask(prompt, ratio, authToken, email) { |
| console.log('Creating video task...'); |
| await randomDelay(1000, 2000); |
| |
| const { data } = await proxyRequest('/aimodels/api/v1/ai/video/create', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'uniqueid': generateUniqueId(), |
| 'verify': '', |
| 'authorization': authToken |
| }, |
| data: { |
| prompt: prompt, |
| channel: 'SORA2', |
| pageId: 536, |
| source: 'bylo.ai', |
| watermarkFlag: false, |
| privateFlag: false, |
| isTemp: true, |
| model: 'sora_video2', |
| videoType: 'text-to-video', |
| duration: '10', |
| aspectRatio: ratio, |
| email: email |
| } |
| }); |
| |
| if (data.code !== 200) { |
| throw new Error(`Failed to create video task: ${data.message || 'Unknown error'}`); |
| } |
| |
| console.log(`Video task created with ID: ${data.data}`); |
| return data.data; |
| } |
|
|
| async function getTaskStatus(taskId, authToken) { |
| try { |
| const { data } = await proxyRequest( |
| `/aimodels/api/v1/ai/${taskId}?channel=SORA2`, |
| { |
| method: 'GET', |
| headers: { |
| 'Content-Type': 'application/json', |
| 'authorization': authToken |
| } |
| } |
| ); |
| |
| if (!data || !data.data) { |
| throw new Error('Invalid response from task status API'); |
| } |
| |
| return data.data; |
| } catch (error) { |
| console.error('Error getting task status:', error.message); |
| throw error; |
| } |
| } |
|
|
| async function waitForVideoCompletion(taskId, authToken) { |
| console.log('Waiting for video generation...'); |
| let attempts = 0; |
| const maxAttempts = 100; |
| |
| while (attempts < maxAttempts) { |
| await randomDelay(4000, 6000); |
| |
| const taskData = await getTaskStatus(taskId, authToken); |
| |
| console.log(`Status check ${attempts + 1}/${maxAttempts} - State: ${taskData.state}`); |
| |
| if (taskData.state === 1 && taskData.completeData) { |
| const completeData = JSON.parse(taskData.completeData); |
| console.log('Video generation completed!'); |
| return completeData.data.result_urls[0]; |
| } |
| |
| if (taskData.failMsg) { |
| throw new Error(`Video generation failed: ${taskData.failMsg}`); |
| } |
| |
| attempts++; |
| } |
| |
| throw new Error('Video generation timeout'); |
| } |
|
|
| async function sora2(prompt, ratio = 'portrait') { |
| console.log('=== Starting Sora2 Video Generation ==='); |
| console.log(`Prompt: ${prompt}`); |
| console.log(`Ratio: ${ratio}`); |
| console.log(`Proxy: ${PROXY_URL}`); |
| |
| const tempMail = await createTempEmail(); |
| const email = tempMail.email; |
| const password = generatePassword(); |
| |
| await sendVerificationEmail(email); |
| const verificationCode = await getVerificationCode(email); |
| const result = await registerAccount(email, password, verificationCode); |
| |
| console.log('=== Creating Video Task ==='); |
| const taskId = await createVideoTask(prompt, ratio, result.token, result.email); |
| const videoUrl = await waitForVideoCompletion(taskId, result.token); |
| |
| console.log('=== Video Generation Completed ==='); |
| console.log(`Video URL: ${videoUrl}`); |
| |
| return { |
| success: true, |
| email: result.email, |
| password: result.password, |
| videoUrl: videoUrl, |
| taskId: taskId |
| }; |
| } |
|
|
| const handler = async (req, res) => { |
| const startTime = Date.now(); |
| |
| try { |
| const { prompt, key, ratio = 'portrait' } = req.query; |
| |
| if (!prompt) { |
| return res.status(400).json({ |
| author: 'Herza', |
| success: false, |
| msg: 'Missing required parameter: prompt', |
| usage: '/api/AI/sora2?prompt=your_prompt&ratio=portrait&key=your_key' |
| }); |
| } |
| |
| if (!key) { |
| return res.status(400).json({ |
| author: 'Herza', |
| success: false, |
| msg: 'Missing required parameter: key' |
| }); |
| } |
| |
| if (!['portrait', 'landscape', 'square'].includes(ratio)) { |
| return res.status(400).json({ |
| author: 'Herza', |
| success: false, |
| msg: 'Invalid ratio. Use: portrait, landscape, or square' |
| }); |
| } |
| |
| console.log(`\n${'='.repeat(60)}`); |
| console.log('NEW REQUEST RECEIVED'); |
| console.log(`Prompt: ${prompt}`); |
| console.log(`Ratio: ${ratio}`); |
| console.log(`Proxy: ${PROXY_URL}`); |
| console.log(`${'='.repeat(60)}\n`); |
| |
| const result = await sora2(prompt, ratio); |
| |
| const duration = ((Date.now() - startTime) / 1000).toFixed(2); |
| |
| console.log(`\n${'='.repeat(60)}`); |
| console.log('REQUEST COMPLETED'); |
| console.log(`Duration: ${duration}s`); |
| console.log(`${'='.repeat(60)}\n`); |
| |
| res.json({ |
| author: 'Herza', |
| success: true, |
| data: { |
| model: 'sora-video2', |
| prompt: prompt, |
| ratio: ratio, |
| videoUrl: result.videoUrl, |
| taskId: result.taskId, |
| account: { |
| email: result.email, |
| password: result.password |
| }, |
| processingTime: `${duration}s` |
| } |
| }); |
| } catch (error) { |
| console.error('\n❌ ERROR:', error.message); |
| console.error('Stack:', error.stack); |
| |
| const duration = ((Date.now() - startTime) / 1000).toFixed(2); |
| |
| res.status(500).json({ |
| author: 'Herza', |
| success: false, |
| msg: error.message || 'Terjadi kesalahan saat generate video.', |
| processingTime: `${duration}s`, |
| error: { |
| code: error.code || 'UNKNOWN', |
| details: error.response?.data || null |
| } |
| }); |
| } |
| } |
|
|
| module.exports = { |
| name: 'Sora2 Video Generator', |
| description: 'Generate videos using Sora2 AI model from Bylo.ai via DanBot Proxy', |
| type: 'GET', |
| routes: ['api/AI/sora2'], |
| tags: ['AI', 'Sora', 'OpenAI', 'Video'], |
| parameters: ['prompt', 'ratio', 'key'], |
| enabled: true, |
| main: ['AI'], |
| limit: 15, |
| handler |
| }; |