#include "ChatWebAPI.h" #include "Logger.h" #include "Game.h" #include "json.hpp" #include "dCommonVars.h" #include "MessageType/Chat.h" #include "dServer.h" #include "dConfig.h" #include "PlayerContainer.h" void ChatWebAPI::HandleRequests(struct mg_connection* connection, int request, void* request_data) { if (request == MG_EV_HTTP_MSG) { struct mg_http_message* http_msg = static_cast(request_data); if (!http_msg) { mg_http_reply(connection, 400, json_content_type, "{\"error\":\"Invalid Request\"}"); return; } // Handle Post requests if (mg_strcmp(http_msg->method, mg_str("POST")) == 0) { // handle announcements if (mg_match(http_msg->uri, mg_str((root_path + "announce").c_str()), NULL)) { auto data = ParseJSON(http_msg->body.buf); if (!data) { mg_http_reply(connection, 400, json_content_type, "{\"error\":\"Invalid JSON\"}"); return; } if (!data.value().contains("title")) { mg_http_reply(connection, 400, json_content_type, "{\"error\":\"Missing paramater: title\"}"); return; } std::string title = data.value()["title"]; if (!data.value().contains("message")) { mg_http_reply(connection, 400, json_content_type, "{\"error\":\"Missing paramater: message\"}"); return; } std::string message = data.value()["message"]; LOG_DEBUG("Announcement: %s - %s", title.c_str(), message.c_str()); // build and send the packet to all world servers { CBITSTREAM; BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_ANNOUNCE); bitStream.Write(title.size()); bitStream.Write(title); bitStream.Write(message.size()); bitStream.Write(message); Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true); } mg_http_reply(connection, 200, json_content_type, "{\"status\":\"Announcement Sent\"}"); return; } // Handle GET Requests } else if (mg_strcmp(http_msg->method, mg_str("GET")) == 0) { // Get All Online players if (mg_match(http_msg->uri, mg_str((root_path + "players").c_str()), NULL)) { auto data = json::array(); for (auto& [playerID, playerData] : Game::playerContainer.GetAllPlayers()) { if (!playerData) continue; data.push_back(playerData.to_json()); } if (data.empty()) { mg_http_reply(connection, 200, json_content_type, "{\"error\":\"No Players Online\"}"); } else { mg_http_reply(connection, 200, json_content_type, data.dump().c_str()); } return; } else if (mg_match(http_msg->uri, mg_str((root_path + "teams").c_str()), NULL)) { // Get Teams auto data = json::array(); for (auto& teamData : Game::playerContainer.GetAllTeams()) { if (!teamData) continue; json toInsert; toInsert["id"] = teamData->teamID; toInsert["loot_flag"] = teamData->lootFlag; toInsert["local"] = teamData->local; auto& leader = Game::playerContainer.GetPlayerData(teamData->leaderID); toInsert["leader"] = leader.to_json(); json members; for (auto& member : teamData->memberIDs) { auto& playerData = Game::playerContainer.GetPlayerData(member); if (!playerData) continue; members.push_back(playerData.to_json()); } toInsert["members"] = members; data.push_back(toInsert); } if (data.empty()) { mg_http_reply(connection, 200, json_content_type, "{\"error\":\"No Teams Online\"}"); } else { mg_http_reply(connection, 200, json_content_type, data.dump().c_str()); } return; } } // If it hasn't been handled then reply 404 Not Found mg_http_reply(connection, 404, json_content_type, "{\"error\":\"Not Found\"}"); } } ChatWebAPI::ChatWebAPI() { if (Game::logger->GetLogDebugStatements()) mg_log_set(MG_LL_DEBUG); mg_mgr_init(&mgr); // Initialize event manager } ChatWebAPI::~ChatWebAPI() { mg_mgr_free(&mgr); } void ChatWebAPI::Listen() { // make listen address std::string listen_ip = Game::config->GetValue("web_server_listen_ip"); std::string listen_port = Game::config->GetValue("wed_server_listen_port"); std::string listen_address = "http://" + listen_ip + ":" + listen_port; LOG("Starting web server on %s", listen_address.c_str()); mg_http_listen(&mgr, listen_address.c_str(), HandleRequests, NULL); // Create HTTP listener } void ChatWebAPI::ReceiveRequests() { mg_mgr_poll(&mgr, 15); } // TODO: Move to GeneralUtils std::optional ChatWebAPI::ParseJSON(char* data) { try { return std::make_optional(json::parse(data)); } catch (const std::exception& e) { LOG_DEBUG("Failed to parse JSON: %s", e.what()); return std::nullopt; } }