BF2MC-Matchmaker
api_admin.cpp
1 #include <atomizes.hpp>
2 #include <json/json.h>
3 #include <random>
4 #include <thread>
5 #include <chrono>
6 
7 #include <logger.h>
8 #include <globals.h>
9 #include <settings.h>
10 #include <database.h>
11 #include <gpcm/client.h>
12 #include <battlefield/gamestat.h>
13 
14 #include <webserver/client.h>
15 
16 void Webserver::Client::requestAPIAdminClients(const atomizes::HTTPMessage& http_request, const std::string& url_base,
17  const Util::Url::Variables& url_variables)
18 {
19  // Check password
20  auto it = url_variables.find("password");
21  if (it == url_variables.end() || it->second != g_settings["webserver"]["password"].asString())
22  {
23  return;
24  }
25 
26  Json::Value json_results;
27 
28  // Browsing
29  Json::Value json_browsing(Json::arrayValue);
30  for(std::shared_ptr<Net::Socket> client : g_browsing_server->GetClients())
31  {
32  Json::Value json_client;
33 
34  json_client["ip"] = client.get()->GetIP();
35  json_client["port"] = client.get()->GetPort();
36 
37  time_t last_recieved_time = std::chrono::system_clock::to_time_t(client.get()->GetLastRecievedTime());
38  json_client["last_recieved_time"] = std::string(std::ctime(&last_recieved_time));
39 
40  // Debug
41  //json_client["ref_count"] = client.use_count();
42 
43  json_browsing.append(json_client);
44  }
45  json_results["browsing"] = json_browsing;
46 
47  // Gamestats
48  Json::Value json_gamestats(Json::arrayValue);
49  for(std::shared_ptr<Net::Socket> client : g_gamestats_server->GetClients())
50  {
51  Json::Value json_client;
52 
53  json_client["ip"] = client.get()->GetIP();
54  json_client["port"] = client.get()->GetPort();
55 
56  time_t last_recieved_time = std::chrono::system_clock::to_time_t(client.get()->GetLastRecievedTime());
57  json_client["last_recieved_time"] = std::string(std::ctime(&last_recieved_time));
58 
59  // Debug
60  //json_client["ref_count"] = client.use_count();
61 
62  json_gamestats.append(json_client);
63  }
64  json_results["gamestats"] = json_gamestats;
65 
66  // GPCM
67  Json::Value json_gpcm(Json::arrayValue);
68  for(std::shared_ptr<Net::Socket> client : g_gpcm_server->GetClients())
69  {
70  Json::Value json_client;
71  Json::Value json_session;
72 
73  std::shared_ptr<GPCM::Client> gpcm_client = std::dynamic_pointer_cast<GPCM::Client>(client);
74 
75  // Find session
76  GPCM::Session session = gpcm_client->GetSession();
77 
78  Battlefield::Player player;
79  player.SetProfileId(session.profileid);
80  g_database->queryPlayerByProfileId(player);
81 
82  json_client["ip"] = client.get()->GetIP();
83  json_client["port"] = client.get()->GetPort();
84 
85  time_t last_recieved_time = std::chrono::system_clock::to_time_t(client.get()->GetLastRecievedTime());
86  json_client["last_recieved_time"] = std::string(std::ctime(&last_recieved_time));
87 
88  json_session["authtoken"] = session.authtoken;
89  json_session["challenge"] = session.challenge;
90  json_session["profileid"] = session.profileid;
91  json_session["uniquenick"] = player.GetUniquenick();
92  json_session["status"] = session.status;
93 
94  json_client["session"] = json_session;
95 
96  // Debug
97  //json_client["ref_count"] = client.use_count();
98 
99  json_gpcm.append(json_client);
100  }
101  json_results["gpcm"] = json_gpcm;
102 
103  // GPSP
104  Json::Value json_gpsp(Json::arrayValue);
105  for(std::shared_ptr<Net::Socket> client : g_gpsp_server->GetClients())
106  {
107  Json::Value json_client;
108 
109  json_client["ip"] = client.get()->GetIP();
110  json_client["port"] = client.get()->GetPort();
111 
112  time_t last_recieved_time = std::chrono::system_clock::to_time_t(client.get()->GetLastRecievedTime());
113  json_client["last_recieved_time"] = std::string(std::ctime(&last_recieved_time));
114 
115  // Debug
116  //json_client["ref_count"] = client.use_count();
117 
118  json_gpsp.append(json_client);
119  }
120  json_results["gpsp"] = json_gpsp;
121 
122  // Webserver
123  Json::Value json_webserver(Json::arrayValue);
124  for(std::shared_ptr<Net::Socket> client : g_webserver_server->GetClients())
125  {
126  Json::Value json_client;
127 
128  json_client["ip"] = client.get()->GetIP();
129  json_client["port"] = client.get()->GetPort();
130 
131  time_t last_recieved_time = std::chrono::system_clock::to_time_t(client.get()->GetLastRecievedTime());
132  json_client["last_recieved_time"] = std::string(std::ctime(&last_recieved_time));
133 
134  // Debug
135  //json_client["ref_count"] = client.use_count();
136 
137  json_webserver.append(json_client);
138  }
139  json_results["webserver"] = json_webserver;
140 
141  this->Send(json_results);
142 
143  this->_LogTransaction("<--", "HTTP/1.1 200 OK");
144 }
145 
146 void Webserver::Client::requestAPIAdminKick(const atomizes::HTTPMessage& http_request, const std::string& url_base,
147  const Util::Url::Variables& url_variables)
148 {
149  Json::Value json_results;
150 
151  json_results["result"] = "FAIL";
152 
153  // Check password
154  auto it = url_variables.find("password");
155  if (it == url_variables.end() || it->second != g_settings["webserver"]["password"].asString())
156  {
157  return;
158  }
159 
160  Battlefield::Player player;
161 
162  // Get profile id
163  it = url_variables.find("profileid");
164  if (it == url_variables.end() || !player.SetProfileId(it->second))
165  {
166  return;
167  }
168 
169  for(std::shared_ptr<Net::Socket> client : g_gpcm_server->GetClients())
170  {
171  std::shared_ptr<GPCM::Client> gpcm_client = std::dynamic_pointer_cast<GPCM::Client>(client);
172 
173  // Find session
174  GPCM::Session session = gpcm_client->GetSession();
175 
176  if(session.profileid == player.GetProfileId())
177  {
178  gpcm_client.get()->Disconnect();
179  json_results["result"] = "OK";
180  }
181  }
182 
183  this->Send(json_results);
184 
185  this->_LogTransaction("<--", "HTTP/1.1 200 OK");
186 }
187 
188 void Webserver::Client::requestAPIAdminMessage(const atomizes::HTTPMessage& http_request, const std::string& url_base,
189  const Util::Url::Variables& url_variables)
190 {
191  // Check password
192  auto it = url_variables.find("password");
193  if (it == url_variables.end() || it->second != g_settings["webserver"]["password"].asString())
194  {
195  return;
196  }
197 
198  // Get message
199  it = url_variables.find("message");
200  if (it == url_variables.end() || !Util::UTF8::isValid(it->second))
201  {
202  return;
203  }
204  std::string message = it->second;
205 
206  // Get profile id
207  Battlefield::Player player;
208  it = url_variables.find("profileid");
209  if (it == url_variables.end())
210  {
211  player.SetProfileId(it->second);
212  }
213 
214  Json::Value json_results;
215 
216  for(std::shared_ptr<Net::Socket> client : g_gpcm_server->GetClients())
217  {
218  std::shared_ptr<GPCM::Client> gpcm_client = std::dynamic_pointer_cast<GPCM::Client>(client);
219 
220  // Find session
221  GPCM::Session session = gpcm_client->GetSession();
222 
223  if(session.profileid == player.GetProfileId() || player.GetProfileId() == -1)
224  {
226  1,
227  session.profileid,
228  "1",
229  message
230  );
231 
232  json_results["result"] = "OK";
233  }
234  }
235 
236  this->Send(json_results);
237 
238  this->_LogTransaction("<--", "HTTP/1.1 200 OK");
239 }
240 
241 void Webserver::Client::requestAPIAdminPlayerStatsRecalc(const atomizes::HTTPMessage& http_request, const std::string& url_base,
242  const Util::Url::Variables& url_variables)
243 {
244  // Check password
245  auto it = url_variables.find("password");
246  if (it == url_variables.end() || it->second != g_settings["webserver"]["password"].asString())
247  {
248  return;
249  }
250 
251  Battlefield::Player player;
252 
253  // Get profile id
254  it = url_variables.find("profileid");
255  if (it == url_variables.end() || !player.SetProfileId(it->second) && player.GetProfileId() > 0)
256  {
257  return;
258  }
259 
260  Json::Value json_results;
261  Json::Value json_gsplayers(Json::arrayValue);
262 
263  // Get total games needs to be process
264  uint32_t total;
265  g_database->countGameStatPlayersByProfileId(player, total);
266  json_results["total"] = total;
267 
268  for(uint32_t offset = 0; offset < total; offset += 250)
269  {
270  Battlefield::GameStatPlayers gsplayers;
271 
272  // Sleep for 50 milliseconds
273  std::this_thread::sleep_for(std::chrono::milliseconds(50));
274 
275  // Get games that the player has played in the limit and offset range
276  g_database->queryGameStatPlayersByProfileId(player, gsplayers, 250, offset);
277 
278  for(const Battlefield::GameStatPlayer& gsplayer : gsplayers)
279  {
280  if(gsplayer.IsDisabled())
281  continue;
282 
283  // Update player stats with gsplayer
284  player.Update(gsplayer);
285 
286  // Give json feedback
287  Json::Value json_gsplayer;
288 
289  json_gsplayer["id"] = gsplayer.GetId();
290  json_gsplayer["medals"] = player.GetMedals();
291  json_gsplayer["score"] = player.GetScore();
292  json_gsplayer["pph"] = player.GetPPH();
293  json_gsplayer["rank"] = player.GetRank();
294 
295  json_gsplayers.append(json_gsplayer);
296  }
297  }
298 
299  json_results["gsplayers"] = json_gsplayers;
300 
301  // Update player stats on database
302  g_database->updatePlayerStats(player);
303 
304  this->Send(json_results);
305 
306  this->_LogTransaction("<--", "HTTP/1.1 200 OK");
307 }
308 
Represents a player's statistics in a game.
Definition: gamestat.h:146
void Update(const Battlefield::GameStatPlayer &gsplayer)
Update player stats based on played game.
Represents a player with extended statistics.
Definition: player.h:38
bool queryGameStatPlayersByProfileId(const Battlefield::Player &player, Battlefield::GameStatPlayers &gsplayers, uint32_t limit=250, uint32_t offset=0)
Queries game statistics for a player by their profile ID.
bool queryPlayerByProfileId(Battlefield::Player &player)
Queries a player by their profile ID.
bool updatePlayerStats(const Battlefield::Player &player)
Updates the statistics of a player in the database.
bool countGameStatPlayersByProfileId(const Battlefield::Player &player, uint32_t &output_total)
Counts the number of game statistic players for a player by their profile ID.
static void SendBuddyMessage(int profileid, int target_profileid, const std::string &bm, const std::string &message)
Sends a buddy message from one profile ID to another.
std::vector< std::shared_ptr< Net::Socket > > GetClients()
Get the vector of client sockets connected to this server.
Definition: server.cpp:86
void requestAPIAdminKick(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to kick a client through the API.
Definition: api_admin.cpp:146
void requestAPIAdminMessage(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request to send a message to a client through the API.
Definition: api_admin.cpp:188
void requestAPIAdminClients(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handle a request for admin clients through the API.
Definition: api_admin.cpp:16
void Send(const atomizes::HTTPMessage &http_response) const
Send an HTTP response.
void _LogTransaction(const std::string &direction, const std::string &response) const
Log a transaction.
void requestAPIAdminPlayerStatsRecalc(const atomizes::HTTPMessage &http_request, const std::string &url_base, const Util::Url::Variables &url_variables)
Handles the API request to recalculate player statistics.
Definition: api_admin.cpp:241
Represents a session with a GPCM client.
Definition: gpcm/client.h:19