DashX / plugins /img2zombie.js
HerzaJ's picture
Create img2zombie.js
28cb6f0 verified
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
};