const fs = require('fs'); const path = require('path'); const express = require('express'); const helmet = require('helmet'); const winston = require('winston'); const ejs = require('ejs'); const DocumentHandler = require('./lib/document_handler.js'); const FileStorage = require('./lib/file_storage.js'); // load configuration let config; try { config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'), 'utf8')); } catch (err) { console.error('Error reading config.json:', err); process.exit(1); } config.port = process.env.PORT || config.port || 8080; config.host = process.env.HOST || config.host || '0.0.0.0'; // logger-setup const logger = winston.createLogger({ level: 'verbose', format: winston.format.combine( winston.format.colorize(), winston.format.simple() ), transports: [ new winston.transports.Console() ] }); logger.info('Welcome to unknownBIN!'); // init file-storage const fileStorage = new FileStorage({ path: config.dataPath, logger: logger }); // configure the document handler const documentHandler = new DocumentHandler({ store: fileStorage, maxLength: config.maxLength, keyLength: config.keyLength, createKey: config.createKey, logger: logger }); // setup routes and request-handling const app = express(); // Configure EJS as the view engine app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'views')); // Use helmet for basic security headers app.use(helmet()); // API routes app.get('/raw/:id', (req, res) => { return documentHandler.handleRawGet(req.params.id, res); }); app.post('/documents', (req, res) => { return documentHandler.handlePost(req, res); }); app.get('/documents/:id', (req, res) => { return documentHandler.handleGet(req.params.id, res); }); // Static files app.use(express.static(path.join(__dirname, 'static'))); // Frontend routes (SSR) app.get('/:id', (req, res) => { const key = req.params.id; // Don't treat static files as paste IDs if (key.includes('.')) { return res.status(404).send('Not Found'); } fileStorage.get(key, (data) => { if (data) { // Paste found, render it with dynamic SEO tags const title = `Paste ${key} - unknownBIN`; const description = data.substring(0, 160).replace(/\n/g, ' '); res.render('index', { paste: { key: key, data: data, title: title, description: description } }); } else { // Paste not found, render the homepage res.render('index', { paste: null }); } }); }); app.get('/', (req, res) => { // Render the homepage res.render('index', { paste: null }); }); app.listen(config.port, config.host, () => { logger.info(`Listening on ${config.host}:${config.port}`); });