fixes lol
All checks were successful
Build and Push / build-all (push) Successful in 9m28s

This commit is contained in:
doomtube 2026-01-10 01:50:20 -05:00
parent 48f62c8c02
commit 33624d3b02
9 changed files with 114 additions and 3 deletions

View file

@ -424,6 +424,9 @@ void ChatWebSocketController::handleNewMessage(const WebSocketConnectionPtr& wsC
} else if (msgType == "auth") {
// SECURITY FIX #9: Handle auth token sent as message (not in URL)
handleAuthMessage(wsConnPtr, data);
} else if (msgType == "get_global_history") {
// Global chat: fetch messages from ALL active realms
handleGetGlobalHistory(wsConnPtr, info);
} else {
sendError(wsConnPtr, "Unknown message type");
}
@ -918,6 +921,24 @@ void ChatWebSocketController::handleGetParticipants(const WebSocketConnectionPtr
wsConnPtr->send(Json::writeString(Json::StreamWriterBuilder(), response));
}
void ChatWebSocketController::handleGetGlobalHistory(const WebSocketConnectionPtr& wsConnPtr,
const ConnectionInfo& info) {
// Get messages from ALL active realms for global chat feature
auto& chatService = services::ChatService::getInstance();
auto messages = chatService.getGlobalMessages(100);
Json::Value response;
response["type"] = "global_history";
response["messages"] = Json::arrayValue;
for (const auto& msg : messages) {
response["messages"].append(msg.toJson());
}
LOG_DEBUG << "Sending global history with " << messages.size() << " messages";
wsConnPtr->send(Json::writeString(Json::StreamWriterBuilder(), response));
}
void ChatWebSocketController::handleRename(const WebSocketConnectionPtr& wsConnPtr,
ConnectionInfo& info,
const Json::Value& data) {

View file

@ -92,6 +92,10 @@ private:
void handleBotApiKeyAuth(const WebSocketConnectionPtr& wsConnPtr,
const std::string& apiKey);
// Global chat: fetch messages from ALL active realms
void handleGetGlobalHistory(const WebSocketConnectionPtr& wsConnPtr,
const ConnectionInfo& info);
void sendError(const WebSocketConnectionPtr& wsConnPtr, const std::string& error);
void sendSuccess(const WebSocketConnectionPtr& wsConnPtr, const Json::Value& data);

View file

@ -166,6 +166,11 @@ std::vector<models::ChatMessage> ChatService::getRealmMessages(const std::string
return redis.getMessages(realmId, limit, beforeTimestamp);
}
std::vector<models::ChatMessage> ChatService::getGlobalMessages(int limit) {
auto& redis = RedisMessageStore::getInstance();
return redis.getGlobalMessages(limit);
}
bool ChatService::deleteMessage(const std::string& realmId, const std::string& messageId,
const std::string& moderatorId) {
auto& modService = ModerationService::getInstance();

View file

@ -49,6 +49,9 @@ public:
int limit = 100,
int64_t beforeTimestamp = 0);
// Get messages from ALL active realms (for global chat history)
std::vector<models::ChatMessage> getGlobalMessages(int limit = 100);
bool deleteMessage(const std::string& realmId, const std::string& messageId,
const std::string& moderatorId);

View file

@ -131,6 +131,55 @@ std::vector<ChatMessage> RedisMessageStore::getMessages(const std::string& realm
return messages;
}
std::vector<ChatMessage> RedisMessageStore::getGlobalMessages(int limit) {
std::vector<ChatMessage> allMessages;
if (!redis_) {
LOG_ERROR << "Redis not initialized - cannot get global messages";
return allMessages;
}
try {
// Get all active realms
auto activeRealms = getActiveRealms();
LOG_DEBUG << "Getting global messages from " << activeRealms.size() << " active realms";
auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
// Fetch messages from each realm (limit per realm to avoid overwhelming)
int perRealmLimit = std::max(20, limit / 2); // At least 20, or half of total limit
for (const auto& realmId : activeRealms) {
auto realmMessages = getMessages(realmId, perRealmLimit, 0);
for (auto& msg : realmMessages) {
// Filter out expired self-destruct messages
if (msg.selfDestructAt > 0 && msg.selfDestructAt <= now) {
continue;
}
allMessages.push_back(std::move(msg));
}
}
// Sort all messages by timestamp
std::sort(allMessages.begin(), allMessages.end(),
[](const ChatMessage& a, const ChatMessage& b) {
return a.timestamp < b.timestamp;
});
// Keep only the most recent 'limit' messages
if (static_cast<int>(allMessages.size()) > limit) {
allMessages.erase(allMessages.begin(), allMessages.begin() + (allMessages.size() - limit));
}
LOG_DEBUG << "Returning " << allMessages.size() << " global messages";
} catch (const Error& e) {
LOG_ERROR << "Redis error getting global messages: " << e.what();
}
return allMessages;
}
bool RedisMessageStore::deleteMessage(const std::string& realmId, const std::string& messageId) {
if (!redis_) {
LOG_ERROR << "Redis not initialized - cannot delete message";

View file

@ -24,6 +24,8 @@ public:
std::vector<models::ChatMessage> getMessages(const std::string& realmId,
int limit = 100,
int64_t beforeTimestamp = 0);
// Get messages from ALL active realms (for global chat history)
std::vector<models::ChatMessage> getGlobalMessages(int limit = 100);
bool deleteMessage(const std::string& realmId, const std::string& messageId);
void cleanupOldMessages(const std::string& realmId, int retentionHours);
void cleanupExpiredSelfDestruct(const std::string& realmId);