Compare commits

...

15 Commits

Author SHA1 Message Date
214626222c address feedback 2024-04-26 06:17:54 -05:00
ce5bd68067 Merge remote-tracking branch 'refs/remotes/origin/chat-http-api' into chat-http-api 2024-04-25 22:28:02 -05:00
9192dca4e6 address feedback 2024-04-25 22:27:28 -05:00
06607c9b55 Update dChatServer/ChatWebApi.cpp
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2024-04-25 21:05:35 -05:00
c3ea448be0 use reference with GetAllTeams
Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com>
2024-04-25 20:55:24 -05:00
ff721ed49b Add Swagger OpenAPI doc 2024-04-25 17:24:19 -05:00
bce03ca08d fixed config value 2024-04-25 10:25:19 -05:00
faee5b72e7 Merge branch 'main' into chat-http-api 2024-04-25 09:23:20 -05:00
77143fc2cf rename files
use config vars to disable the api and whitelist listen IP
2024-04-25 09:21:59 -05:00
5e16c13a58 Merge branch 'feat--add-nlohmann-dep' into chat-http-api 2024-04-24 10:10:32 -05:00
29e759f793 remove build test off 2024-04-24 10:00:37 -05:00
63f9a9f9d4 feat: add nlohmann/json lib 2024-04-23 16:29:57 -05:00
850ad2aa15 nl @ eof 2024-04-21 22:02:25 -05:00
ed7b33d8ab provide all the info for a some integration client to use
who->players
add teams endpoint
2024-04-21 21:56:10 -05:00
55a52b6cc0 WIP
Only works on linux, get rekt
2024-04-21 02:09:54 -05:00
8 changed files with 293 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
set(DCHATSERVER_SOURCES set(DCHATSERVER_SOURCES
"ChatWebApi.cpp"
"ChatIgnoreList.cpp" "ChatIgnoreList.cpp"
"ChatPacketHandler.cpp" "ChatPacketHandler.cpp"
"PlayerContainer.cpp" "PlayerContainer.cpp"

View File

@@ -20,6 +20,7 @@
#include "eWorldMessageType.h" #include "eWorldMessageType.h"
#include "ChatIgnoreList.h" #include "ChatIgnoreList.h"
#include "StringifiedEnum.h" #include "StringifiedEnum.h"
#include "ChatWebApi.h"
#include "Game.h" #include "Game.h"
#include "Server.h" #include "Server.h"
@@ -36,7 +37,7 @@ namespace Game {
AssetManager* assetManager = nullptr; AssetManager* assetManager = nullptr;
Game::signal_t lastSignal = 0; Game::signal_t lastSignal = 0;
std::mt19937 randomEngine; std::mt19937 randomEngine;
PlayerContainer playerContainer; PlayerContainer playerContainer;
} }
void HandlePacket(Packet* packet); void HandlePacket(Packet* packet);
@@ -122,6 +123,9 @@ int main(int argc, char** argv) {
uint32_t framesSinceMasterDisconnect = 0; uint32_t framesSinceMasterDisconnect = 0;
uint32_t framesSinceLastSQLPing = 0; uint32_t framesSinceLastSQLPing = 0;
// start the web api thread
std::thread webAPIThread(ChatWebApi::Listen, ourPort);
Game::logger->Flush(); // once immediately before main loop Game::logger->Flush(); // once immediately before main loop
while (!Game::ShouldShutdown()) { while (!Game::ShouldShutdown()) {
//Check if we're still connected to master: //Check if we're still connected to master:
@@ -174,6 +178,10 @@ int main(int argc, char** argv) {
delete Game::server; delete Game::server;
delete Game::logger; delete Game::logger;
delete Game::config; delete Game::config;
// rejoin the web api thread
ChatWebApi::Stop();
webAPIThread.join();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@@ -0,0 +1,93 @@
#include "ChatWebApi.h"
#include <cstdint>
#include "dCommonVars.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "httplib.h"
#include "dServer.h"
#include "PlayerContainer.h"
#include "dConfig.h"
#include "httplib.h"
#include "nlohmann/json.hpp"
using json = nlohmann::json;
namespace {
httplib::Server m_APIServer;
}
void ChatWebApi::Listen(const uint32_t port) {
if (Game::config->GetValue("enable_chat_web_api") != "1") {
LOG("Chat Web API is disabled");
return;
}
LOG("Chat Web API is enabled, starting web server...");
m_APIServer.Post("/announce", [](const httplib::Request& req, httplib::Response& res) {
const json data = json::parse(req.body);
if (!data.contains("title")) {
res.set_content("{\"error\":\"Missing paramater: title\"}", "application/json");
res.status = 400;
return;
}
std::string title = data["title"];
if (!data.contains("message")) {
res.set_content("{\"error\":\"Missing paramater: message\"}", "application/json");
res.status = 400;
return;
}
std::string message = data["message"];
// build and send the packet to all world servers
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_ANNOUNCE);
bitStream.Write<uint32_t>(title.size());
bitStream.Write(title);
bitStream.Write<uint32_t>(message.size());
bitStream.Write(message);
Game::server->Send(bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
});
m_APIServer.Get("/players", [](const httplib::Request& req, httplib::Response& res) {
auto data = json::array();
for (auto& [playerID, playerData ]: Game::playerContainer.GetAllPlayers()){
if (!playerData) continue;
data.push_back(playerData.to_json());
}
res.set_content(data.dump(), "application/json");
if (data.empty()) res.status = 204;
});
m_APIServer.Get("/teams", [](const httplib::Request& req, httplib::Response& res) {
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);
}
res.set_content(data.dump(), "application/json");
if (data.empty()) res.status = 204;
});
m_APIServer.listen(Game::config->GetValue("chat_web_api_listen_address").c_str(), port);
};
void ChatWebApi::Stop(){
LOG("Stopping Chat Web API server...");
m_APIServer.stop();
}

6
dChatServer/ChatWebApi.h Normal file
View File

@@ -0,0 +1,6 @@
#include <cstdint>
namespace ChatWebApi {
void Listen(const uint32_t port);
void Stop();
};

View File

@@ -1,7 +1,9 @@
#include "PlayerContainer.h" #include "PlayerContainer.h"
#include "dNetCommon.h"
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include "dNetCommon.h"
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
#include "ChatPacketHandler.h" #include "ChatPacketHandler.h"
@@ -11,7 +13,24 @@
#include "eConnectionType.h" #include "eConnectionType.h"
#include "ChatPackets.h" #include "ChatPackets.h"
#include "dConfig.h" #include "dConfig.h"
#include "eChatMessageType.h" #include "eChatMessageType.h"
using json = nlohmann::json;
const json PlayerData::to_json() const {
json data;
data["id"] = this->playerID;
data["name"] = this->playerName;
data["gm_level"] = this->gmLevel;
data["muted"] = this->GetIsMuted();
json zoneID;
zoneID["map_id"] = std::to_string(this->zoneID.GetMapID());
zoneID["instance_id"] = std::to_string(this->zoneID.GetInstanceID());
zoneID["clone_id"] = std::to_string(this->zoneID.GetCloneID());
data["zone_id"] = zoneID;
return data;
}
void PlayerContainer::Initialize() { void PlayerContainer::Initialize() {
m_MaxNumberOfBestFriends = m_MaxNumberOfBestFriends =

View File

@@ -6,6 +6,7 @@
#include "Game.h" #include "Game.h"
#include "dServer.h" #include "dServer.h"
#include <unordered_map> #include <unordered_map>
#include "nlohmann/json.hpp"
enum class eGameMasterLevel : uint8_t; enum class eGameMasterLevel : uint8_t;
@@ -36,6 +37,8 @@ struct PlayerData {
return muteExpire == 1 || muteExpire > time(NULL); return muteExpire == 1 || muteExpire > time(NULL);
} }
const nlohmann::json to_json() const;
SystemAddress sysAddr{}; SystemAddress sysAddr{};
LWOZONEID zoneID{}; LWOZONEID zoneID{};
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
@@ -88,6 +91,7 @@ public:
LWOOBJID GetId(const std::u16string& playerName); LWOOBJID GetId(const std::u16string& playerName);
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; } uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; } uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
const std::vector<TeamData*>& GetAllTeams() { return mTeams;};
private: private:
LWOOBJID m_TeamIDCounter = 0; LWOOBJID m_TeamIDCounter = 0;

151
docs/ChatWebAPI.yaml Normal file
View File

@@ -0,0 +1,151 @@
openapi: 3.0.3
info:
title: DLU Chat Server API
description: |-
This documents the available api endpoints for the DLU Chat Server Web API
contact:
name: DarkflameUniverse Github
url: https://github.com/DarkflameUniverse/DarkflameServer/issues
license:
name: GNU AGPL v3.0
url: https://github.com/DarkflameUniverse/DarkflameServer/blob/main/LICENSE
version: 1.0.0
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: http://localhost:2005/
description: localhost
tags:
- name: management
description: Server Management Utilities
- name: user
description: User Data Utilities
paths:
/announce:
post:
tags:
- management
summary: Send an announcement to the game server
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Announce"
required: true
responses:
"200":
description: Successful operation
"400":
description: Missing Parameter
/players:
get:
tags:
- user
summary: Get all online Players
responses:
"200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Player"
"204":
description: No Data
/teams:
get:
tags:
- user
summary: Get all active Teams
responses:
"200":
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Team"
"204":
description: No Data
components:
schemas:
Player:
type: object
properties:
id:
type: integer
format: int64
example: 1152921508901824000
gm_level:
type: integer
format: uint8
example: 0
name:
type: string
example: thisisatestname
muted:
type: boolean
example: false
zone_id:
$ref: "#/components/schemas/ZoneID"
ZoneID:
type: object
properties:
map_id:
type: integer
format: uint16
example: 1200
instance_id:
type: integer
format: uint16
example: 2
clone_id:
type: integer
format: uint32
example: 0
Team:
type: object
properties:
id:
type: integer
format: int64
example: 1152921508901824000
loot_flag:
type: integer
format: uint8
example: 1
local:
type: boolean
example: false
leader:
$ref: "#/components/schemas/Player"
members:
type: array
items:
$ref: "#/components/schemas/Player"
Announce:
required:
- title
- message
type: object
properties:
title:
type: string
example: A Mythran has taken Action against you!
message:
type: string
example: Check your mailbox for details!

View File

@@ -6,3 +6,11 @@ max_number_of_best_friends=5
# Change the value below to what you would like this to be (50 is live accurate) # Change the value below to what you would like this to be (50 is live accurate)
# going over 50 will be allowed in some secnarios, but proper handling will require client modding # going over 50 will be allowed in some secnarios, but proper handling will require client modding
max_number_of_friends=50 max_number_of_friends=50
# Enable or disable the chat web API, disabled by default
# It will run on the same port the chat server is running on, defined in shardconfig.ini
enable_chat_web_api=0
# If that chat web api is enabled, it will only listen for connections on this ip address
# 127.0.0.1 is localhost
chat_web_api_listen_address=127.0.0.1