const express = require('express'); const dotenv = require('dotenv'); const dns = require('dns'); // DNS FIX: Force SRV resolution to use reliable servers // This fixes querySrv EBADNAME in Termux/Android dns.setServers(['8.8.8.8', '8.8.4.4']); const cors = require('cors'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); const http = require('http'); const path = require('path'); const socketio = require('socket.io'); const connectDB = require('./db'); const { performSurgery, getLogs, handleCommand } = require('./services/sentinelService'); const { syncToCloud, restoreFromCloud } = require('./services/persistenceService'); dotenv.config(); // Critical Environment Defaults process.env.JWT_SECRET = process.env.JWT_SECRET || 'TITAN_CORE_BETA_SECRET_2026'; process.env.JWT_EXPIRE = process.env.JWT_EXPIRE || '30d'; process.env.JWT_COOKIE_EXPIRE = process.env.JWT_COOKIE_EXPIRE || '30'; // Connect to Cloud Database connectDB(); restoreFromCloud(); // Periodic Cloud Sync (Every 30 minutes) setInterval(syncToCloud, 30 * 60 * 1000); // Ensure Uploads Directory exists inside public const fs = require('fs'); const uploadsDir = path.join(__dirname, 'public', 'uploads'); if (!fs.existsSync(uploadsDir)){ fs.mkdirSync(uploadsDir, { recursive: true }); } const auth = require('./routes/auth'); const ai = require('./routes/ai'); const users = require('./routes/users'); const app = express(); // Trust first proxy (Hugging Face / Cloudflare) app.set('trust proxy', 1); // --- SENTINEL PRIORITY INTERCEPTOR --- app.use((req, res, next) => { const originalSend = res.send; res.send = function (body) { if (res.statusCode >= 500) { console.log(`[SENTINEL_AUTO] Intercepted 500 on ${req.originalUrl}`); // performSurgery logic handled in error catcher below } return originalSend.apply(res, arguments); }; next(); }); const server = http.createServer(app); const io = socketio(server, { cors: { origin: "*" } }); app.use(express.json()); app.use(helmet({ contentSecurityPolicy: false, frameguard: false, // Allow iframing crossOriginResourcePolicy: { policy: "cross-origin" }, crossOriginEmbedderPolicy: false })); // Request Logger app.use((req, res, next) => { console.log(`${req.method} ${req.path} - ${new Date().toISOString()}`); next(); }); const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 1000 }); app.use(limiter); // Enable Robust Multi-Node CORS app.use(cors({ origin: function (origin, callback) { // Allow any origin for now to 'allow everything' as requested, // or you can keep it slightly restricted to your domains: const isAllowed = !origin || origin === 'null' || origin.includes("hf.space") || origin.includes("qzz.io") || origin.includes("js.org") || origin.includes("onrender.com") || origin.includes("localhost"); if (isAllowed) { callback(null, true); } else { callback(new Error('CORS_VIOLATION_BY_MAIN_CORE')); } }, credentials: true })); app.use(express.static(path.join(__dirname, 'public'))); app.use('/api/auth', auth); app.use('/api/ai', ai); app.use('/api/users', users); app.get('/api/status/uptime', (req, res) => { const uptime = process.uptime(); res.json({ success: true, uptime: Math.floor(uptime) }); }); app.get('/api/status/sentinel-test', (req, res) => { console.log("[DIAGNOSTIC] Triggering synthetic breach for Sentinel verification..."); throw new Error("SENTINEL_TEST_STRESS_BREACH"); }); app.get('/', (req, res) => res.sendFile(path.join(__dirname, 'public', 'index.html'))); app.get('/auth', (req, res) => res.sendFile(path.join(__dirname, 'public', 'auth.html'))); const Announcement = require('./models/Announcement'); // --- ANNOUNCEMENT API --- app.get('/api/announcements/active', async (req, res) => { const now = new Date(); const active = await Announcement.findOne({ isActive: true, startTime: { $lte: now }, endTime: { $gte: now } }).sort({ createdAt: -1 }); res.json({ success: true, data: active }); }); app.post('/api/announcements', async (req, res) => { const { message, startTime, endTime } = req.body; // Verification: In a production build, we would use JWT. // For now, we will allow the creation and let the frontend handle Architect-level auth. const announcement = await Announcement.create({ message, startTime: new Date(startTime), endTime: new Date(endTime), isActive: true }); res.json({ success: true, data: announcement }); }); app.get('/chat', (req, res) => res.sendFile(path.join(__dirname, 'public', 'chat.html'))); app.get('/keys', (req, res) => res.sendFile(path.join(__dirname, 'public', 'keys.html'))); app.get('/about', (req, res) => res.sendFile(path.join(__dirname, 'public', 'about.html'))); app.get('/sentinel', (req, res) => res.sendFile(path.join(__dirname, 'public', 'sentinel.html'))); app.get('/manifesto', (req, res) => res.sendFile(path.join(__dirname, 'public', 'manifesto.html'))); app.get('/broadcast', (req, res) => res.sendFile(path.join(__dirname, 'public', 'broadcast.html'))); // Catch-all for React/Frontend routes app.get(/^(?!\/api).+/, (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); app.get('/api/status/sentinel-history', (req, res) => { res.json({ success: true, logs: getLogs() }); }); app.post('/api/status/sentinel-command', async (req, res) => { const { command } = req.body; try { const response = await handleCommand(command); res.status(200).json({ success: true, response }); } catch (err) { res.status(500).json({ success: false, error: "INTERLINK_TIMEOUT" }); } }); // GLOBAL ERROR HANDLER (SENTINEL UPLINK) app.use((err, req, res, next) => { console.log(`[SENTINEL_BREACH] ${err.stack}`); performSurgery(err.stack, req.originalUrl); res.status(err.statusCode || 500).json({ success: false, error: err.message || 'Server Error' }); }); const PORT = process.env.PORT || 7860; server.listen(PORT, () => console.log(`Codex Neural Interface active on port ${PORT}`)); module.exports = io;