/** * Content Security Microservice - Standalone Entry Point * * Independent content security service for UGC moderation. * Shared by multiple mini-games via game_id tenant isolation. * * API Endpoints: * POST /api/content/check-text - Text content security check * POST /api/content/check-image - Image content security check * GET /api/content/sensitive-words - Get sensitive word list * GET /api/user/mute-status - Check if a user is muted * GET /api/user/violation-summary - Get violation summary * POST /api/content/report - Submit a content report * GET /api/health - Health check * GET /api/metrics - Service metrics */ const express = require('express'); const http = require('http'); const WechatTokenManager = require('./services/wechatTokenManager'); const AuditLogger = require('./services/auditLogger'); const { createContentSecurityRouter } = require('./services/contentSecurityRoutes'); const ViolationService = require('./services/violationService'); const ReportService = require('./services/reportService'); // ============================================================ // Configuration // ============================================================ const PORT = process.env.PORT || 3000; const HOST = process.env.HOST || '0.0.0.0'; const DEFAULT_GAME_ID = process.env.DEFAULT_GAME_ID || 'tankwar'; // ============================================================ // Express App // ============================================================ const app = express(); // Parse JSON bodies app.use(express.json({ limit: '2mb' })); // Request logging middleware app.use((req, res, next) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; const game_id = req.headers['x-game-id'] || req.body?.game_id || DEFAULT_GAME_ID; console.log(`[HTTP] ${req.method} ${req.url} ${res.statusCode} ${duration}ms game_id=${game_id}`); }); next(); }); // ============================================================ // Health Check // ============================================================ app.get('/api/health', (req, res) => { res.json({ status: 'ok', service: 'content-security', version: '1.0.0', timestamp: Date.now(), tokenManagerAvailable: tokenManager ? tokenManager.isAvailable() : false, }); }); // ============================================================ // Metrics Endpoint // ============================================================ app.get('/api/metrics', (req, res) => { res.json({ uptime: process.uptime(), memory: process.memoryUsage(), tokenManagerAvailable: tokenManager ? tokenManager.isAvailable() : false, activeViolations: violationService ? violationService._records.size : 0, activeMutes: violationService ? violationService._mutes.size : 0, activeReports: reportService ? reportService._reports.size : 0, timestamp: Date.now(), }); }); // ============================================================ // Initialize Services // ============================================================ const auditLogger = new AuditLogger(); const tokenManager = new WechatTokenManager(); const violationService = new ViolationService({ logger: auditLogger }); const reportService = new ReportService({ logger: auditLogger, violationService }); // Mount content security routes const contentSecurityRouter = createContentSecurityRouter({ tokenManager, logger: auditLogger, violationService, reportService, }); app.use('/api/content', contentSecurityRouter); // ============================================================ // Start Server // ============================================================ const server = http.createServer(app); server.listen(PORT, HOST, async () => { console.log(`[Content Security Service] Running on ${HOST}:${PORT}`); console.log(`[Content Security Service] Default game_id: ${DEFAULT_GAME_ID}`); console.log(`[Content Security Service] API URL: http://${HOST}:${PORT}`); // Initialize token manager const success = await tokenManager.init(); if (success) { console.log('[Content Security Service] WeChat token manager initialized successfully'); } else { console.warn('[Content Security Service] WeChat token manager unavailable (token fetch failed)'); console.warn('[Content Security Service] Content checks will be rejected until token is obtained'); } }); // Graceful shutdown process.on('SIGTERM', () => { console.log('[Content Security Service] SIGTERM received, shutting down gracefully...'); tokenManager.destroy(); auditLogger.destroy(); violationService.destroy(); server.close(() => { console.log('[Content Security Service] Server closed'); process.exit(0); }); }); process.on('SIGINT', () => { console.log('[Content Security Service] SIGINT received, shutting down gracefully...'); tokenManager.destroy(); auditLogger.destroy(); violationService.destroy(); server.close(() => { console.log('[Content Security Service] Server closed'); process.exit(0); }); }); module.exports = { app, server };