2025-07-05 16:01:39 -06:00

156 lines
4.1 KiB
JavaScript

const QRCode = require('qrcode');
const axios = require('axios');
const FormData = require('form-data');
const winston = require('winston');
// Configure logger
const logger = winston.createLogger({
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console({
format: winston.format.simple()
})
]
});
/**
* Generate QR code as PNG buffer
* @param {string} text - Text/URL to encode
* @param {Object} options - QR code options
* @returns {Promise<Buffer>} PNG buffer
*/
async function generateQRCode(text, options = {}) {
const defaultOptions = {
type: 'png',
width: 256,
margin: 1,
color: {
dark: '#000000',
light: '#FFFFFF'
},
errorCorrectionLevel: 'M'
};
const qrOptions = { ...defaultOptions, ...options };
try {
const buffer = await QRCode.toBuffer(text, qrOptions);
return buffer;
} catch (error) {
logger.error('Failed to generate QR code:', error);
throw new Error('Failed to generate QR code');
}
}
/**
* Upload QR code to NocoDB storage
* @param {Buffer} buffer - PNG buffer
* @param {string} filename - Filename for the upload
* @param {Object} config - NocoDB configuration
* @returns {Promise<Object>} Upload response
*/
async function uploadQRCodeToNocoDB(buffer, filename, config) {
const formData = new FormData();
formData.append('file', buffer, {
filename: filename,
contentType: 'image/png'
});
try {
const response = await axios({
url: `${config.apiUrl}/api/v2/storage/upload`,
method: 'post',
data: formData,
headers: {
...formData.getHeaders(),
'xc-token': config.apiToken
},
params: {
path: 'qrcodes'
}
});
return response.data;
} catch (error) {
logger.error('Failed to upload QR code to NocoDB:', error);
throw new Error('Failed to upload QR code');
}
}
/**
* Generate and upload QR code
* @param {string} url - URL to encode
* @param {string} label - Label for the QR code
* @param {Object} config - NocoDB configuration
* @returns {Promise<Object>} Upload result
*/
async function generateAndUploadQRCode(url, label, config) {
if (!url) {
return null;
}
try {
// Generate QR code
const buffer = await generateQRCode(url);
// Create filename
const timestamp = Date.now();
const safeLabel = label.replace(/[^a-z0-9]/gi, '_').toLowerCase();
const filename = `qr_${safeLabel}_${timestamp}.png`;
// Upload to NocoDB
const uploadResult = await uploadQRCodeToNocoDB(buffer, filename, config);
return uploadResult;
} catch (error) {
logger.error('Failed to generate and upload QR code:', error);
throw error;
}
}
/**
* Delete QR code from NocoDB storage
* @param {string} fileUrl - File URL to delete
* @param {Object} config - NocoDB configuration
* @returns {Promise<boolean>} Success status
*/
async function deleteQRCodeFromNocoDB(fileUrl, config) {
if (!fileUrl) {
return true;
}
try {
// Extract file path from URL
const urlParts = fileUrl.split('/');
const filePath = urlParts.slice(-2).join('/');
await axios({
url: `${config.apiUrl}/api/v2/storage/upload`,
method: 'delete',
headers: {
'xc-token': config.apiToken
},
params: {
path: filePath
}
});
return true;
} catch (error) {
logger.error('Failed to delete QR code from NocoDB:', error);
// Don't throw error for deletion failures
return false;
}
}
module.exports = {
generateQRCode,
uploadQRCodeToNocoDB,
generateAndUploadQRCode,
deleteQRCodeFromNocoDB
};