import axios from "axios"; import { fileTypeFromBuffer } from "file-type"; import { readFileSync } from "fs"; import CryptoJS from "crypto-js"; const ModelMap = { nano_banana: 2, seed_dream: 5, flux: 8, qwen_image: 9 }; const IMAGE_TO_ANIME_PRESETS = { manga: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into a KOREAN-STYLE MANGA illustration. Apply strong stylization with clear and noticeable differences from the original image." }, anime: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into an ANIME-STYLE illustration. Apply strong stylization with clear and noticeable differences from the original image." }, ghibli: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into a STUDIO GHIBLI-STYLE illustration. Apply strong stylization with clear and noticeable differences from the original image." }, cyberpunk: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into a CYBERPUNK-STYLE illustration with neon colors, futuristic elements, and dark atmosphere." }, watercolor: { size: "2K", aspect_ratio: "match_input_image", output_format: "png", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into a WATERCOLOR painting style with soft brush strokes and pastel colors." }, pixelart: { size: "2K", aspect_ratio: "match_input_image", output_format: "png", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into PIXEL ART style with 8-bit retro gaming aesthetic." }, sketch: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into a detailed PENCIL SKETCH with realistic shading and artistic strokes." }, oilpainting: { size: "2K", aspect_ratio: "match_input_image", output_format: "jpg", sequential_image_generation: "disabled", max_images: 1, prompt: "Convert the provided image into an OIL PAINTING style with thick brush strokes and rich colors." } }; const IMAGE_TO_ANIME_ENCRYPTED_PAYLOADS = { manga: "L7p91uXhVyp5OOJthAyqjSqhlbM+RPZ8+h2Uq9tz6Y+4Agarugz8f4JjxjEycxEzuj/7+6Q0YY9jUvrfmqkucENhHAkMq1EOilzosQlw2msQpW2yRqV3C/WqvP/jrmSu3aUVAyeFhSbK3ARzowBzQYPVHtxwBbTWwlSR4tehnodUasnmftnY77c8gIFtL2ArNdzmPLx5H8O9un2U8WE4s0+xiFV3y4sbetHMN7rHh7DRIpuIQD4rKISR/vE+HeaHpRavXfsilr5P7Y6bsIo+RRFIPgX2ofbYYiATziqsjDeie4IlcOAVf1Pudqz8uk6YKM78CGxjF9iPLYQnkW+c6j96PNsg1Yk4Xz8/ZcdmHF4GGZe8ILYH/D0yyM1dsCkK1zY8ciL+6pAk4dHIZ/4k9A==", ghibli: "L7p91uXhVyp5OOJthAyqjSqhlbM+RPZ8+h2Uq9tz6Y+4Agarugz8f4JjxjEycxEzuj/7+6Q0YY9jUvrfmqkucENhHAkMq1EOilzosQlw2msQpW2yRqV3C/WqvP/jrmSu3aUVAyeFhSbK3ARzowBzQYPVHtxwBbTWwlSR4tehnodUasnmftnY77c8gIFtL2ArNdzmPLx5H8O9un2U8WE4syzL5EYHGJWC1rlQM9xhNe1PViOsBSxmwHVwOdqtxZtcAJmGuzTgG7JVU7Hr9ZRwajhYK5yxQwSdJGwwR4jjS1yF9s9wKUQqgI+fYxaw7FZziLS+9JG5pTEjch4D0fpl+LO7vIynHN4cyu4DDeAUwNeYfbGMn2QQs+5OgMdViCAM1GkJk2jhlQm10rESTjDryw==", anime: "L7p91uXhVyp5OOJthAyqjSqhlbM+RPZ8+h2Uq9tz6Y+4Agarugz8f4JjxjEycxEzuj/7+6Q0YY9jUvrfmqkucENhHAkMq1EOilzosQlw2msQpW2yRqV3C/WqvP/jrmSu3aUVAyeFhSbK3ARzowBzQYPVHtxwBbTWwlSR4tehnodUasnmftnY77c8gIFtL2ArNdzmPLx5H8O9un2U8WE4s7O2FxvQPCjt2uGmHPMOx1DsNSnLvzCKPVdz8Ob1cPHePmmquQZlsb/p+8gGv+cizSiOL4ts6GD2RxWN+K5MmpA/F3rQXanFUm4EL0g7qZCQbChRRQyaAyZuxtIdTKsmsMzkVKM5Sx96eV7bEjUAJ52j6NcP96INv2DhnWTP7gB6tltFQe8B8SPS2LuLRuPghA==" }; export class AIEnhancer { constructor() { this.CREATED_BY = "Ditzzy"; this.NOTE = "Thank you for using this scrape, I hope you appreciate me for making this scrape by not deleting wm"; this.AES_KEY = "ai-enhancer-web__aes-key"; this.AES_IV = "aienhancer-aesiv"; this.HEADERS = { "accept": "*/*", "content-type": "application/json", "Referer": "https://aienhancer.ai", "Referrer-Policy": "strict-origin-when-cross-origin" }; this.POLLING_INTERVAL = 2000; this.MAX_POLLING_ATTEMPTS = 120; } encrypt(data) { const plaintext = typeof data === "string" ? data : JSON.stringify(data); return CryptoJS.AES.encrypt( plaintext, CryptoJS.enc.Utf8.parse(this.AES_KEY), { iv: CryptoJS.enc.Utf8.parse(this.AES_IV), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ).toString(); } decrypt(encryptedData) { const decrypted = CryptoJS.AES.decrypt( encryptedData, CryptoJS.enc.Utf8.parse(this.AES_KEY), { iv: CryptoJS.enc.Utf8.parse(this.AES_IV), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); return decrypted.toString(CryptoJS.enc.Utf8); } decryptToJSON(encryptedData) { const decrypted = this.decrypt(encryptedData); return JSON.parse(decrypted); } wrapResponse(data) { return { created_by: this.CREATED_BY, note: this.NOTE, results: data }; } async sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async processImage(image) { let img; let type; if (typeof image === "string") { img = readFileSync(image); type = await fileTypeFromBuffer(img); } else if (Buffer.isBuffer(image)) { img = image; type = await fileTypeFromBuffer(image); } else { throw new Error("Invalid image input: must be file path (string) or Buffer"); } if (!type) { throw new Error("Could not detect file type"); } const allowedImageTypes = [ 'image/jpeg', 'image/jpg', 'image/png', 'image/webp', 'image/gif', 'image/bmp' ]; if (!allowedImageTypes.includes(type.mime)) { throw new Error( `Unsupported format: ${type.mime}. Allowed: jpeg, jpg, png, webp, gif, bmp` ); } const imgbase64 = img.toString("base64"); return { base64: `data:${type.mime};base64,${imgbase64}`, mime: type.mime }; } async createTask(apiUrl, model, image, config) { const { base64 } = await this.processImage(image); const settings = typeof config === "string" ? config : this.encrypt(config); const requestConfig = { url: apiUrl, method: "POST", headers: this.HEADERS, data: { model, image: base64, settings } }; const { data } = await axios.request(requestConfig); if (data.code !== 100000 || !data.data.id) { throw new Error(`Task creation failed: ${data.message}`); } return data.data.id; } async checkTaskStatus(resultUrl, taskId) { const config = { url: resultUrl, method: "POST", headers: this.HEADERS, data: { task_id: taskId } }; const { data } = await axios.request(config); return data; } async pollTaskResult(resultUrl, taskId) { let attempts = 0; while (attempts < this.MAX_POLLING_ATTEMPTS) { const response = await this.checkTaskStatus(resultUrl, taskId); if (response.code !== 100000) { throw new Error(`Status check failed: ${response.message}`); } const { status, error, output, input, completed_at } = response.data; if ((status === "succeeded" || status === "success") && output && input) { return { id: taskId, output, input, error, status, created_at: response.data.created_at, started_at: response.data.started_at, completed_at: completed_at }; } if (status === "failed" || status === "fail" || error) { throw new Error(`Task failed: ${error || "Unknown error"}`); } console.log(`[${taskId} | ${status}] Polling attempt ${attempts + 1}/${this.MAX_POLLING_ATTEMPTS}`); await this.sleep(this.POLLING_INTERVAL); attempts++; } throw new Error(`Task timeout after ${this.MAX_POLLING_ATTEMPTS} attempts`); } async imageToAnime(image, preset = "anime") { try { const apiUrl = "https://aienhancer.ai/api/v1/r/image-enhance/create"; const resultUrl = "https://aienhancer.ai/api/v1/r/image-enhance/result"; const model = 5; let config; if (typeof preset === "string") { if (IMAGE_TO_ANIME_PRESETS[preset]) { config = IMAGE_TO_ANIME_PRESETS[preset]; } else if (IMAGE_TO_ANIME_ENCRYPTED_PAYLOADS[preset]) { config = IMAGE_TO_ANIME_ENCRYPTED_PAYLOADS[preset]; } else { config = preset; } } else { config = preset; } const taskId = await this.createTask(apiUrl, model, image, config); console.log(`✓ Task created: ${taskId}`); const result = await this.pollTaskResult(resultUrl, taskId); return this.wrapResponse(result); } catch (error) { throw new Error(`Image to anime conversion failed: ${error}`); } } async ImageAIEditor(image, model, preset) { try { const apiUrl = "https://aienhancer.ai/api/v1/k/image-enhance/create"; const resultUrl = "https://aienhancer.ai/api/v1/k/image-enhance/result"; const modelId = ModelMap[model]; const taskId = await this.createTask(apiUrl, modelId, image, preset); const result = await this.pollTaskResult(resultUrl, taskId); return this.wrapResponse(result); } catch (e) { throw new Error("Image editor failed: " + e); } } async AIImageRestoration(image, model, config) { try { const apiUrl = "https://aienhancer.ai/api/v1/r/image-enhance/create"; const resultUrl = "https://aienhancer.ai/api/v1/r/image-enhance/result"; const taskId = await this.createTask(apiUrl, model, image, config); const result = await this.pollTaskResult(resultUrl, taskId); return this.wrapResponse(result); } catch (e) { throw new Error(`An error occurred while upscaling the image: ${e}`); } } async RemoveBackground(image, config = {}) { try { const apiUrl = "https://aienhancer.ai/api/v1/r/image-enhance/create"; const resultUrl = "https://aienhancer.ai/api/v1/r/image-enhance/result"; const model = 4; const payloadConfig = config ? config : { threshold: 0, reverse: false, background_type: "rgba", format: "png", }; const taskId = await this.createTask(apiUrl, model, image, payloadConfig); const result = await this.pollTaskResult(resultUrl, taskId); return this.wrapResponse(result); } catch (e) { throw new Error(`Remove background error: ${e}`); } } decryptPayload(encryptedPayload) { return this.decryptToJSON(encryptedPayload); } encryptConfig(config) { return this.encrypt(config); } }