// server.js const express = require('express'); const session = require('express-session'); const bodyParser = require('body-parser'); const path = require('path'); const fs = require('fs'); const cors = require('cors'); const app = express(); const port = 25570; // Dynamic CORS configuration: allow requests with or without an Origin header app.use(cors({ origin: function (origin, callback) { // Allow requests with no origin (like extension or curl requests) if (!origin) return callback(null, true); callback(null, true); }, credentials: true })); // Setup persistent sessions with a 1-week cookie lifetime app.use(session({ secret: 'my-secret-key', resave: false, saveUninitialized: true, cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } // 1 week })); // Parse incoming request bodies app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); // (Optional) Serve static files from "public" if needed app.use(express.static(path.join(__dirname, 'public'))); // Default route for testing app.get('/', (req, res) => { res.send("Welcome to the NovelSaver server. Please use the POST /api/login endpoint to log in."); }); // Demo credentials const demoUsername = "demo"; const demoPassword = "demo"; // In-memory storage for auto update tasks (keyed by session ID) const userAutoUpdateTasks = {}; // In-memory storage for update logs, now keyed by username (account) const userUpdatesLog = {}; // Example chapters array (if used elsewhere) const chapters = []; // POST /api/login - JSON-based login endpoint (records logs by username) app.post('/api/login', (req, res) => { console.log("Login attempt:", req.body); const { username, password } = req.body; if (username === demoUsername && password === demoPassword) { req.session.username = username; // Initialize the user's update log if it doesn't exist. if (!userUpdatesLog[username]) { userUpdatesLog[username] = []; } console.log("Login successful for account:", username); res.json({ success: true, message: "Logged in successfully" }); } else { console.log("Invalid credentials:", req.body); res.status(401).json({ success: false, message: "Invalid credentials" }); } }); // GET /api/status - returns the login status app.get('/api/status', (req, res) => { if (req.session.username) { res.json({ loggedIn: true, username: req.session.username }); } else { res.json({ loggedIn: false }); } }); // POST /record - record the current chapter URL sent by the extension (by account) app.post('/record', (req, res) => { if (!req.session.username) { return res.status(401).json({ error: 'Unauthorized' }); } const recordUrl = req.body.url; if (!recordUrl) { return res.status(400).json({ error: 'URL required' }); } // Use the username as the key for the log const user = req.session.username; if (!userUpdatesLog[user]) { userUpdatesLog[user] = []; } // Check if this URL has already been recorded for this account. const accountLog = userUpdatesLog[user]; const alreadyRecorded = accountLog.some(record => record.url === recordUrl); if (alreadyRecorded) { console.log(`Account ${user}: URL already recorded: ${recordUrl}`); return res.json({ success: true, message: 'URL already recorded, ignoring.' }); } const updateRecord = { account: user, url: recordUrl, timestamp: new Date().toISOString() }; userUpdatesLog[user].push(updateRecord); fs.appendFile('updates.log', JSON.stringify(updateRecord) + '\n', err => { if (err) { console.error("Error writing update log:", err); return res.status(500).json({ error: 'Logging failed' }); } console.log(`Account ${user} recorded URL: ${recordUrl}`); res.json({ success: true, message: 'URL recorded' }); }); }); // GET /logs - retrieve the update logs for the logged-in account app.get('/logs', (req, res) => { if (!req.session.username) { return res.status(401).json({ error: 'Unauthorized' }); } const user = req.session.username; res.json({ updates: userUpdatesLog[user] || [] }); }); // GET /logout - logout endpoint (logs persist) app.get('/logout', (req, res) => { if (userAutoUpdateTasks[req.sessionID]) { clearInterval(userAutoUpdateTasks[req.sessionID]); delete userAutoUpdateTasks[req.sessionID]; } req.session.destroy(); res.json({ success: true, message: "Logged out" }); }); app.listen(port, () => { console.log(`Server running at http://192.168.0.226:${port}`); });