//By: 𖧄 𝐋𝐔𝐂𝐀𝐒 𝐌𝐎𝐃 𝐃𝐎𝐌𝐈𝐍𝐀 𖧄 //Canal: https://whatsapp.com/channel/0029Vb69bDnAe5VmzSMwBH11 const { fromBuffer } = require('file-type') const FormData = require("form-data") const crypto = require("node:crypto") const axios = require("axios") class GridPlus { constructor() { this.ins = axios.create({ baseURL: 'https://api.grid.plus/v1', headers: { 'user-agent': 'Mozilla/5.0 (Android 15; Mobile; SM-F958; rv:130.0) Gecko/130.0 Firefox/130.0', 'X-AppID': '808645', 'X-Platform': 'h5', 'X-Version': '8.9.7', 'X-SessionToken': '', 'X-UniqueID': this.uid(), 'X-GhostID': this.uid(), 'X-DeviceID': this.uid(), 'X-MCC': 'id-ID', 'sig': `XX${this.uid() + this.uid()}` } }); } uid() { return crypto.randomUUID().replace(/-/g, ''); } form(dt) { const form = new FormData(); Object.entries(dt).forEach(([key, value]) => { form.append(key, String(value)); }); return form; } async upload(buff, method) { try { if (!Buffer.isBuffer(buff)) throw new Error('Os dados não são um buffer!'); const fileType = await fromBuffer(buff); if (!fileType) throw new Error('Não foi possível determinar o tipo de arquivo.'); const { mime, ext } = fileType; const d = await this.ins.post('/ai/web/nologin/getuploadurl', this.form({ ext, method })).then(i => i.data); await axios.put(d.data.upload_url, buff, { headers: { 'content-type': mime } }); return d.data.img_url; } catch(e) { throw new Error('Ocorreu um erro ao carregar a imagem: ' + e.message); } } async task({ path, data, sl = () => false }) { const [start, interval, timeout] = [ Date.now(), 3000, 60000 ]; return new Promise(async (resolve, reject) => { const check = async () => { if (Date.now() - start > timeout) { return reject(new Error(`O tempo limite de sondagem para o caminho foi excedido: ${path}`)); } try { const dt = await this.ins({ url: path, method: data ? 'POST' : 'GET', ...(data ? { data } : {}) }); if (dt.errmsg?.trim()) { return reject(new Error(`API error: ${dt.errmsg}`)); } if (sl(dt.data)) { return resolve(dt.data); } setTimeout(check, interval); } catch (error) { reject(error); } }; check(); }); } async edit(buff, prompt) { try { const up = await this.upload(buff, 'wn_aistyle_nano'); const dn = await this.ins.post('/ai/nano/upload', this.form({ prompt, url: up })).then(i => i.data); if (!dn.task_id) throw new Error('taskId não encontrado na solicitação'); const res = await this.task({ path: `/ai/nano/get_result/${dn.task_id}`, sl: (dt) => dt.code === 0 && !!dt.image_url, }); return res.image_url; } catch(e) { throw new Error('Falha na edição: ' + e.message); } } } module.exports = GridPlus /* EXEMPLO DE USO: const fs = require("fs"); const GridPlus = require("./gridplus"); async function exemploUso() { try { const gp = new GridPlus(); const img = fs.readFileSync("./caminho/para/sua/imagem.jpg"); // Define o prompt de edição const prompt = "Crie uma miniatura comercial em escala 1/7 dos personagens da imagem, em estilo realista e em um ambiente real. A miniatura está posicionada sobre uma mesa de computador. A miniatura possui um globo transparente redondo."; const res = await gp.edit(img, prompt); console.log("Imagem processada com sucesso:"); console.log(res); } catch (error) { console.error("Erro ao processar imagem:", error.message); } } // exemploUso(); */