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 res.render('index', { title: `Paste ${key} - unknownBIN`, description: data.substring(0, 160).replace(/\n/g, ' ').trim(), content: data }); } else { // Paste not found, render the homepage with 404 status res.status(404).render('index', { title: '404 Not Found - unknownBIN', description: 'The paste you were looking for could not be found.', content: null }); } }); }); app.get('/', (req, res) => { // Render the homepage with static SEO tags res.render('index', { title: 'unknownBIN - A Secure & Modern Pastebin', description: 'unknownBIN is a secure and modern open-source Pastebin software written in Node.js. Easily share code, logs, and text snippets.', content: null }); }); app.listen(config.port, config.host, () => { logger.info(`Listening on ${config.host}:${config.port}`); });