| const axios = require('axios'); | |
| const dns = require('dns').promises; | |
| const PROXY_URL = 'https://proxy-sigma-roan.vercel.app/api/proxy'; | |
| 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(url, options = {}) { | |
| const targetPath = url.startsWith('http') ? url : url; | |
| const fakeIP = generateRandomIP(); | |
| const headers = { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', | |
| 'Accept': 'application/json, text/plain, */*', | |
| 'X-Forwarded-For': fakeIP, | |
| 'X-Real-IP': fakeIP, | |
| 'X-Client-IP': fakeIP, | |
| ...(options.headers || {}) | |
| }; | |
| await randomDelay(500, 1500); | |
| const axiosConfig = { | |
| method: options.method || 'GET', | |
| headers: headers, | |
| timeout: 30000, | |
| params: { | |
| url: targetPath | |
| }, | |
| 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 { | |
| axiosConfig.url = PROXY_URL; | |
| console.log(`Attempt ${attempt}: ${PROXY_URL}?url=${targetPath}`); | |
| const response = await axios(axiosConfig); | |
| console.log(`Attempt ${attempt} got status ${response.status}`); | |
| console.log(`Response data:`, JSON.stringify(response.data).substring(0, 200)); | |
| if (response.status === 403) { | |
| console.log('Got 403, waiting longer before retry...'); | |
| await randomDelay(3000, 5000); | |
| throw new Error('API Bylo returned 403 Forbidden - possible rate limit or IP block'); | |
| } | |
| if (response.status === 429) { | |
| console.log('Got 429 Too Many Requests, waiting...'); | |
| await randomDelay(5000, 10000); | |
| 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 from proxy'); | |
| } | |
| return response; | |
| } | |
| if (response.status >= 400) { | |
| const errorMsg = response.data?.msg || response.data?.message || response.data?.error || 'Unknown error'; | |
| throw new Error(`API error (${response.status}): ${errorMsg}`); | |
| } | |
| if (attempt < 3) { | |
| await randomDelay(2000, 4000); | |
| } | |
| } catch (error) { | |
| lastError = error; | |
| console.error(`Attempt ${attempt} failed:`, error.message); | |
| if (error.response) { | |
| console.error(`Response status: ${error.response.status}`); | |
| console.error(`Response data:`, error.response.data); | |
| } | |
| if (attempt < 3) { | |
| const waitTime = 3000 * attempt; | |
| console.log(`Retrying in ${waitTime/1000} seconds...`); | |
| await randomDelay(waitTime, waitTime + 2000); | |
| } | |
| } | |
| } | |
| throw new Error(`Proxy request failed after 3 attempts: ${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: 15000 | |
| }); | |
| console.log(`Email created: ${data.email}`); | |
| return data; | |
| } | |
| async function getHcaptchaToken() { | |
| console.log('Getting hCaptcha token...'); | |
| const { data } = await axios.get( | |
| 'https://anabot.my.id/api/tools/bypass?url=https%3A%2F%2Fapi.hcaptcha.com&siteKey=6f70c0f2-3ef6-4972-9fb6-c0b4bade3af8&type=hcaptcha-invisible&apikey=freeApikey', | |
| { | |
| timeout: 15000 | |
| } | |
| ); | |
| if (!data.success) { | |
| throw new Error('Failed to get hCaptcha token'); | |
| } | |
| console.log('hCaptcha token obtained'); | |
| return data.data.result.token; | |
| } | |
| async function sendVerificationEmail(email) { | |
| console.log(`Sending verification email to ${email}...`); | |
| await randomDelay(1000, 2000); | |
| const hcaptchaToken = await getHcaptchaToken(); | |
| const encodedEmail = encodeURIComponent(email); | |
| await randomDelay(500, 1000); | |
| 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(3000, 5000); | |
| return true; | |
| } | |
| async function getVerificationCode(email) { | |
| console.log('Waiting for verification code...'); | |
| let attempts = 0; | |
| const maxAttempts = 30; | |
| while (attempts < maxAttempts) { | |
| try { | |
| await new Promise(resolve => setTimeout(resolve, 5000)); | |
| 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: 10000 | |
| } | |
| ); | |
| 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 for verification code... attempt ${attempts}/${maxAttempts}`); | |
| } catch (error) { | |
| console.log(`Email check attempt ${attempts} failed:`, error.message); | |
| attempts++; | |
| } | |
| } | |
| throw new Error('Verification code not received after 30 attempts'); | |
| } | |
| 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 data.data.token; | |
| } | |
| async function createVideo(prompt, ratio, authToken, email) { | |
| console.log('Creating video task...'); | |
| await randomDelay(2000, 3000); | |
| 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: ${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 = 120; | |
| while (attempts < maxAttempts) { | |
| await randomDelay(5000, 7000); | |
| const taskData = await getTaskStatus(taskId, authToken); | |
| console.log(`Video 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 after 10 minutes'); | |
| } | |
| async function sora2(prompt, ratio = 'portrait') { | |
| console.log('=== Starting Sora2 Video Generation ==='); | |
| console.log(`Prompt: ${prompt}`); | |
| console.log(`Ratio: ${ratio}`); | |
| const tempMail = await createTempEmail(); | |
| const email = tempMail.email; | |
| const password = generatePassword(); | |
| await sendVerificationEmail(email); | |
| const verificationCode = await getVerificationCode(email); | |
| const authToken = await registerAccount(email, password, verificationCode); | |
| const taskId = await createVideo(prompt, ratio, authToken, email); | |
| const videoUrl = await waitForVideoCompletion(taskId, authToken); | |
| console.log('=== Video Generation Completed ==='); | |
| console.log(`Video URL: ${videoUrl}`); | |
| return { | |
| success: true, | |
| email: email, | |
| password: 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(`${'='.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 Vercel Proxy', | |
| type: 'GET', | |
| routes: ['api/AI/sora2'], | |
| tags: ['AI', 'Sora', 'OpenAI', 'Video'], | |
| parameters: ['prompt', 'ratio', 'key'], | |
| enabled: true, | |
| main: ['AI'], | |
| limit: 10, | |
| handler | |
| }; |