Sylvatica.

Back to Library

sketch

js 1/27/2026
10
const axios = require('axios');
const FormData = require('form-data');

const CONFIG = {
  baseUrl: 'https://app.live3d.io/aitools',
  resultUrl: 'https://temp.live3d.io',
  origin: 'https://live3d.io',
  originFrom: '5b3e78451640893a',
  fnName: 'demo-colorify-img2img',
  requestFrom: 9
};

function getHeaders() {
  return {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
    'Accept': 'application/json, text/plain, */*',
    'fp': '20cebea9c9d06e3b020503f67762edf3',
    'fp1': 'VYuryLPUfU5QZLF53k96BkHdB7IYyJ8VXkNwwNHDooU+n3SlBumb/UiX+PyrVRJv',
    'x-code': Date.now().toString(),
    'x-guide': 'PFu2MqGSK5Wgg3jFZ9VX/LCzTI03jSf6rvUSw8ydSHolxrgCsQrbpZtyycWD/+c4ttuBDSKIYhxAPt4zhxZ4qqyEwjwk6oXmK9Nc04LlwAar9K5Hw2f781SnnuKT/CU0l5PfwaeIIqxXCn3OxyJHKLpPNp6OdkBH952BZ40GETY=',
    'theme-version': '83EmcUoQTUv50LhNx0VrdcK8rcGexcP35FcZDcpgWsAXEyO4xqL5shCY6sFIWB2Q',
    'origin': CONFIG.origin,
    'referer': CONFIG.origin + '/'
  };
}

async function uploadImage(buffer) {
  const form = new FormData();
  form.append('file', buffer, { filename: 'image.jpg', contentType: 'image/jpeg' });
  form.append('fn_name', CONFIG.fnName);
  form.append('request_from', String(CONFIG.requestFrom));
  form.append('origin_from', CONFIG.originFrom);

  const res = await axios.post(CONFIG.baseUrl + '/upload-img', form, {
    headers: { ...getHeaders(), ...form.getHeaders() }
  });

  return res.data;
}

async function createTask(path) {
  const res = await axios.post(CONFIG.baseUrl + '/of/create', {
    fn_name: CONFIG.fnName,
    call_type: 3,
    input: {
      source_image: path,
      request_from: CONFIG.requestFrom
    },
    request_from: CONFIG.requestFrom,
    origin_from: CONFIG.originFrom
  }, {
    headers: { ...getHeaders(), 'Content-Type': 'application/json' }
  });

  return res.data;
}

async function checkStatus(taskId) {
  const res = await axios.post(CONFIG.baseUrl + '/of/check-status', {
    task_id: taskId,
    fn_name: CONFIG.fnName,
    call_type: 3,
    request_from: CONFIG.requestFrom,
    origin_from: CONFIG.originFrom
  }, {
    headers: { ...getHeaders(), 'Content-Type': 'application/json' }
  });

  return res.data;
}

async function sketchColorizer(url) {
    const imageRes = await axios.get(url, { responseType: 'arraybuffer' });
    const buffer = Buffer.from(imageRes.data);

    const upload = await uploadImage(buffer);
    if (upload.code !== 200) throw new Error('Gagal upload gambar ke server AI.');

    const task = await createTask(upload.data.path);
    if (task.code !== 200) throw new Error('Gagal membuat task pemrosesan.');

    const taskId = task.data.task_id;
    for (let i = 0; i < 30; i++) { // Max tunggu 60 detik
        const result = await checkStatus(taskId);

        if (result.code === 200 && result.data?.status === 2 && result.data?.result_image) {
            const finalUrl = CONFIG.resultUrl + '/' + result.data.result_image;
            return finalUrl;
        }

        if (result.data?.status === -1) throw new Error('Proses gagal dari sisi server AI.');
        
        await new Promise(r => setTimeout(r, 2000));
    }

    throw new Error('Timeout: Proses memakan waktu terlalu lama.');
}

module.exports = { sketchColorizer };