cloudku-uploader
Version:
Blazing-fast, zero-dependency uploader for CloudKu. Supports auto-conversion, chunked uploads, and TypeScript. Easily upload images, videos, audio, and documents via Node.js.
177 lines (149 loc) • 6.03 kB
JavaScript
const Base = [
'https://cloudkuimages.guru',
'https://cloudkuimages-guru.us.itpanel.app'
];
const Headers = {
'x-content-type-options': 'nosniff',
'x-frame-options': 'DENY',
'x-xss-protection': '0',
'referrer-policy': 'strict-origin-when-cross-origin,origin',
'x-provided-by': 'StackCDN',
'Referer': 'https://cloudkuimages.guru',
'Origin': 'https://cloudkuimages.guru',
'User-Agent': 'cloudku-uploader/4.2.1',
'Accept': '*/*'
};
const generateBoundary = () => '----formdata-' + Math.random().toString(36).substr(2, 9);
const parseExpireTime = (timeStr) => {
if (!timeStr) return null;
const match = timeStr.match(/^(\d+)([smhdMy])$/);
if (!match) return timeStr;
const [, amount, unit] = match;
const now = new Date();
const value = parseInt(amount);
const calculations = {
's': () => new Date(now.getTime() + value * 1000),
'm': () => new Date(now.getTime() + value * 60 * 1000),
'h': () => new Date(now.getTime() + value * 60 * 60 * 1000),
'd': () => new Date(now.getTime() + value * 24 * 60 * 60 * 1000),
'M': () => {
const date = new Date(now);
date.setMonth(date.getMonth() + value);
return date;
},
'y': () => {
const date = new Date(now);
date.setFullYear(date.getFullYear() + value);
return date;
}
};
return calculations[unit]?.()?.toISOString().split('T')[0] || timeStr;
};
const buildMultipartData = (fileBuffer, fileName, expireDate) => {
const boundary = generateBoundary();
const encoder = new TextEncoder();
let formData = `--${boundary}\r\n`;
formData += `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`;
formData += `Content-Type: application/octet-stream\r\n\r\n`;
const headerBytes = encoder.encode(formData);
const fileBytes = new Uint8Array(fileBuffer);
let expireBytes = new Uint8Array(0);
if (expireDate) {
const expireForm = `\r\n--${boundary}\r\n` +
`Content-Disposition: form-data; name="expire_date"\r\n\r\n${expireDate}`;
expireBytes = encoder.encode(expireForm);
}
const footerBytes = encoder.encode(`\r\n--${boundary}--\r\n`);
const totalSize = headerBytes.length + fileBytes.length + expireBytes.length + footerBytes.length;
const multipartData = new Uint8Array(totalSize);
let pos = 0;
multipartData.set(headerBytes, pos);
pos += headerBytes.length;
multipartData.set(fileBytes, pos);
pos += fileBytes.length;
multipartData.set(expireBytes, pos);
pos += expireBytes.length;
multipartData.set(footerBytes, pos);
return { data: multipartData, boundary };
};
const uploadFile = async (fileBuffer, fileName = 'image.jpg', expireDate = null) => {
const endpoint = expireDate ? '/temp.php' : '/upload.php';
const { data, boundary } = buildMultipartData(fileBuffer, fileName, expireDate);
const headers = {
...Headers,
'Content-Type': `multipart/form-data; boundary=${boundary}`
};
for (let i = 0; i < Base.length; i++) {
try {
const response = await fetch(Base[i] + endpoint, {
method: 'POST',
headers,
body: data
});
const result = await response.json();
result.information = 'https://cloudkuimages.guru/ch';
return result;
} catch (error) {
if (i === Base.length - 1) {
return {
status: 'error',
message: `Upload gagal: ${error.message}`,
information: 'https://cloudkuimages.guru/ch'
};
}
}
}
};
const uploadSmart = async (fileBuffer, fileName = 'image.jpg', expireTime = null) => {
const expireDate = parseExpireTime(expireTime);
return uploadFile(fileBuffer, fileName, expireDate);
};
const uploadTemp = (fileBuffer, fileName, expireTime) =>
uploadSmart(fileBuffer, fileName, expireTime);
const uploadPermanent = (fileBuffer, fileName) =>
uploadFile(fileBuffer, fileName);
const uploadBatch = async (files) => {
const results = await Promise.allSettled(
files.map(({ buffer, name, expire }) =>
uploadSmart(buffer, name, expire)
)
);
return results.map((result, index) => ({
index,
status: result.status,
data: result.status === 'fulfilled' ? result.value : null,
error: result.status === 'rejected' ? result.reason : null
}));
};
const upload30s = (buffer, name) => uploadTemp(buffer, name, '30s');
const upload15m = (buffer, name) => uploadTemp(buffer, name, '15m');
const upload6h = (buffer, name) => uploadTemp(buffer, name, '6h');
const upload7d = (buffer, name) => uploadTemp(buffer, name, '7d');
const upload3M = (buffer, name) => uploadTemp(buffer, name, '3M');
const upload1y = (buffer, name) => uploadTemp(buffer, name, '1y');
module.exports = {
uploadFile,
uploadSmart,
uploadTemp,
uploadPermanent,
uploadBatch,
parseExpireTime,
upload30s,
upload15m,
upload6h,
upload7d,
upload3M,
upload1y
};
module.exports.uploadFile = uploadFile;
module.exports.uploadSmart = uploadSmart;
module.exports.uploadTemp = uploadTemp;
module.exports.uploadPermanent = uploadPermanent;
module.exports.uploadBatch = uploadBatch;
module.exports.parseExpireTime = parseExpireTime;
module.exports.upload30s = upload30s;
module.exports.upload15m = upload15m;
module.exports.upload6h = upload6h;
module.exports.upload7d = upload7d;
module.exports.upload3M = upload3M;
module.exports.upload1y = upload1y;