beeta/chat-service/src/main.cpp
2026-01-05 22:54:27 -05:00

134 lines
4.8 KiB
C++

#include <drogon/drogon.h>
#include <iostream>
#include "services/RedisMessageStore.h"
#include "services/AuthService.h"
#include "services/ChatService.h"
#include "services/StickerService.h"
#include "services/CensorService.h"
#include "controllers/ChatController.h"
#include "controllers/ChatWebSocketController.h"
#include "controllers/ModerationController.h"
#include "controllers/ChatAdminController.h"
#include "controllers/WatchSyncController.h"
using namespace drogon;
int main() {
// Load configuration
app().loadConfigFile("config.json");
LOG_INFO << "Starting Chat Service...";
// Get configuration values
auto config = app().getCustomConfig();
auto redisConfig = config.get("redis", Json::Value::null);
auto jwtConfig = config.get("jwt", Json::Value::null);
// Initialize Redis
auto& redis = services::RedisMessageStore::getInstance();
// Get Redis host from environment or config
std::string redisHost = redisConfig.get("host", "localhost").asString();
const char* envRedisHost = std::getenv("REDIS_HOST");
if (envRedisHost) {
redisHost = envRedisHost;
}
// Get Redis password from environment
std::string redisPass = "";
const char* envRedisPass = std::getenv("REDIS_PASS");
if (envRedisPass && strlen(envRedisPass) > 0) {
redisPass = envRedisPass;
}
redis.initialize(
redisHost,
redisConfig.get("port", 6379).asInt(),
redisConfig.get("db", 1).asInt(),
redisPass
);
// Initialize Auth Service
std::string jwtSecret = jwtConfig.get("secret", "").asString();
if (jwtSecret.empty()) {
// Try environment variable
const char* envSecret = std::getenv("JWT_SECRET");
if (envSecret) {
jwtSecret = envSecret;
} else {
LOG_ERROR << "JWT_SECRET not configured!";
return 1;
}
}
auto& authService = services::AuthService::getInstance();
authService.initialize(jwtSecret);
// Initialize Chat Service
auto& chatService = services::ChatService::getInstance();
chatService.initialize();
// Initialize Sticker Service (for :roll: and :rtd: processing)
auto& stickerService = services::StickerService::getInstance();
stickerService.initialize();
// Initialize Censor Service (for word filtering)
auto& censorService = services::CensorService::getInstance();
censorService.initialize();
LOG_INFO << "Chat initialization complete";
// Set CORS
app().registerPostHandlingAdvice([](const HttpRequestPtr& req, const HttpResponsePtr& resp) {
resp->addHeader("Access-Control-Allow-Origin", "*");
resp->addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
resp->addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
resp->addHeader("Access-Control-Max-Age", "3600");
});
// Handle OPTIONS requests
app().registerPreHandlingAdvice([](const HttpRequestPtr& req, AdviceCallback&& acb, AdviceChainCallback&& accb) {
if (req->method() == Options) {
auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(k200OK);
resp->addHeader("Access-Control-Allow-Origin", "*");
resp->addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
resp->addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
resp->addHeader("Access-Control-Max-Age", "3600");
acb(resp);
return;
}
accb();
});
// Ensure WebSocket controllers are loaded
ChatWebSocketController::ensureLoaded();
WatchSyncController::ensureLoaded();
// Explicitly register WebSocket paths (workaround for custom CMake builds)
app().registerWebSocketController("/chat/ws", "ChatWebSocketController");
app().registerWebSocketController("/chat/stream/{1}", "ChatWebSocketController");
app().registerWebSocketController("/watch/ws", "WatchSyncController");
LOG_INFO << "WebSocket paths explicitly registered";
LOG_INFO << "Chat Service initialized successfully";
LOG_INFO << "WebSocket endpoint: ws://localhost:8081/chat/stream/{realmId}";
LOG_INFO << "REST API: http://localhost:8081/api/chat/*";
// Register guest session timeout checker (runs every 5 minutes)
app().getLoop()->runEvery(300.0, []() {
ChatWebSocketController::checkGuestTimeouts();
});
LOG_INFO << "Guest session timeout checker registered (45-123 minute random timeout)";
// Schedule sticker fetch (must be done here, after event loop is set up)
stickerService.scheduleFetch();
// Schedule censored words fetch (must be done here, after event loop is set up)
censorService.scheduleFetch();
// Run the application
app().run();
return 0;
}