webui/server.js

116 lines
3.6 KiB
JavaScript

const express = require('express')
const multer = require('multer')
const path = require('path')
const fs = require('fs')
const morgan = require('morgan')
const chalk = require('chalk').default
const app = express()
const uploadDir = path.join(__dirname, 'uploads')
if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true })
function loadConfig() {
try {
const content = fs.readFileSync(path.join(__dirname, 'config.conf'), 'utf8')
const match = content.match(/^logs\s*=\s*(.*)$/m)
if (match && match[1].trim().toLowerCase() === 'disable') return { loggingEnabled: false }
} catch {}
return { loggingEnabled: true }
}
const config = loadConfig()
const colors = {
info: chalk.cyanBright,
warn: chalk.yellowBright,
error: chalk.redBright,
action: chalk.greenBright,
sys: chalk.magentaBright
}
function log(level, msg) {
if (!config.loggingEnabled) return
const time = new Date().toISOString().replace('T', ' ').split('.')[0]
const colorFn = colors[level.toLowerCase()] || chalk.white
console.log(`[${time}] [${level.toUpperCase()}] ${colorFn(msg)}`)
}
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, uploadDir),
filename: (req, file, cb) => cb(null, `${Date.now()}-${Math.round(Math.random() * 1e9)}-${file.originalname}`)
})
const upload = multer({ storage }).array('files')
app.use(express.static(__dirname))
if (config.loggingEnabled) app.use(morgan('dev'))
app.post('/upload', (req, res) => {
upload(req, res, err => {
if (err) {
log('error', `UPLOAD ERROR: ${err.message}`)
return res.status(500).send('Upload error')
}
if (!req.files?.length) {
log('warn', `UPLOAD FAILED: No files received`)
return res.status(400).send('No files uploaded')
}
const names = req.files.map(f => f.filename).join(', ')
log('action', `UPLOADED ${req.files.length} file(s): ${names}`)
res.send(`Uploaded ${req.files.length} file(s)!`)
})
})
app.get('/files', (req, res) => {
log('info', 'Listing all files')
fs.readdir(uploadDir, (err, files) => {
if (err) {
log('error', `Unable to read uploads directory: ${err.message}`)
return res.status(500).send('Unable to scan directory')
}
const fileList = files.map(file => {
const stat = fs.statSync(path.join(uploadDir, file))
return { name: file, path: `/uploads/${file}`, size: stat.size, date: stat.mtime }
})
res.json(fileList)
})
})
app.get('/uploads/:filename', (req, res) => {
const filename = req.params.filename
const filePath = path.join(uploadDir, filename)
log('info', `Serving file: ${filename}`)
res.sendFile(filePath, err => {
if (err) {
log('error', `File not found: ${filename}`)
res.status(404).send('File not found')
}
})
})
app.get('/download/:filename', (req, res) => {
const filename = req.params.filename
const filePath = path.join(uploadDir, filename)
log('action', `Downloading file: ${filename}`)
res.download(filePath, err => {
if (err) {
log('error', `Download failed for: ${filename}`)
res.status(404).send('File not found')
}
})
})
app.delete('/delete/:filename', (req, res) => {
const filename = req.params.filename
const filePath = path.join(uploadDir, filename)
fs.unlink(filePath, err => {
if (err) {
log('error', `Failed to delete: ${filename}`)
return res.status(404).send('File not found')
}
log('action', `Deleted file: ${filename}`)
res.send('File deleted successfully')
})
})
const PORT = 3000
app.listen(PORT, () => log('sys', `Server running on http://localhost:${PORT}`))