10 changed files with 349 additions and 5 deletions
@ -1,2 +1,3 @@ |
|||
/.idea/ |
|||
/target/ |
|||
/ext/plugins/ |
|||
|
@ -0,0 +1,221 @@ |
|||
#include <sourcemod> |
|||
#include <ripext> |
|||
|
|||
#define PLUGIN_VERSION "1.0" |
|||
|
|||
public Plugin myinfo = { |
|||
name = "Facti13 Backend Integration", |
|||
author = "gsd", |
|||
description = "Update server info directly without RCON", |
|||
version = PLUGIN_VERSION, |
|||
url = "https://tf2.pblr-nyk.pro" |
|||
} |
|||
|
|||
/* CONVAR */ |
|||
Handle g_server_id_convar = INVALID_HANDLE; |
|||
Handle g_api_secret_key_convar = INVALID_HANDLE; |
|||
Handle g_api_gateway_convar = INVALID_HANDLE; |
|||
|
|||
char g_server_id[32]; |
|||
char g_secretkey[64]; |
|||
char g_gateway[128]; |
|||
|
|||
char g_cookie[128]; |
|||
char g_url[128]; |
|||
|
|||
Handle g_timer = INVALID_HANDLE; |
|||
int g_lastupdate = 0; |
|||
bool g_warned = true; |
|||
bool g_setuped = false; |
|||
bool g_updating = false; |
|||
|
|||
stock SetupConVar() { |
|||
g_server_id_convar = CreateConVar("sm_fbi_server_id", "srv8", "fbi server id", FCVAR_PROTECTED); |
|||
g_api_secret_key_convar = CreateConVar("sm_fbi_secretkey", "123456789", "fbi secret key", FCVAR_PROTECTED); |
|||
g_api_gateway_convar = CreateConVar("sm_fbi_gateway", "http://192.168.3.50:8080/api/server/%s", "fbi gateway", FCVAR_PROTECTED); |
|||
// |
|||
HookConVarChange(g_server_id_convar, OnServerIdChanged); |
|||
HookConVarChange(g_api_secret_key_convar, OnSecretKeyChanged); |
|||
HookConVarChange(g_api_gateway_convar, OnGatewayChanged); |
|||
// |
|||
GetConVarString(g_server_id_convar, g_server_id, sizeof(g_server_id)); |
|||
GetConVarString(g_api_secret_key_convar, g_secretkey, sizeof(g_secretkey)); |
|||
GetConVarString(g_api_gateway_convar, g_gateway, sizeof(g_gateway)); |
|||
// |
|||
UpdateUrlData(); |
|||
} |
|||
|
|||
stock UnSetupConvar() { |
|||
UnhookConVarChange(g_server_id_convar, OnServerIdChanged); |
|||
UnhookConVarChange(g_api_secret_key_convar, OnSecretKeyChanged); |
|||
UnhookConVarChange(g_api_gateway_convar, OnGatewayChanged); |
|||
} |
|||
|
|||
public OnServerIdChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { |
|||
strcopy(g_server_id, sizeof(g_server_id), newVal); |
|||
LogMessage("[FBI] Server id now: %s", g_server_id); |
|||
UpdateUrlData(); |
|||
} |
|||
public OnSecretKeyChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { |
|||
strcopy(g_secretkey, sizeof(g_secretkey), newVal); |
|||
LogMessage("[FBI] Secret key now lenght: %d", strlen(g_secretkey)); |
|||
UpdateUrlData(); |
|||
} |
|||
public OnGatewayChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { |
|||
strcopy(g_gateway, sizeof(g_gateway), newVal); |
|||
LogMessage("[FBI] Gateway now: %s", g_gateway); |
|||
UpdateUrlData(); |
|||
} |
|||
|
|||
stock UpdateUrlData(){ |
|||
g_setuped = false; |
|||
if (strlen(g_server_id)>0 && strlen(g_secretkey)>0){ |
|||
Format(g_url, sizeof(g_url), g_gateway, g_server_id); |
|||
Format(g_cookie, sizeof(g_cookie), "secretkey=%s", g_secretkey); |
|||
g_setuped = true; |
|||
LogMessage("[FBI] Successful set URL and SecretKey"); |
|||
} else |
|||
LogError("[FBI] Failed URL and SecretKey"); |
|||
} |
|||
|
|||
stock HTTPRequest createRequest() { |
|||
HTTPRequest client = INVALID_HANDLE; |
|||
if (strlen(g_url)>0) { |
|||
client = new HTTPRequest(g_url); |
|||
client.SetHeader("Cookie", g_cookie); |
|||
client.Timeout = 3; |
|||
} else { |
|||
LogMessage("[FBI] Client not builded"); |
|||
} |
|||
return client; |
|||
} |
|||
|
|||
stock JSONObject createPayload() { |
|||
JSONObject payload = new JSONObject(); |
|||
payload.SetBool("status", true); |
|||
|
|||
payload.SetInt("player_count", GetClientCount(true)); |
|||
payload.SetInt("max_players", MaxClients); |
|||
|
|||
char map_name[128]; |
|||
GetCurrentMap(map_name, sizeof(map_name)); |
|||
payload.SetString("map_name", map_name); |
|||
|
|||
JSONArray players = new JSONArray(); |
|||
|
|||
for(int client = 0; client <= MAXPLAYERS; client++) { |
|||
if (IsValidClient(client)) { |
|||
JSONObject player = new JSONObject(); |
|||
/* Name */ |
|||
char name[64]; |
|||
GetClientName(client, name, sizeof(name)); |
|||
player.SetString("name", name); |
|||
/* Score */ |
|||
player.SetInt("score", GetClientFrags(client)) |
|||
/* Duration */ |
|||
char duration[16]; |
|||
int ct = RoundFloat(GetClientTime(client)); |
|||
int h = ct / 3600; |
|||
int m = ct % 3600 / 60; |
|||
int s = ct % 60; |
|||
Format(duration, sizeof(duration), "%02d:%02d:%02d", h, m, s); |
|||
player.SetString("duration", duration); |
|||
/* Id */ |
|||
player.SetInt("id", GetClientUserId(client)); |
|||
/* Ip */ |
|||
char ip[32]; |
|||
GetClientIP(client, ip, sizeof(ip), false); |
|||
player.SetString("ip", ip); |
|||
/* Loss */ |
|||
player.SetInt("loss",RoundFloat(GetClientAvgLoss(client, NetFlow_Both)*1000.0)); |
|||
/* Ping */ |
|||
player.SetInt("ping",RoundFloat(GetClientLatency(client, NetFlow_Both)*1000.0)); |
|||
/* State */ |
|||
player.SetString("state", "active") |
|||
/* Steam 2 так надо, не надо спрашивать почему*/ |
|||
char steam2[32]; |
|||
GetClientAuthId(client, AuthId_Steam3, steam2, sizeof(steam2)); |
|||
player.SetString("steam2", steam2); |
|||
players.Push(player); |
|||
} |
|||
|
|||
} |
|||
|
|||
payload.Set("players", players); |
|||
return payload; |
|||
} |
|||
|
|||
stock UpdateStatus(){ |
|||
if (!g_setuped) return; |
|||
if (g_updating) return; |
|||
if (GetTime() - g_lastupdate < 10) return; |
|||
|
|||
g_updating = true; |
|||
JSONObject payload = createPayload(); |
|||
createRequest().Post(payload, Request_Callback); |
|||
g_lastupdate = GetTime(); |
|||
} |
|||
|
|||
static void Request_Callback(HTTPResponse response, any value){ |
|||
g_updating = false; |
|||
if (response.Status == HTTPStatus_OK){ |
|||
if(!g_warned) { |
|||
LogMessage("Success send payload, after error"); |
|||
g_warned = true; |
|||
} |
|||
return; |
|||
} |
|||
else{ |
|||
if(g_warned) { |
|||
LogMessage("Failed response! Code: %i", response.Status); |
|||
g_warned = false; |
|||
} |
|||
return; |
|||
} |
|||
} |
|||
|
|||
stock IsValidClient(int client){ |
|||
if(client > 4096){ |
|||
client = EntRefToEntIndex(client); |
|||
} |
|||
if(client < 1 || client > MaxClients) return false; |
|||
if(!IsClientInGame(client)) return false; |
|||
if(IsFakeClient(client)) return false; |
|||
return true; |
|||
} |
|||
|
|||
public OnPluginStart() { |
|||
SetupConVar(); |
|||
RegAdminCmd("fbi_test", TestUpdate, ADMFLAG_ROOT); |
|||
g_timer = CreateTimer(15, timerCall, 0, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); |
|||
} |
|||
|
|||
public Action timerCall(Handle:t, any:d) { |
|||
UpdateStatus(); |
|||
} |
|||
|
|||
public OnPluginEnd() { |
|||
UnSetupConvar(); |
|||
if (g_timer != INVALID_HANDLE) { |
|||
KillTimer(g_timer); |
|||
} |
|||
} |
|||
|
|||
public Action TestUpdate(int client, int args){ |
|||
UpdateStatus(); |
|||
ReplyToCommand(client, "OK!") |
|||
return Plugin_Handled; |
|||
} |
|||
|
|||
public OnClientDisconnect(int client) { |
|||
UpdateStatus(); |
|||
} |
|||
public OnClientAuthorized(int client) { |
|||
UpdateStatus(); |
|||
} |
|||
public OnMapStart() { |
|||
UpdateStatus(); |
|||
} |
|||
public OnMapEnd() { |
|||
UpdateStatus(); |
|||
} |
@ -0,0 +1,38 @@ |
|||
package app.controllers.server; |
|||
|
|||
import app.annotations.enums.AuthMethod; |
|||
import app.annotations.interfaces.CheckWebAccess; |
|||
import app.entities.Stats; |
|||
import app.entities.server.request.ServerRequestBody; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.http.HttpStatus; |
|||
import org.springframework.http.ResponseEntity; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
@RestController |
|||
@RequestMapping("api/server") |
|||
public class ServerUpdaterController { |
|||
private Stats stats; |
|||
|
|||
@Autowired |
|||
ServerUpdaterController(Stats stats) { |
|||
this.stats = stats; |
|||
} |
|||
|
|||
@PostMapping(value = "/{srv}") |
|||
@CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) |
|||
public ResponseEntity updateServer(HttpServletRequest request, @PathVariable String srv, @RequestBody ServerRequestBody serverRequestBody) { |
|||
if (!stats.getServers().containsKey(srv)) return new ResponseEntity<>(HttpStatus.NOT_FOUND); |
|||
stats.getServers().get(srv).RefreshServerFromRequest(serverRequestBody); |
|||
return new ResponseEntity(HttpStatus.OK); |
|||
} |
|||
|
|||
@DeleteMapping(value = "/{srv}") |
|||
@CheckWebAccess(auth_method = AuthMethod.SECRET_KEY) |
|||
public ResponseEntity downServer(HttpServletRequest request, @PathVariable String srv) { |
|||
if (!stats.getServers().containsKey(srv)) return new ResponseEntity<>(HttpStatus.NOT_FOUND); |
|||
stats.getServers().get(srv).RefreshServerFromRequest(null); |
|||
return new ResponseEntity(HttpStatus.OK); |
|||
} |
|||
} |
@ -0,0 +1,11 @@ |
|||
package app.entities.server.request; |
|||
|
|||
import app.entities.server.players.RCONPlayer; |
|||
import com.fasterxml.jackson.annotation.JsonGetter; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class PlayerOnServer extends RCONPlayer { |
|||
float[] pos = {}; |
|||
//int duration_seconds = 0;
|
|||
} |
@ -0,0 +1,12 @@ |
|||
package app.entities.server.request; |
|||
|
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
public class ServerRequestBody { |
|||
int max_players = 0; |
|||
int player_count = 0; |
|||
String map_name = ""; |
|||
boolean status = false; |
|||
PlayerOnServer[] players = {}; |
|||
} |
Loading…
Reference in new issue