/**
© ZENITH
ᘎ https://whatsapp.com/channel/0029Vai9MMj5vKABWrYzIJ2Z
*/
import axios from "axios"
import CryptoJS from "crypto-js"
import fs from "fs"
let handler = async(m, { conn, text, usedPrefix: prefix, command: cmd }) => {
let q = m.quoted ? m.quoted : m
let mime = (q.msg || q).mimetype || q.mediaType || ''
if (!/image/.test(mime)) return await conn.reply(m.chat, `*\`Kirim atau balas pesan gambar dengan caption:\`*\n> _*${prefix+cmd} [1/2/3/4] (untuk menentukan style nya)*_`, m)
let style
try {
if (Number(text)) style = Number(text)
else style = 2
await m.reply(wait)
const aieaseInstance = new Aiease({ debug: true })
const image = await q.download()
await aieaseInstance.generateImage('filter', image, { style: style })
if (!res) await conn.reply(m.chat, "Gagal membuat anime pada foto anda!", m).then(async() => {
return await conn.sendMessage(m.chat, { react: { delete: m.key, key: m.key }})
})
const { nsfw, origin, thumb } = res[0]
await conn.sendMessage(m.chat, {
image: { url: origin },
mimetype: "image/jpeg",
caption: "Berhasil",
}, { quoted: m })
} catch(err) {
return await conn.reply(m.chat, `Maaf terjadi kesalahan...\n> _Log Error:_ \`\`\`${err?.message}\`\`\``, m)
}
}
handler.help = ["jadianime"]
handler.tags = ["tools"]
handler.command = ["jadianime", "toanime"]
export default handler
class Aiease {
constructor({ debug = false } = {}) {
this.DEBUG = debug
this.AUTH_TOKEN = null
this.api = {
uploader: 'https://www.aiease.ai/api/api/id_photo/s',
genImg2Img: 'https://www.aiease.ai/api/api/gen/img2img',
gentext2img: 'https://www.aiease.ai/api/api/gen/text2img',
taskInfo: 'https://www.aiease.ai/api/api/id_photo/task-info',
styleList: ' https://www.aiease.ai/api/api/common/',
token: 'https://www.aiease.ai/api/api/user/visit',
}
this.headers = {
json: {
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0',
'Authorization': null,
'Accept': 'application/json'
},
image: {
'Content-Type': 'image/jpeg',
'Host': 'pub-static.aiease.ai',
'Origin': 'https://www.aiease.ai',
'Referer': 'https://www.aiease.ai/',
'User-Agent': 'Mozilla/5.0',
'Accept': '*/*'
}
}
this.default_payload = {
enhance: {
gen_type: "enhance",
enhance_extra_data: {
img_url: null,
mode: null, // general || anime || old_photo
size: "4",
restore: 1
}
},
filter: {
gen_type: 'ai_filter',
ai_filter_extra_data: {
img_url: null,
style_id: null
}
},
watermark: {
gen_type: "text_remove",
text_remove_extra_data: {
img_url: null,
mask_url: ""
}
},
rembg: {
gen_type: "rembg",
rembg_extra_data: {
img_url: null
}
},
retouch: {
gen_type: "ai_skin_repair",
ai_skin_repair_extra_data: {
img_url: null
}
}
}
this.constants = {
maxRetry: 40,
retryDelay: 3000,
}
const { useEncrypt, useDecrypt } = this._setupEncryption()
this.useEncrypt = useEncrypt
this.useDecrypt = useDecrypt
}
_setupEncryption() {
const encryptionKeyPhrase = ["Q", "@", "D", "2", "4", "=", "o", "u", "e", "V", "%", "]", "O", "B", "S", "8", "i", ",", "%", "e", "K", "=", "5", "I", "|", "7", "W", "U", "$", "P", "e", "E"]
.map((char) => {
const charCode = char.charCodeAt(0)
return String.fromCharCode(charCode)
}).join("")
const hashHex = CryptoJS.SHA256(encryptionKeyPhrase).toString(CryptoJS.enc.Hex)
const encryptionKey = CryptoJS.enc.Hex.parse(hashHex)
return {
useEncrypt: function (plainText) {
const encodedText = encodeURIComponent(plainText)
const iv = CryptoJS.lib.WordArray.random(16)
const encrypted = CryptoJS.AES.encrypt(encodedText, encryptionKey, {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding
})
const combined = iv.concat(encrypted.ciphertext)
const encryptedStr = CryptoJS.enc.Base64.stringify(combined)
return encryptedStr
},
useDecrypt: function (base64EncryptedText) {
const encryptedBytes = CryptoJS.enc.Base64.parse(base64EncryptedText)
const iv = CryptoJS.lib.WordArray.create(encryptedBytes.words.slice(0, 4), 16)
const ciphertext = CryptoJS.lib.WordArray.create(encryptedBytes.words.slice(4), encryptedBytes.sigBytes - 16)
const decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, encryptionKey, {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding
})
const decryptedText = decodeURIComponent(decrypted.toString(CryptoJS.enc.Utf8))
return decryptedText
}
}
}
async uploadImage(input) {
if (!this.AUTH_TOKEN) await this.getToken()
try {
const fileBuffer = Buffer.isBuffer(input) ? input : /^data:.*?\/.*?;base64,/i.test(input) ? Buffer.from(input.split`,`[1], 'base64') : /^https?:\/\//.test(input) ? Buffer.from(new Uint8Array((await (await fetch(input)).arrayBuffer()))) : fs.existsSync(input) ? fs.readFileSync(input) : typeof input === 'string' ? input : Buffer.alloc(0)
const metadata = {
length: fileBuffer.length,
filetype: 'image/jpeg',
filename: "IMG-" + Date.now() + "-WA" + ["0012", "0034", "00371", "0018", "1120", "0045", "0038"].getRandom() + ".jpg"
}
const metadataJsonString = JSON.stringify(metadata)
const encryptedMetadata = this.useEncrypt(metadataJsonString)
const tValue = encryptedMetadata
const apiUrl = `${this.api.uploader}?time=${Date.now()}`
const payload = { t: tValue }
const response = await axios.post(apiUrl, payload, { headers: this.headers.json })
const uploadUrl = this.useDecrypt(response.data.result)
const imageSizeInBytes = fileBuffer.length
await axios.put(uploadUrl, fileBuffer, { headers: { 'Content-Length': imageSizeInBytes, ...this.headers.image } })
console.log('Upload success!', `Image uploaded to ${uploadUrl.split('?')[0]}`)
return uploadUrl.split('?')[0]
} catch (error) {
console.error('Image Upload Error:', error.message)
throw error
}
}
async generateImage(type, input, { style = 4, mode = 'general' } = {}) {
if (!this.AUTH_TOKEN) await this.getToken()
try {
const payload = this.default_payload[type]
if (!payload) {
throw new Error(`Invalid type: ${type}\nSupported types: ${Object.keys(this.default_payload).join(', ')}`)
}
const imgUrl = await this.uploadImage(input)
const dataKey = Object.keys(payload).find(key => key.endsWith("_extra_data"))
if (dataKey) {
payload[dataKey].img_url = imgUrl
}
if (type === 'filter') {
payload[dataKey].style_id = style
} else if (type === 'enhance') {
payload[dataKey].mode = mode
}
const response = await axios.post(this.api.genImg2Img, payload, {
headers: this.headers.json
})
if (response.data && response.data.result && response.data.result.task_id) {
const taskId = response.data.result.task_id
console.log(`Task ID received: ${taskId}`)
return await this.checkTaskStatus(taskId)
} else {
throw new Error(response.data.message || 'Task ID not found in response')
}
} catch (error) {
console.error('Image Generation Error:', error.message)
throw error
}
}
async text2img(prompt, { style = 1, size = '1-1' } = {}) {
if (!this.AUTH_TOKEN) await this.getToken()
try {
if (!prompt) throw new Error('Please provide a prompt.')
const payload = {
gen_type: "art_v1",
art_v1_extra_data: {
prompt: prompt,
style_id: style,
size: size
}
}
const response = await axios.post(this.api.gentext2img, payload, {
headers: this.headers.json
})
if (response.data && response.data.result && response.data.result.task_id) {
const taskId = response.data.result.task_id
console.log(`Task ID received: ${taskId}`)
return await this.checkTaskStatus(taskId)
} else {
throw new Error(response.data.message || 'Task ID not found in response')
}
} catch (error) {
console.error('Image Generation Error:', error.message)
throw error
}
}
async checkTaskStatus(taskId, maxRetry = this.constants.maxRetry) {
let status = ''
let attempts = 0
while (status !== 'success' && attempts < maxRetry) {
try {
const response = await axios.get(`${this.api.taskInfo}?task_id=${taskId}`, {
headers: this.headers.json
})
if (response.data.code === 450) {
throw new Error(response.data.message)
}
if (response.data && response.data.result && response.data.result.data) {
status = response.data.result.data.queue_info.status
console.log(`Task ${taskId} status: ${status}`)
if (status === 'success') {
console.log(`Task ${taskId} succeeded!`)
return response.data.result.data.results
}
}
} catch (error) {
console.error('Task Status Check Error:', error.message)
if (error.message.includes('Image generation failed')) {
throw new Error(error.message)
}
}
attempts++;
if (attempts >= maxRetry) {
console.error('Task Status Check Error:', `Max retry limit reached (${maxRetry}) for task ${taskId}`)
throw new Error(`Max retry limit reached (${maxRetry}) for task ${taskId}`)
}
await new Promise(resolve => setTimeout(resolve, this.constants.retryDelay))
}
}
async getStyle(type) {
if (!this.AUTH_TOKEN) await this.getToken()
try {
const end = {
art: 'ai_art_style',
filter: 'ai_filter_style'
}[type]
if (!end) {
throw new Error(`Invalid type: ${type}\nSupported types: ${Object.keys(end).join(', ')}`)
}
const response = await axios.get(this.api.styleList + end, {
headers: this.headers.json
})
if (response.data.code === 200) {
console.log('Style list fetched successfully.')
return response.data.result
} else {
console.error('Failed to fetch style list:', response.data.message || 'Unknown error')
throw new Error(response.data.message || 'Failed to fetch style list')
}
} catch (error) {
console.error('Error fetching style list:', error.message)
throw error
}
}
async getToken() {
try {
const response = await axios.post(this.api.token, {}, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'Mozilla/5.0'
}
})
if (response.data.code === 200) {
console.log('Token fetched successfully.')
const jwt = `JWT ${response.data.result.user.token}`
this.AUTH_TOKEN = jwt
this.headers.json.Authorization = this.AUTH_TOKEN
return
} else {
console.error('Failed to fetch token:', response.data.message || 'Unknown error')
throw new Error(response.data.message || 'Failed to fetch token')
}
} catch (error) {
console.error('Error fetching token:', error.message)
throw error
}
}
}