sms-extension-1777538290/server/services/pixelbin.js
2026-03-26 14:19:26 +05:30

146 lines
4.4 KiB
JavaScript

const { PixelbinConfig, PixelbinClient } = require('@pixelbin/admin');
const { Readable } = require('stream');
const axios = require('axios');
function getPixelbinClient() {
const apiToken = process.env.PIXELBIN_API_TOKEN;
if (!apiToken) throw new Error('PIXELBIN_API_TOKEN not set');
const config = new PixelbinConfig({
domain: 'https://api.pixelbin.io',
apiSecret: apiToken,
});
return new PixelbinClient(config);
}
/** Upload a JSON object to Pixelbin. Overwrites if already exists. */
async function uploadJSON(folderPath, filename, jsonObject) {
const pixelbin = getPixelbinClient();
const buffer = Buffer.from(JSON.stringify(jsonObject, null, 2), 'utf-8');
const stream = Readable.from(buffer);
stream.path = `${filename}.json`;
await pixelbin.assets.fileUpload({
file: stream,
path: folderPath,
name: filename,
access: 'public-read',
overwrite: true,
});
}
/** Fetch a JSON file from Pixelbin. Returns null if not found. */
async function fetchJSON(folderPath, filename) {
const pixelbin = getPixelbinClient();
try {
const result = await pixelbin.assets.listFiles({ path: folderPath });
const items = result.items || [];
const file = items.find(
f => f.type === 'file' && (f.name === filename || f.name === `${filename}.json`)
);
if (!file?.url) return null;
const bustUrl = `${file.url}?t=${Date.now()}`;
const res = await axios.get(bustUrl, { timeout: 10000 });
return res.data;
} catch {
return null;
}
}
/** Download an image URL and upload it to Pixelbin. Returns CDN URL or null. */
async function uploadImageFromUrl(imageUrl, folderPath, filename) {
try {
const pixelbin = getPixelbinClient();
const res = await axios.get(imageUrl, { responseType: 'arraybuffer', timeout: 15000 });
const buffer = Buffer.from(res.data);
const rawExt = (imageUrl.split('?')[0].split('.').pop() || 'jpg').toLowerCase();
const ext = ['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(rawExt) ? rawExt : 'jpg';
const stream = Readable.from(buffer);
stream.path = `${filename}.${ext}`;
const uploaded = await pixelbin.assets.fileUpload({
file: stream,
path: folderPath,
name: filename,
access: 'public-read',
overwrite: true,
});
return uploaded?.url || null;
} catch (err) {
console.error(`Image upload failed (${imageUrl}):`, err.message);
return null;
}
}
/** List all image files in a Pixelbin folder. Returns [{ name, url }] */
async function listImages(folderPath) {
const pixelbin = getPixelbinClient();
try {
const result = await pixelbin.assets.listFiles({ path: folderPath });
return (result.items || [])
.filter(f => f.type === 'file')
.map(f => ({ name: f.name, url: f.url }));
} catch {
return [];
}
}
/** List template file names (slugs) in a Pixelbin folder. */
async function listTemplateFiles(folderPath) {
const pixelbin = getPixelbinClient();
try {
const result = await pixelbin.assets.listFiles({ path: folderPath });
return (result.items || [])
.filter(f => f.type === 'file')
.map(f => f.name);
} catch {
return [];
}
}
/** Delete a single file from Pixelbin by its fileId. */
async function deleteFile(fileId) {
const pixelbin = getPixelbinClient();
try {
await pixelbin.assets.deleteFile({ fileId });
} catch (err) {
console.error(`Failed to delete ${fileId}:`, err.message);
}
}
/** List all file items (with fileId) from a folder. */
async function listFilesWithId(folderPath) {
const pixelbin = getPixelbinClient();
try {
const result = await pixelbin.assets.listFiles({ path: folderPath });
return (result.items || []).filter(f => f.type === 'file');
} catch {
return [];
}
}
/**
* Delete all files belonging to a specific business.
* Business root: {merchantId}/{businessId}/
*/
async function deleteBusinessFiles(merchantId, businessId) {
const root = `${merchantId}/${businessId}`;
const [rootFiles, templateFiles, imageFiles] = await Promise.all([
listFilesWithId(root),
listFilesWithId(`${root}/templates`),
listFilesWithId(`${root}/images`),
]);
const all = [...rootFiles, ...templateFiles, ...imageFiles];
await Promise.all(all.map(f => deleteFile(f.fileId)));
}
module.exports = {
uploadJSON,
fetchJSON,
uploadImageFromUrl,
listImages,
listTemplateFiles,
deleteFile,
listFilesWithId,
deleteBusinessFiles,
};