DashX-API / plugins /upscale.js
HerzaJ's picture
Create upscale.js
520ddc6 verified
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const https = require('https');
const FormData = require('form-data');
const UPLOAD_URL = 'https://api.unblurimage.ai/api/common/upload/upload-image';
const CREATE_JOB_URL = 'https://api.unblurimage.ai/api/imgupscaler/v1/ai-image-upscaler-v2/create-job';
const PRODUCT_SERIAL = '79661c82d918475e7458944c2f66857e';
const TMP_DIR = '/tmp/upscaler';
const axiosInstance = axios.create({
timeout: 60000,
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
});
function ensureTmpDir() {
if (!fs.existsSync(TMP_DIR)) {
fs.mkdirSync(TMP_DIR, { recursive: true });
}
}
async function downloadImage(imageUrl) {
const response = await axiosInstance.get(imageUrl, {
responseType: 'arraybuffer',
});
return Buffer.from(response.data);
}
function saveImageToTmp(imageBuffer) {
ensureTmpDir();
const fileName = `image_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`;
const filePath = path.join(TMP_DIR, fileName);
fs.writeFileSync(filePath, imageBuffer);
return filePath;
}
function deleteFileAfterDelay(filePath, delayMs = 10000) {
setTimeout(() => {
try {
if (fs.existsSync(filePath)) {
fs.unlinkSync(filePath);
}
} catch (error) {
console.error(`Failed to delete file ${filePath}:`, error.message);
}
}, delayMs);
}
async function uploadImage(filePath) {
const imageBuffer = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const contentType = 'image/jpeg';
const form = new FormData();
form.append('file_name', fileName);
form.append('file', imageBuffer, fileName);
const uploadResponse = await axiosInstance.post(UPLOAD_URL, form, {
headers: {
...form.getHeaders(),
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
},
});
if (uploadResponse.data.code !== 100000) {
throw new Error(`Upload failed: ${uploadResponse.data.message.en}`);
}
const uploadUrl = uploadResponse.data.result.url;
await axiosInstance.put(uploadUrl, imageBuffer, {
headers: {
'Content-Type': contentType,
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
},
});
return {
url: uploadUrl.split('?')[0],
};
}
async function createJob(imageUrl, upscaleLevel) {
const form = new FormData();
form.append('original_image_url', imageUrl);
form.append('upscale_type', upscaleLevel.toString());
const response = await axiosInstance.post(CREATE_JOB_URL, form, {
headers: {
...form.getHeaders(),
'Product-Serial': PRODUCT_SERIAL,
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Mobile Safari/537.36',
},
});
if (response.data.code !== 100000) {
throw new Error(`Job creation failed: ${response.data.message.en}`);
}
return response.data.result;
}
async function upscaleImage(imageUrl, scaleNumber) {
let tmpFilePath = null;
try {
if (!imageUrl) {
throw new Error('Image URL is required');
}
if (![2, 4, 8, 16].includes(scaleNumber)) {
throw new Error('Scale number must be 2, 4, 8, or 16');
}
const imageBuffer = await downloadImage(imageUrl);
tmpFilePath = saveImageToTmp(imageBuffer);
const uploadResult = await uploadImage(tmpFilePath);
const result = await createJob(uploadResult.url, scaleNumber);
deleteFileAfterDelay(tmpFilePath, 10000);
return result;
} catch (error) {
if (tmpFilePath && fs.existsSync(tmpFilePath)) {
fs.unlinkSync(tmpFilePath);
}
throw error;
}
}
const handler = async (req, res) => {
try {
const { image_url, scale, key } = req.query;
if (!image_url) {
return res.status(400).json({
success: false,
error: 'Missing required parameter: image_url'
});
}
if (!scale) {
return res.status(400).json({
success: false,
error: 'Missing required parameter: scale'
});
}
const scaleNum = parseInt(scale);
if (![2, 4, 8, 16].includes(scaleNum)) {
return res.status(400).json({
success: false,
error: 'Scale must be 2, 4, 8, or 16'
});
}
const result = await upscaleImage(image_url, scaleNum);
return res.json({
author: "Herza",
success: true,
data: result
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message,
timestamp: new Date().toISOString()
});
}
};
module.exports = {
name: 'Image Upscaler',
description: 'Upscale images to 2x, 4x, 8x, or 16x resolution',
type: 'GET',
routes: ['api/tools/upscale'],
tags: ['image', 'upscale', 'enhancement'],
parameters: ['image_url', 'scale', 'key'],
limit: 5,
enabled: true,
main: ['tools'],
handler
};