const axios = require('axios'); const crypto = require('crypto'); class LightXBot { constructor() { this.tempMailHeaders = { 'Content-Type': 'application/json', 'Application-Name': 'web', 'Application-Version': '4.0.0', 'X-CORS-Header': 'iaWg3pchvFx48fY' }; this.lightxHeaders = { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }; this.authPayload = { clientHash: '78e7841d9f1891ced5b260c455ea99f3', accessToken: '', version: '0.1', deviceId: '', model: '', os: 24, platform: 'web', appname: 'lightx', locale: 'en-GB', appVersion: 3, apiHash: 'fb194c698ecca6bc73d649c3fabee629cfe0e2ccc9805ef5a91b0374e52fe4969cd62e2b9abe8bb3d55738914fedcd50ffbe225740ae84c9e2b1aa5081c511fc' }; this.zombieStyles = { 1: { name: "Classic Zombie", prompt: "A man dressed as a zombie male costume features torn, bloodstained clothes, creating a creepy, haunted house with a creepy butler for a spooky and pumpkin, halloween night background", productId: 10103796, productImageId: 123663 }, 2: { name: "Walking Dead Zombie", prompt: "Transform into a decaying walking dead zombie with rotting flesh, pale grey skin, sunken eyes, and tattered bloody clothing in a post-apocalyptic setting", productId: 10103796, productImageId: 123663 }, 3: { name: "Horror Zombie", prompt: "Become a terrifying horror movie zombie with gruesome makeup, exposed bones, blood dripping, vacant stare, and decomposed skin in a dark spooky graveyard", productId: 10103796, productImageId: 123663 }, 4: { name: "Undead Creature", prompt: "Transform into an undead zombie creature with greenish rotting skin, missing chunks of flesh, empty soulless eyes, torn clothes covered in dirt and blood", productId: 10103796, productImageId: 123663 }, 5: { name: "Nightmare Zombie", prompt: "Become a nightmarish zombie with horrifying scars, decaying face, bloodshot eyes, ripped and stained clothing in a foggy haunted cemetery at midnight", productId: 10103796, productImageId: 123663 } }; this.email = ''; this.token = ''; this.password = ''; this.bearerToken = ''; this.systemRefKey = ''; } hashPassword(password) { return crypto.createHash('sha512').update(password).digest('hex'); } generateRandomString(length) { const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; let result = ''; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } return result; } async createTempEmail() { const response = await axios.post( 'https://api.internal.temp-mail.io/api/v3/email/new', { min_name_length: 10, max_name_length: 10 }, { headers: this.tempMailHeaders } ); this.email = response.data.email; this.token = response.data.token; return { email: this.email, token: this.token }; } async registerAccount(name, password) { this.password = password; const hashedPassword = this.hashPassword(password); const response = await axios.post( 'https://www.instagraphe.mobi/andor-login-1.0/mobile/emailSignup', { name: name, email: this.email, password: hashedPassword }, { headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) } } ); return response.data; } async waitForVerificationEmail(maxRetries = 20, interval = 5000) { for (let i = 0; i < maxRetries; i++) { const response = await axios.get( `https://api.internal.temp-mail.io/api/v3/email/${this.email}/messages`, { headers: this.tempMailHeaders } ); if (response.data && response.data.length > 0) { const verificationEmail = response.data.find(msg => msg.subject === 'Welcome to LightX' && msg.body_text.includes('validate-email') ); if (verificationEmail) { const linkMatch = verificationEmail.body_text.match(/https:\/\/www\.lightxeditor\.com\/validate-email\?[^\s)]+/); if (linkMatch) { return linkMatch[0]; } } } await new Promise(resolve => setTimeout(resolve, interval)); } throw new Error('Email verifikasi tidak diterima'); } async verifyEmail(verificationLink) { try { await axios.get(verificationLink, { maxRedirects: 5, timeout: 10000 }); return 'Success'; } catch (error) { return 'Success'; } } async login() { const hashedPassword = this.hashPassword(this.password); const response = await axios.post( 'https://www.instagraphe.mobi/andor-login-1.0/mobile/login', { password: hashedPassword, type: 'EMAIL', value: this.email }, { headers: { ...this.lightxHeaders, auth: JSON.stringify(this.authPayload) } } ); this.bearerToken = response.data.body.token.accessToken; this.systemRefKey = response.data.body.user.systemRefKey; return response.data; } async checkCredits() { const authWithToken = { ...this.authPayload, accessToken: this.bearerToken, systemRefKey: this.systemRefKey }; const response = await axios.get( 'https://www.instagraphe.mobi/andor-login-1.0/user/getAPIUsageDetails?apiId=1', { headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) } } ); return response.data.body; } async uploadImage(imageBuffer, fileName, size) { const authWithToken = { ...this.authPayload, accessToken: this.bearerToken, systemRefKey: this.systemRefKey }; const presignResponse = await axios.post( 'https://www.instagraphe.mobi/andor-media-1.0/content/generatePresignedUrls', { featureType: 'selfie', contents: [{ size: size, contentType: 'image/jpeg', assetType: 'IMG', assetRefId: '1', name: fileName }] }, { headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) } } ); const uploadData = presignResponse.data.body.contents[0]; const presignedUrl = uploadData.presignedUrl; const imageUrl = uploadData.contentUrl; await axios.put(presignedUrl, imageBuffer, { headers: { 'Content-Type': 'image/jpeg', 'Content-Length': size } }); return imageUrl; } async convertToZombie(imageUrl, styleId) { const style = this.zombieStyles[styleId]; if (!style) { throw new Error(`Invalid style ID: ${styleId}. Valid IDs are 1-5`); } const authWithToken = { ...this.authPayload, accessToken: this.bearerToken, systemRefKey: this.systemRefKey }; try { const response = await axios.post( 'https://www.instagraphe.mobi/andor-media-1.0/aiartweb/generateImage', { featureType: 'selfie', isCustomPrompt: 0, quality: 1, imageUrl: imageUrl, productId: style.productId, model: 58, textPrompt: style.prompt, productImageId: style.productImageId }, { headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) } } ); if (!response.data || !response.data.body || !response.data.body.assetId) { throw new Error(`Invalid response: ${JSON.stringify(response.data)}`); } const assetId = response.data.body.assetId; return await this.checkGenerationStatus(assetId); } catch (error) { if (error.response) { throw new Error(`API Error: ${JSON.stringify(error.response.data)}`); } throw error; } } async checkGenerationStatus(assetId, maxRetries = 30, interval = 3000) { const authWithToken = { ...this.authPayload, accessToken: this.bearerToken, systemRefKey: this.systemRefKey }; for (let i = 0; i < maxRetries; i++) { const response = await axios.post( 'https://www.instagraphe.mobi/andor-media-1.0/aiart/checkStatus', { assetId: assetId }, { headers: { ...this.lightxHeaders, auth: JSON.stringify(authWithToken) } } ); const status = response.data.body.status; if (status === 'active') { return response.data.body; } await new Promise(resolve => setTimeout(resolve, interval)); } throw new Error('Generation timeout'); } } async function img2zombie(imageUrl, styleId = 1, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { const bot = new LightXBot(); try { await bot.createTempEmail(); const randomName = 'User' + bot.generateRandomString(6); const randomPassword = 'Pass' + bot.generateRandomString(10) + '!'; await bot.registerAccount(randomName, randomPassword); const verificationLink = await bot.waitForVerificationEmail(); await bot.verifyEmail(verificationLink); await new Promise(resolve => setTimeout(resolve, 3000)); await bot.login(); const credits = await bot.checkCredits(); if (credits.remainingCalls < 1) { throw new Error('No credits available, trying new account...'); } const imageResponse = await axios.get(imageUrl, { responseType: 'arraybuffer' }); const imageBuffer = Buffer.from(imageResponse.data); const uploadedUrl = await bot.uploadImage(imageBuffer, 'image.jpg', imageBuffer.length); const result = await bot.convertToZombie(uploadedUrl, styleId); return { success: true, styleName: bot.zombieStyles[styleId].name, email: bot.email, resultUrl: result.imgUrl, thumbnailUrl: result.thumbUrl, width: result.width, height: result.height, creditsRemaining: credits.remainingCalls - 1 }; } catch (error) { if (attempt === maxRetries) { return { success: false, error: error.message, attemptsUsed: attempt }; } await new Promise(resolve => setTimeout(resolve, 2000)); } } } const handler = async (req, res) => { try { const { image, style, key } = req.query; if (!image || !key) { return res.status(400).json({ success: false, error: 'Missing required parameters: image and key' }); } const styleId = style ? parseInt(style) : 1; if (styleId < 1 || styleId > 5) { return res.status(400).json({ success: false, error: 'Invalid style parameter. Must be between 1-5', styles: { 1: 'Classic Zombie', 2: 'Walking Dead Zombie', 3: 'Horror Zombie', 4: 'Undead Creature', 5: 'Nightmare Zombie' } }); } const result = await img2zombie(image, styleId); if (!result.success) { return res.status(500).json({ success: false, error: result.error, attemptsUsed: result.attemptsUsed }); } res.json({ author: "Herza", success: true, data: { styleName: result.styleName, url: result.resultUrl, thumbnail: result.thumbnailUrl, width: result.width, height: result.height, creditsUsed: 1, email: result.email } }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } }; module.exports = { name: 'Image to Zombie Converter', description: 'Convert photos to zombie style using AI with 5 different zombie themes', type: 'GET', routes: ['api/AI/img2zombie'], tags: ['ai', 'image', 'zombie', 'converter', 'horror'], main: ['AI'], parameters: ['image', 'style', 'key'], enabled: true, limit: 5, handler };