/** * ROUTES */ const { TextEncoder, TextDecoder } = require('util'); const fs = require('fs'); // const fsPromises = require('fs').promises; // Добавим для проверки файла перед отправкой const path = require('path'); const multer = require('multer'); const { pdfFillDataXfinity, pdfFillDataCOX, pdfFillDataATT, pdfFillDataSpectrum, pdfFillDataDukeEnergy, pdfFillDataAEPOhio, pdfFillDataEntergy, pdfFillDataPGE, pdfFillDataVerizon } = require('./lib/pdf-fill-data/src'); const appConfig = require('./config'); /** * API GLOBAL */ global.TextEncoder = global.TextEncoder || TextEncoder; global.TextDecoder = global.TextDecoder || TextDecoder; /** * API CONSTANTS */ const SECRET_KEY = appConfig.token; const authenticateToken = (req, res, next) => { let token = null; // 1. Сначала ищем токен в заголовке const authHeader = req.headers['authorization']; if (authHeader) { token = authHeader.split(' ')[1]; } // 2. Если в заголовке нет, ищем в параметрах URL if (!token && req.query.token) { token = req.query.token; } if (!token) { return res.status(401).json({ error: 'Token not found' }); } if (token != SECRET_KEY) { return res.status(403).json({ error: 'Token is not valid' }); } next(); }; const storage = multer.diskStorage({ destination: function (req, file, cb) { const uploadDir = path.join(__dirname, 'public', 'csv'); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } cb(null, uploadDir); }, filename: function (req, file, cb) { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname)); } }); const upload = multer({ storage: storage, fileFilter: (req, file, cb) => { if (path.extname(file.originalname) !== '.csv') { return cb(new Error('Only CSV files are allowed')); } cb(null, true); }, limits: { fileSize: 5 * 1024 * 1024 } }); // Создание экземпляров всех классов const pXfinity = new pdfFillDataXfinity(); const pCOX = new pdfFillDataCOX(); const pATT = new pdfFillDataATT(); const pSpectrum = new pdfFillDataSpectrum(); const pDukeEnergy = new pdfFillDataDukeEnergy(); const pEntergy = new pdfFillDataEntergy(); const pAEPOhio = new pdfFillDataAEPOhio(); const pPGE = new pdfFillDataPGE(); const pVerizon = new pdfFillDataVerizon(); /** * Template path */ pXfinity.setTemplatePath(path.join(__dirname, '/public/template/Xfinity.pdf')); pCOX.setTemplatePath(path.join(__dirname, '/public/template/COX.pdf')); pATT.setTemplatePath(path.join(__dirname, '/public/template/ATT.pdf')); pSpectrum.setTemplatePath(path.join(__dirname, '/public/template/SPECTRUM.pdf')); pDukeEnergy.setTemplatePath(path.join(__dirname, '/public/template/DukeEnergy.pdf')); pAEPOhio.setTemplatePath(path.join(__dirname, '/public/template/AEPOhio.pdf')); pEntergy.setTemplatePath(path.join(__dirname, '/public/template/Entergy.pdf')); pPGE.setTemplatePath(path.join(__dirname, '/public/template/pge_template.pdf')); pVerizon.setTemplatePath(path.join(__dirname, '/public/template/verizon_template.pdf')); /** * CSV path */ pXfinity.setTemplateCSVPath(path.join(__dirname, '/public/csv/Xfinity_States_Plans_by_Region.csv')); pXfinity.setTemplateSocrCSVPath(path.join(__dirname, '/public/csv/Xfinity_socr.csv')); /** * API ACTIONS */ pXfinity.initTaxClient(appConfig.taxtoken); pCOX.initTaxClient(appConfig.taxtoken); pATT.initTaxClient(appConfig.taxtoken); pSpectrum.initTaxClient(appConfig.taxtoken); pDukeEnergy.initTaxClient(appConfig.taxtoken); pAEPOhio.initTaxClient(appConfig.taxtoken); pPGE.initTaxClient(appConfig.taxtoken); pVerizon.initTaxClient(appConfig.taxtoken); pXfinity.loadTariffs(); pXfinity.loadSocr(); // MODULE // routes.js // ... (весь код до module.exports остается без изменений) ... // MODULE module.exports = function (app) { app.get('/', function (req, res) { console.log("=================================="); console.log("HOME"); console.log("=================================="); res.render('home', { title: 'PDFGEN' }); }); app.get('/aep-ohio-form', function (req, res) { res.render('aep_ohio_form', { title: 'AEP Ohio Form' }); // 'aep_ohio_form' - это имя вашего EJS файла }); app.get('/entergy-form', function (req, res) { res.render('entergy_form', { title: 'AEP Ohio Form' }); }); app.get('/pge-form', function (req, res) { res.render('pge_form', { title: 'PG&E PDF Generation Form' }); }); app.get('/verizon-form', function (req, res) { res.render('verizon_form', { title: 'PG&E PDF Generation Form' }); }); app.get('/api/v1', function (req, res) { console.log("=================================="); console.log("API"); console.log("=================================="); res.render('api', { title: 'PDFGEN API' }); }); // --- Xfinity API --- app.post('/api/v1/Xfinity', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Xfinity (Memory Mode)"); console.log("=================================="); try { await pXfinity.checkAccessTemplate(); await pXfinity.initPdfDoc(); await pXfinity.initBaseFonts(); await pXfinity.initCustomFonts([ path.join(__dirname, '/public/fonts/XfinityBrownTT-Light.ttf'), path.join(__dirname, '/public/fonts/XfinityBrownTT-Regular.ttf'), path.join(__dirname, '/public/fonts/XfinityBrownTT-Bold.ttf'), path.join(__dirname, '/public/fonts/OcrA.ttf') ]); await pXfinity.initPages(); await pXfinity.setFields(req.body); await pXfinity.draw(); const pdfBytes = await pXfinity.pdfDoc.save(); const filename = pXfinity.generateFilename('Xfinity'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (Xfinity) has been sent successfully from memory.`); } catch (error) { console.error('Error in Xfinity PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Xfinity PDF: ' + error.message }); } } }); app.get('/api/v1/Xfinity/tariffs', (req, res) => { res.json(pXfinity.getTariffsCache()); }); app.get('/api/v1/Xfinity/socr', (req, res) => { res.json(pXfinity.getSocrCache()); }); app.post('/api/v1/Xfinity/tariffs/upload', authenticateToken, upload.single('csvFile'), (req, res) => { if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } fs.renameSync(req.file.path, pXfinity.getTemplateCSVPath()); pXfinity.loadTariffs(); res.send('OK'); }); // --- COX API --- app.post('/api/v1/COX', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API COX (Memory Mode)"); console.log("=================================="); try { await pCOX.checkAccessTemplate(); await pCOX.initPdfDoc(); await pCOX.initBaseFonts(); await pCOX.initCustomFonts([ path.join(__dirname, '/public/fonts/OpenSans-Regular.ttf'), path.join(__dirname, '/public/fonts/OpenSans-Bold.ttf'), path.join(__dirname, '/public/fonts/avenir-lt-std-heavy.ttf'), path.join(__dirname, '/public/fonts/avenir-lt-std-roman.ttf'), path.join(__dirname, '/public/fonts/OCRAStd.ttf') ]); await pCOX.initPages(); await pCOX.setFields(req.body); await pCOX.draw(); const pdfBytes = await pCOX.pdfDoc.save(); const filename = pCOX.generateFilename('COX'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (COX) has been sent successfully from memory.`); } catch (error) { console.error('Error in COX PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating COX PDF: ' + error.message }); } } }); // --- ATT API --- app.post('/api/v1/ATT', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API ATT (Memory Mode)"); console.log("=================================="); try { await pATT.checkAccessTemplate(); await pATT.initPdfDoc(); await pATT.initBaseFonts(); await pATT.initCustomFonts([ path.join(__dirname, '/public/fonts/OCRAStd.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Medium Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Italic.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Black Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Black Italic.ttf') ]); await pATT.initPages(); await pATT.setFields(req.body); await pATT.draw(); const pdfBytes = await pATT.pdfDoc.save(); const filename = pATT.generateFilename('ATT'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (ATT) has been sent successfully from memory.`); } catch (error) { console.error('Error in ATT PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating ATT PDF: ' + error.message }); } } }); // --- Spectrum API --- app.post('/api/v1/Spectrum', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Spectrum (Memory Mode)"); console.log("=================================="); try { await pSpectrum.checkAccessTemplate(); await pSpectrum.initPdfDoc(); await pSpectrum.initBaseFonts(); await pSpectrum.initCustomFonts([ path.join(__dirname, '/public/fonts/OCRAStd.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Medium Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Italic.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Black Regular.ttf'), path.join(__dirname, '/public/fonts/ATT Aleck Sans Black Italic.ttf') ]); await pSpectrum.initPages(); await pSpectrum.setFields(req.body); // Убедитесь, что для Spectrum есть метод draw. В одном из файлов он был закомментирован. await pSpectrum.draw(); const pdfBytes = await pSpectrum.pdfDoc.save(); const filename = pSpectrum.generateFilename('Spectrum'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (Spectrum) has been sent successfully from memory.`); } catch (error) { console.error('Error in Spectrum PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Spectrum PDF: ' + error.message }); } } }); // --- DukeEnergy API --- app.post('/api/v1/DukeEnergy', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API DukeEnergy (Memory Mode)"); console.log("=================================="); try { await pDukeEnergy.checkAccessTemplate(); await pDukeEnergy.initPdfDoc(); await pDukeEnergy.initBaseFonts(); await pDukeEnergy.initCustomFonts([ path.join(__dirname, '/public/fonts/OpenSans-Bold.ttf'), path.join(__dirname, '/public/fonts/OpenSans-Regular.ttf') ]); await pDukeEnergy.initPages(); await pDukeEnergy.setFields(req.body); await pDukeEnergy.draw(); const pdfBytes = await pDukeEnergy.pdfDoc.save(); const filename = pDukeEnergy.generateFilename('DukeEnergy'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (DukeEnergy) has been sent successfully from memory.`); } catch (error) { console.error('Error in DukeEnergy PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating DukeEnergy PDF: ' + error.message }); } } }); // --- AEPOhio API --- app.post('/api/v1/AEPOhio', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API AEPOhio (Memory Mode)"); console.log("=================================="); try { await pAEPOhio.checkAccessTemplate(); await pAEPOhio.initPdfDoc(); await pAEPOhio.initBaseFonts(); await pAEPOhio.initCustomFonts([ path.join(__dirname, '/public/fonts/Gotham-Bold.otf'), path.join(__dirname, '/public/fonts/Gotham-Book.otf'), path.join(__dirname, '/public/fonts/OcrA.ttf') ]); await pAEPOhio.initPages(); await pAEPOhio.setFields(req.body); await pAEPOhio.draw(); const pdfBytes = await pAEPOhio.pdfDoc.save(); const filename = pAEPOhio.generateFilename('AEPOhio'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (AEPOhio) has been sent successfully from memory.`); } catch (error) { console.error('Error in AEPOhio PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating AEPOhio PDF: ' + error.message }); } } }); // --- Entergy API --- app.post('/api/v1/Entergy', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Entergy (Memory Mode)"); console.log("=================================="); try { await pEntergy.checkAccessTemplate(); await pEntergy.initPdfDoc(); await pEntergy.initBaseFonts(); // Helvetica await pEntergy.initCustomFonts([ // Укажите пути к шрифтам, которые будете использовать для Entergy path.join(__dirname, '/public/fonts/OpenSans-Bold.ttf'), path.join(__dirname, '/public/fonts/OpenSans-Regular.ttf'), path.join(__dirname, '/public/fonts/OcrA.ttf') // для штрих-кода, если нужно ]); await pEntergy.initPages(); await pEntergy.setFields(req.body); await pEntergy.draw(); const pdfBytes = await pEntergy.pdfDoc.save(); const filename = pEntergy.generateFilename('Entergy'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (Entergy) has been sent successfully from memory.`); } catch (error) { console.error('Error in Entergy PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Entergy PDF: ' + error.message }); } } }); app.post('/api/v1/PGE', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API PGE (SVG Parser Mode)"); console.log("=================================="); try { await pPGE.checkAccessTemplate(); await pPGE.initPdfDoc(); // Загружаем PDF-основу await pPGE.initBaseFonts(); // Загрузите шрифты, которые используются в SVG (например, Arial, Myriad Pro) await pPGE.initCustomFonts([ path.join(__dirname, '/public/fonts/ArialBold.ttf'), path.join(__dirname, '/public/fonts/Arial.ttf'), path.join(__dirname, '/public/fonts/ARIALNB.TTF'), path.join(__dirname, '/public/fonts/ARIALN.TTF'), path.join(__dirname, '/public/fonts/ArialItalic.ttf'), // ... ]); await pPGE.initPages(); await pPGE.setFields(req.body); await pPGE.draw(); // Этот метод теперь вызывает parseAndDrawSVG const pdfBytes = await pPGE.pdfDoc.save(); const filename = pPGE.generateFilename('PGE'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.end(pdfBytes); } catch (error) { console.error('Error in PGE PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating PGE PDF: ' + error.message }); } } }); app.post('/api/v1/Verizon', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Verizon (SVG Parser Mode)"); console.log("=================================="); try { await pVerizon.checkAccessTemplate(); await pVerizon.initPdfDoc(); await pVerizon.initBaseFonts(); // Helvetica (ifont 0) await pVerizon.initCustomFonts([ path.join(__dirname, '/public/fonts/ArialBold.ttf'), path.join(__dirname, '/public/fonts/Arial.ttf'), path.join(__dirname, '/public/fonts/OcrA.ttf'), // для штрих-кода, если нужно path.join(__dirname, '/public/fonts/kalypsa.ttf') ]); await pVerizon.initPages(); await pVerizon.setFields(req.body); await pVerizon.draw(); // Вызывает parseAndDrawSVG const pdfBytes = await pVerizon.pdfDoc.save(); const filename = pVerizon.generateFilename('Verizon'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.end(pdfBytes); } catch (error) { console.error('Error in Verizon PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Verizon PDF: ' + error.message }); } } }); ///////////////////////////////////////////////////////////////////////////////////// // --- AEPOhio API --- app.get('/api/v1/AEPOhio/random', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API AEPOhio (Memory Mode)"); console.log("=================================="); try { await pAEPOhio.checkAccessTemplate(); await pAEPOhio.initPdfDoc(); await pAEPOhio.initBaseFonts(); await pAEPOhio.initCustomFonts([ path.join(__dirname, '/public/fonts/Gotham-Bold.otf'), path.join(__dirname, '/public/fonts/Gotham-Book.otf'), path.join(__dirname, '/public/fonts/OcrA.ttf') ]); await pAEPOhio.initPages(); await pAEPOhio.setFields({}); await pAEPOhio.draw(); const pdfBytes = await pAEPOhio.pdfDoc.save(); const filename = pAEPOhio.generateFilename('AEPOhio'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (AEPOhio) has been sent successfully from memory.`); } catch (error) { console.error('Error in AEPOhio PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating AEPOhio PDF: ' + error.message }); } } }); // --- Entergy API --- app.get('/api/v1/Entergy/random', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Entergy (Memory Mode)"); console.log("=================================="); try { await pEntergy.checkAccessTemplate(); await pEntergy.initPdfDoc(); await pEntergy.initBaseFonts(); // Helvetica await pEntergy.initCustomFonts([ // Укажите пути к шрифтам, которые будете использовать для Entergy path.join(__dirname, '/public/fonts/OpenSans-Bold.ttf'), path.join(__dirname, '/public/fonts/OpenSans-Regular.ttf'), path.join(__dirname, '/public/fonts/OcrA.ttf') // для штрих-кода, если нужно ]); await pEntergy.initPages(); await pEntergy.setFields({}); await pEntergy.draw(); const pdfBytes = await pEntergy.pdfDoc.save(); const filename = pEntergy.generateFilename('Entergy'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.setHeader('Content-Length', pdfBytes.length); res.end(pdfBytes); console.log(`File ${filename} (Entergy) has been sent successfully from memory.`); } catch (error) { console.error('Error in Entergy PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Entergy PDF: ' + error.message }); } } }); app.get('/api/v1/PGE/random', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API PGE (SVG Parser Mode)"); console.log("=================================="); try { await pPGE.checkAccessTemplate(); await pPGE.initPdfDoc(); // Загружаем PDF-основу await pPGE.initBaseFonts(); // Загрузите шрифты, которые используются в SVG (например, Arial, Myriad Pro) await pPGE.initCustomFonts([ path.join(__dirname, '/public/fonts/ArialBold.ttf'), path.join(__dirname, '/public/fonts/Arial.ttf'), path.join(__dirname, '/public/fonts/ARIALNB.TTF'), path.join(__dirname, '/public/fonts/ARIALN.TTF'), path.join(__dirname, '/public/fonts/ArialItalic.ttf'), // ... ]); await pPGE.initPages(); await pPGE.setFields({}); await pPGE.draw(); // Этот метод теперь вызывает parseAndDrawSVG const pdfBytes = await pPGE.pdfDoc.save(); const filename = pPGE.generateFilename('PGE'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.end(pdfBytes); } catch (error) { console.error('Error in PGE PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating PGE PDF: ' + error.message }); } } }); app.get('/api/v1/Verizon/random', authenticateToken, async function (req, res) { console.log("=================================="); console.log("API Verizon (SVG Parser Mode)"); console.log("=================================="); try { await pVerizon.checkAccessTemplate(); await pVerizon.initPdfDoc(); await pVerizon.initBaseFonts(); // Helvetica (ifont 0) await pVerizon.initCustomFonts([ path.join(__dirname, '/public/fonts/ArialBold.ttf'), path.join(__dirname, '/public/fonts/Arial.ttf'), path.join(__dirname, '/public/fonts/OcrA.ttf'), // для штрих-кода, если нужно path.join(__dirname, '/public/fonts/kalypsa.ttf') ]); await pVerizon.initPages(); await pVerizon.setFields({}); await pVerizon.draw(); // Вызывает parseAndDrawSVG const pdfBytes = await pVerizon.pdfDoc.save(); const filename = pVerizon.generateFilename('Verizon'); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.end(pdfBytes); } catch (error) { console.error('Error in Verizon PDF generation:', error); if (!res.headersSent) { res.status(500).json({ error: 'Error generating Verizon PDF: ' + error.message }); } } }); };