|
@@ -0,0 +1,150 @@
|
|
|
+/**
|
|
|
+ * [CSRD] SourceCBL Integration
|
|
|
+ *
|
|
|
+ * An optimized version of the SourceCBL plugin.
|
|
|
+ */
|
|
|
+#pragma semicolon 1
|
|
|
+#include <sourcemod>
|
|
|
+
|
|
|
+#include <steamtools>
|
|
|
+
|
|
|
+#pragma newdecls required
|
|
|
+#include <newdecl-handles/smjansson>
|
|
|
+
|
|
|
+#define PLUGIN_VERSION "0.1.0"
|
|
|
+public Plugin myinfo = {
|
|
|
+ name = "[CSRD] SourceCBL Integration",
|
|
|
+ author = "nosoop",
|
|
|
+ description = "Personal integartion of the SourceCBL API.",
|
|
|
+ version = PLUGIN_VERSION,
|
|
|
+ url = "https://git.csrd.science/"
|
|
|
+}
|
|
|
+
|
|
|
+#define INVALID_USERID -1
|
|
|
+#define SOURCECBL_REQUEST_BAN_ENDPOINT "https://sourcecbl.com/api/steam/"
|
|
|
+#define SOURCECBL_API_TIMEOUT 5
|
|
|
+
|
|
|
+enum APIResponse {
|
|
|
+ Response_Success = 0,
|
|
|
+ Response_NotAuthorized
|
|
|
+};
|
|
|
+
|
|
|
+char g_CommunityKickLog[PLATFORM_MAX_PATH];
|
|
|
+
|
|
|
+public void OnPluginStart() {
|
|
|
+ CreateConVar("sm_scbl_enabled", "1",
|
|
|
+ "Teamwork.TF convar for A2S_RULES's sake. Does absolutely nothing else.",
|
|
|
+ FCVAR_NOTIFY);
|
|
|
+
|
|
|
+ // really though, does this actually matter? we're just going to skip the thing anyways
|
|
|
+ int port = FindConVar("hostport").IntValue;
|
|
|
+ char portString[6];
|
|
|
+ IntToString(port, portString, sizeof(portString));
|
|
|
+
|
|
|
+
|
|
|
+ RegAdminCmd("cbl_check_steamid", CheckCBLStatus, ADMFLAG_ROOT);
|
|
|
+
|
|
|
+ BuildPath(Path_SM, g_CommunityKickLog, sizeof(g_CommunityKickLog), "logs/sourcecbl.log");
|
|
|
+}
|
|
|
+
|
|
|
+public void OnClientAuthorized(int client) {
|
|
|
+ if (!IsFakeClient(client) && !SkipCommunityBanListCheck(client)) {
|
|
|
+ RequestClientBanStatus(client);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool SkipCommunityBanListCheck(int client) {
|
|
|
+ // TODO check if account is whitelisted (command group / keyvalues / clientprefs cache, etc.)
|
|
|
+ return CheckCommandAccess(client, "cbl_whitelist", 0);
|
|
|
+}
|
|
|
+
|
|
|
+void RequestClientBanStatus(int client) {
|
|
|
+ char steamid64[64];
|
|
|
+
|
|
|
+ if (GetClientAuthId(client, AuthId_SteamID64, steamid64, sizeof(steamid64))) {
|
|
|
+ QueryBanList(steamid64, GetClientUserId(client));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public Action CheckCBLStatus(int client, int argc) {
|
|
|
+ char steamid64[64];
|
|
|
+ GetCmdArgString(steamid64, sizeof(steamid64));
|
|
|
+ StripQuotes(steamid64);
|
|
|
+
|
|
|
+ // TODO make sure this is a valid steamid
|
|
|
+ QueryBanList(steamid64);
|
|
|
+}
|
|
|
+
|
|
|
+void QueryBanList(const char[] steamid64, int userid = INVALID_USERID) {
|
|
|
+ // we need to use the steamid64 later on down the line to verify the request even if the
|
|
|
+ // player disconnects
|
|
|
+ DataPack pack = new DataPack();
|
|
|
+ pack.WriteCell(userid);
|
|
|
+ pack.WriteString(steamid64);
|
|
|
+
|
|
|
+ HTTPRequestHandle request = Steam_CreateHTTPRequest(HTTPMethod_GET,
|
|
|
+ SOURCECBL_REQUEST_BAN_ENDPOINT);
|
|
|
+ Steam_SetHTTPRequestNetworkActivityTimeout(request, SOURCECBL_API_TIMEOUT);
|
|
|
+ Steam_SetHTTPRequestGetOrPostParameter(request, "steamid", steamid64);
|
|
|
+
|
|
|
+ Steam_SendHTTPRequest(request, OnAccountStatusReceived, pack);
|
|
|
+}
|
|
|
+
|
|
|
+public int OnAccountStatusReceived(HTTPRequestHandle request, bool bSuccess,
|
|
|
+ HTTPStatusCode status, DataPack pack) {
|
|
|
+ if (!bSuccess || status != HTTPStatusCode_OK) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int maxlen = Steam_GetHTTPResponseBodySize(request);
|
|
|
+ char[] buffer = new char[maxlen];
|
|
|
+
|
|
|
+ Steam_GetHTTPResponseBodyData(request, buffer, maxlen);
|
|
|
+ Steam_ReleaseHTTPRequest(request);
|
|
|
+
|
|
|
+ // they should've just gone with outputting VDF so I could just slap that shit into a buffer and call it a day
|
|
|
+ // also would've preferred SteamID3 so I wouldn't have to use strings
|
|
|
+
|
|
|
+ pack.Reset();
|
|
|
+ int userid = pack.ReadCell();
|
|
|
+ char steamid64[64];
|
|
|
+ pack.ReadString(steamid64, sizeof(steamid64));
|
|
|
+ delete pack;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * The API response (currently) has SteamID64 strings as keys for players that are banned.
|
|
|
+ * It's going to be a painus in the anus if they change the API again.
|
|
|
+ */
|
|
|
+ JSONObject accountStatus = view_as<JSONObject>(json_load(buffer));
|
|
|
+ if (accountStatus) {
|
|
|
+ APIResponse apiStatus = view_as<APIResponse>(
|
|
|
+ accountStatus.GetInt("response", view_as<int>(Response_Success)) );
|
|
|
+
|
|
|
+ JSONObjectIterator iterator;
|
|
|
+ if (apiStatus == Response_Success &&
|
|
|
+ (iterator = JSONObjectIterator.From(accountStatus))) {
|
|
|
+ char steamid64Key[64];
|
|
|
+
|
|
|
+ do {
|
|
|
+ iterator.GetKey(steamid64Key, sizeof(steamid64Key));
|
|
|
+ if (StrEqual(steamid64Key, steamid64)) {
|
|
|
+ // player in banlist, request ban
|
|
|
+ if (userid != INVALID_USERID) {
|
|
|
+ int client = GetClientOfUserId(userid);
|
|
|
+ if (client) {
|
|
|
+ KickClient(client,
|
|
|
+ "You have been banned by SourceCBL for hacking / cheating."
|
|
|
+ ... "\nVisit www.SourceCBL.com for more information.");
|
|
|
+
|
|
|
+ LogToFile(g_CommunityKickLog, "Kicked \"%L\" from server.", client);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while ((iterator.Next(accountStatus)));
|
|
|
+ // iterator auto-closes
|
|
|
+ } else if (apiStatus == Response_NotAuthorized) {
|
|
|
+ // TODO shut down everything
|
|
|
+ }
|
|
|
+ delete accountStatus;
|
|
|
+ }
|
|
|
+}
|