- Updated API URLs from localhost:3000 to localhost:3001 in script.js - Added CORS headers to server.js to enable cross-origin requests - Changed server port from 3000 to 3001 to avoid port conflicts - Updated CSP in index.html to allow connections to localhost:3001 - Coin tracker entries now persist across page refreshes
224 lines
6.3 KiB
JavaScript
224 lines
6.3 KiB
JavaScript
const express = require('express');
|
|
const bodyParser = require('body-parser');
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const cron = require('node-cron');
|
|
const app = express();
|
|
const port = 3001;
|
|
|
|
// Serve static files from the current directory
|
|
app.use(express.static(__dirname));
|
|
app.use(bodyParser.json());
|
|
|
|
// Add CORS middleware
|
|
app.use((req, res, next) => {
|
|
res.header('Access-Control-Allow-Origin', '*');
|
|
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
|
|
next();
|
|
});
|
|
|
|
// Create backups directory if it doesn't exist
|
|
const backupDir = path.join(__dirname, 'backups');
|
|
if (!fs.existsSync(backupDir)) {
|
|
fs.mkdirSync(backupDir, { recursive: true });
|
|
}
|
|
|
|
// Database setup
|
|
const db = new sqlite3.Database('./rechner.db', (err) => {
|
|
if (err) {
|
|
console.error('Error opening database:', err.message);
|
|
} else {
|
|
console.log('Connected to the SQLite database.');
|
|
// Create tables if they don't exist
|
|
db.run(`CREATE TABLE IF NOT EXISTS coin_trackers (
|
|
id TEXT PRIMARY KEY,
|
|
data TEXT NOT NULL,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)`);
|
|
}
|
|
});
|
|
|
|
// API route to save coin trackers
|
|
app.post('/api/coinTrackers', (req, res) => {
|
|
const data = req.body.data;
|
|
if (!data) {
|
|
return res.status(400).json({ error: 'No data provided' });
|
|
}
|
|
|
|
// Save data to database
|
|
db.run('DELETE FROM coin_trackers', [], function(err) {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
const stmt = db.prepare('INSERT INTO coin_trackers (id, data) VALUES (?, ?)');
|
|
data.forEach(tracker => {
|
|
stmt.run(tracker.id, JSON.stringify(tracker));
|
|
});
|
|
stmt.finalize();
|
|
|
|
res.json({ success: true, message: 'Data saved successfully' });
|
|
});
|
|
});
|
|
|
|
// API route to get coin trackers
|
|
app.get('/api/coinTrackers', (req, res) => {
|
|
db.all('SELECT id, data FROM coin_trackers', [], (err, rows) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
const data = rows.map(row => JSON.parse(row.data));
|
|
res.json({ data });
|
|
});
|
|
});
|
|
|
|
// API route to create a backup
|
|
app.get('/api/backup/create', (req, res) => {
|
|
const name = req.query.name || `Backup_${new Date().toISOString()}`;
|
|
const timestamp = Date.now();
|
|
const fileName = `backup_${timestamp}_name_${name}.json`;
|
|
const filePath = path.join(backupDir, fileName);
|
|
|
|
// Get all data from database
|
|
db.all('SELECT id, data FROM coin_trackers', [], (err, rows) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
const data = rows.map(row => JSON.parse(row.data));
|
|
const backupData = {
|
|
date: new Date().toISOString(),
|
|
name: name,
|
|
data: data
|
|
};
|
|
|
|
// Write backup file
|
|
fs.writeFile(filePath, JSON.stringify(backupData, null, 2), (err) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
res.json({ success: true, message: 'Backup created successfully', file: fileName });
|
|
});
|
|
});
|
|
});
|
|
|
|
// API route to list backups
|
|
app.get('/api/backup/list', (req, res) => {
|
|
fs.readdir(backupDir, (err, files) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
const backups = [];
|
|
|
|
// Process each file synchronously
|
|
for (const file of files) {
|
|
if (!file.startsWith('backup_') || !file.endsWith('.json')) continue;
|
|
|
|
const filePath = path.join(backupDir, file);
|
|
const stats = fs.statSync(filePath);
|
|
|
|
let name = file;
|
|
if (file.includes('_name_')) {
|
|
name = file.split('_name_')[1].split('.json')[0];
|
|
}
|
|
|
|
const timestamp = file.split('_')[1];
|
|
|
|
backups.push({
|
|
file: file,
|
|
date: new Date(parseInt(timestamp)).toISOString(),
|
|
size: stats.size,
|
|
name: name
|
|
});
|
|
}
|
|
|
|
res.json({ backups });
|
|
});
|
|
});
|
|
|
|
// API route to restore from a backup
|
|
app.get('/api/backup/restore/:file', (req, res) => {
|
|
const fileName = req.params.file;
|
|
const filePath = path.join(backupDir, fileName);
|
|
|
|
if (!fs.existsSync(filePath)) {
|
|
return res.status(404).json({ error: 'Backup file not found' });
|
|
}
|
|
|
|
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
try {
|
|
const backupData = JSON.parse(data);
|
|
|
|
// Clear existing data
|
|
db.run('DELETE FROM coin_trackers', [], function(err) {
|
|
if (err) {
|
|
return res.status(500).json({ error: err.message });
|
|
}
|
|
|
|
// Insert backup data
|
|
if (backupData.data && Array.isArray(backupData.data)) {
|
|
const stmt = db.prepare('INSERT INTO coin_trackers (id, data) VALUES (?, ?)');
|
|
backupData.data.forEach(tracker => {
|
|
stmt.run(tracker.id, JSON.stringify(tracker));
|
|
});
|
|
stmt.finalize();
|
|
}
|
|
|
|
res.json({ success: true, message: 'Backup restored successfully' });
|
|
});
|
|
} catch (e) {
|
|
res.status(500).json({ error: 'Invalid backup file format' });
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add a status endpoint for testing
|
|
app.get('/api/status', (req, res) => {
|
|
res.json({ status: 'ok', version: '1.0', timestamp: new Date().toISOString() });
|
|
});
|
|
|
|
// Start the server
|
|
app.listen(port, () => {
|
|
console.log(`Server running at http://localhost:${port}`);
|
|
});
|
|
|
|
// Schedule automatic backups daily at midnight
|
|
cron.schedule('0 0 * * *', () => {
|
|
console.log('Creating automatic daily backup');
|
|
const name = `Auto_${new Date().toLocaleDateString()}`;
|
|
const timestamp = Date.now();
|
|
const fileName = `backup_${timestamp}_name_${name}.json`;
|
|
const filePath = path.join(backupDir, fileName);
|
|
|
|
db.all('SELECT id, data FROM coin_trackers', [], (err, rows) => {
|
|
if (err) {
|
|
console.error('Auto backup error:', err);
|
|
return;
|
|
}
|
|
|
|
const data = rows.map(row => JSON.parse(row.data));
|
|
const backupData = {
|
|
date: new Date().toISOString(),
|
|
name: name,
|
|
data: data
|
|
};
|
|
|
|
fs.writeFile(filePath, JSON.stringify(backupData, null, 2), (err) => {
|
|
if (err) {
|
|
console.error('Error writing auto backup:', err);
|
|
return;
|
|
}
|
|
console.log('Automatic backup created successfully');
|
|
});
|
|
});
|
|
});
|