initial commit
This commit is contained in:
parent
0845d7a88a
commit
877989932d
862
Discord_Unloze/scripting/Discord_Unloze.sp
Normal file
862
Discord_Unloze/scripting/Discord_Unloze.sp
Normal file
@ -0,0 +1,862 @@
|
|||||||
|
#pragma semicolon 1
|
||||||
|
|
||||||
|
#include <basecomm>
|
||||||
|
#include <sourcemod>
|
||||||
|
#include <SteamWorks>
|
||||||
|
#include <regex>
|
||||||
|
#include <smjansson>
|
||||||
|
#include <morecolors>
|
||||||
|
#include "sdktools_functions.inc"
|
||||||
|
|
||||||
|
|
||||||
|
#include <AntiBhopCheat>
|
||||||
|
#include <calladmin>
|
||||||
|
#include <entWatch>
|
||||||
|
|
||||||
|
#pragma newdecls required
|
||||||
|
|
||||||
|
#define STEAM_API_KEY "7FF6DCA2152A102DFF8CEC89D917B2B2"
|
||||||
|
#define DISCORD_LIVEWEBHOOK_URL "https://discordapp.com/api/webhooks/420234463335677961/HC5Sd_WJu4fGq1SlwOfvHLPcpCMoNAniITYAbxz2gAT80VAFin8TWK8P9x0xQSJgLXRj"
|
||||||
|
#define DISCORD_ADMINLOGS_WEBHOOKURL "https://discordapp.com/api/webhooks/420234772254687233/pgqnmLXwR8bTe5SI_EHU5ZbbyITQxBB5FsiyyDzvhQS5LZLsyljzfFGDPpY55aH5H-Lp"
|
||||||
|
#define DISCORD_ADMINCHAT_WEBHOOKURL "https://discordapp.com/api/webhooks/420234615173939220/4k2ejMnksUxS_Fv0UtTazdoWfOVizxli4Bz97PHhw4vgPkkOuG_nNuFNpmsfxCs6XFbm"
|
||||||
|
#define DISCORD_RCON_WEBHOOKURL "https://discordapp.com/api/webhooks/421078039699521536/WHHvLf4DkY8UUR_C0BjdCk1REbu5jugAzOrr0MU2nvrhR0hxn6OtlHhHgi-dR7VmfEaT"
|
||||||
|
#define DISCORD_CALLADMIN_WEBHOOKURL "https://discordapp.com/api/webhooks/423998266544357376/1LeQ5yxlsrAvi8MfgmE1HaI_IHDn419lXefwIS6WveyTa3dbZbPhNOs5cDnc8dLATeNv"
|
||||||
|
#define DISCORD_ANTIBHOPCHEAT_WEBHOOKURL "https://discordapp.com/api/webhooks/424725421632782353/76taTm6PgfeT02oX_yTgM-WEESAFp5uWxwZCoFnrW23cX8hxg9l-9mZTbCz-uI579n_9"
|
||||||
|
#define DISCORD_ENTWATCH_WEBHOOKURL "https://discordapp.com/api/webhooks/428546704195715072/s18ixMOKzadul8OwuQ3wONb3bcsjh-CIPq3jg-g2Ljhc50JpWiepwUWewJQybavpuaOv"
|
||||||
|
|
||||||
|
|
||||||
|
Regex g_Regex_Clyde = null;
|
||||||
|
|
||||||
|
ArrayList g_arrQueuedMessages = null;
|
||||||
|
|
||||||
|
Handle g_hDataTimer = null;
|
||||||
|
Handle g_hReplaceConfigFile = null;
|
||||||
|
|
||||||
|
UserMsg g_umSayText2 = INVALID_MESSAGE_ID;
|
||||||
|
|
||||||
|
bool g_bLoadedLate;
|
||||||
|
bool g_bProcessingData;
|
||||||
|
bool g_bGotReplaceFile;
|
||||||
|
bool g_bTeamChat;
|
||||||
|
|
||||||
|
char g_sReplacePath[PLATFORM_MAX_PATH];
|
||||||
|
char g_sAvatarURL[MAXPLAYERS + 1][128];
|
||||||
|
|
||||||
|
int g_iRatelimitRemaining = 5;
|
||||||
|
int g_iRatelimitReset;
|
||||||
|
|
||||||
|
int g_iLastReportID;
|
||||||
|
|
||||||
|
public Plugin myinfo =
|
||||||
|
{
|
||||||
|
name = "Discord core",
|
||||||
|
author = "Obus and Neon",
|
||||||
|
description = "Chat- & Rcon-Support",
|
||||||
|
version = "1.2.0",
|
||||||
|
url = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
public APLRes AskPluginLoad2(Handle hThis, bool bLate, char[] sError, int err_max)
|
||||||
|
{
|
||||||
|
g_bLoadedLate = bLate;
|
||||||
|
|
||||||
|
return APLRes_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginStart()
|
||||||
|
{
|
||||||
|
char sRegexErr[32];
|
||||||
|
RegexError RegexErr;
|
||||||
|
|
||||||
|
g_Regex_Clyde = CompileRegex(".*(clyde).*", PCRE_CASELESS, sRegexErr, sizeof(sRegexErr), RegexErr);
|
||||||
|
|
||||||
|
if (RegexErr != REGEX_ERROR_NONE)
|
||||||
|
LogError("Could not compile \"Clyde\" regex (err: %s)", sRegexErr);
|
||||||
|
|
||||||
|
g_hReplaceConfigFile = CreateKeyValues("AutoReplace");
|
||||||
|
BuildPath(Path_SM, g_sReplacePath, sizeof(g_sReplacePath), "configs/custom-chatcolorsreplace.cfg");
|
||||||
|
|
||||||
|
if (FileToKeyValues(g_hReplaceConfigFile, g_sReplacePath))
|
||||||
|
g_bGotReplaceFile = true;
|
||||||
|
|
||||||
|
g_arrQueuedMessages = CreateArray(ByteCountToCells(1024));
|
||||||
|
|
||||||
|
g_hDataTimer = CreateTimer(0.333, Timer_DataProcessor, INVALID_HANDLE, TIMER_REPEAT);
|
||||||
|
|
||||||
|
g_umSayText2 = GetUserMessageId("SayText2");
|
||||||
|
|
||||||
|
if (g_umSayText2 == INVALID_MESSAGE_ID)
|
||||||
|
SetFailState("This game doesn't support SayText2 user messages.");
|
||||||
|
|
||||||
|
HookUserMessage(g_umSayText2, Hook_UserMessage, false);
|
||||||
|
|
||||||
|
HookEvent("player_say", EventHook_PlayerSay, EventHookMode_Post);
|
||||||
|
|
||||||
|
if (g_bLoadedLate)
|
||||||
|
{
|
||||||
|
for (int i = 1; i <= MaxClients; i++)
|
||||||
|
{
|
||||||
|
if (!IsClientAuthorized(i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
static char sAuthID32[32];
|
||||||
|
|
||||||
|
GetClientAuthId(i, AuthId_Steam2, sAuthID32, sizeof(sAuthID32));
|
||||||
|
OnClientAuthorized(i, sAuthID32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCommandListener(CommandListener_SmChat, "sm_chat");
|
||||||
|
|
||||||
|
RegServerCmd("sm_printtoadminchat", Command_PrintToAdminChat, "Discord Integration");
|
||||||
|
RegServerCmd("sm_printtoallchat", Command_PrintToAllChat, "Discord Integration");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPluginEnd()
|
||||||
|
{
|
||||||
|
delete g_arrQueuedMessages;
|
||||||
|
delete g_hDataTimer;
|
||||||
|
|
||||||
|
UnhookUserMessage(g_umSayText2, Hook_UserMessage, false);
|
||||||
|
UnhookEvent("player_say", EventHook_PlayerSay, EventHookMode_Post);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientAuthorized(int client, const char[] sAuthID32)
|
||||||
|
{
|
||||||
|
if (IsFakeClient(client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
char sAuthID64[32];
|
||||||
|
|
||||||
|
if (!Steam32IDtoSteam64ID(sAuthID32, sAuthID64, sizeof(sAuthID64)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
static char sRequest[256];
|
||||||
|
|
||||||
|
FormatEx(sRequest, sizeof(sRequest), "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s&format=vdf", STEAM_API_KEY, sAuthID64);
|
||||||
|
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest);
|
||||||
|
|
||||||
|
if (!hRequest ||
|
||||||
|
!SteamWorks_SetHTTPRequestContextValue(hRequest, client) ||
|
||||||
|
!SteamWorks_SetHTTPCallbacks(hRequest, OnTransferComplete) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_PrintToAdminChat(int args)
|
||||||
|
{
|
||||||
|
char sArgs[1024];
|
||||||
|
char sArgs2[1024];
|
||||||
|
|
||||||
|
GetCmdArg(1, sArgs, sizeof(sArgs));
|
||||||
|
GetCmdArg(2, sArgs2, sizeof(sArgs2));
|
||||||
|
|
||||||
|
for(int i = 0; i < MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
|
if (IsValidClient(i))
|
||||||
|
{
|
||||||
|
bool bAdmin = CheckCommandAccess(i, "", ADMFLAG_GENERIC, true);
|
||||||
|
if (bAdmin)
|
||||||
|
CPrintToChat(i, "{azure}[DISCORD](ADMINS) %s: {white}%s", sArgs, sArgs2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Command_PrintToAllChat(int args)
|
||||||
|
{
|
||||||
|
char sArgs[1024];
|
||||||
|
char sArgs2[1024];
|
||||||
|
|
||||||
|
GetCmdArg(1, sArgs, sizeof(sArgs));
|
||||||
|
GetCmdArg(2, sArgs2, sizeof(sArgs2));
|
||||||
|
|
||||||
|
CPrintToChatAll("{azure}[DISCORD](ALL) %s: {white}%s", sArgs, sArgs2);
|
||||||
|
|
||||||
|
return Plugin_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Timer_DataProcessor(Handle hThis)
|
||||||
|
{
|
||||||
|
if (!g_bProcessingData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_iRatelimitRemaining == 0 && GetTime() < g_iRatelimitReset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//PrintToServer("[Timer_DataProcessor] Array Length #1: %d", g_arrQueuedMessages.Length);
|
||||||
|
|
||||||
|
char sContent[1024];
|
||||||
|
g_arrQueuedMessages.GetString(0, sContent, sizeof(sContent));
|
||||||
|
g_arrQueuedMessages.Erase(0);
|
||||||
|
|
||||||
|
char sURL[128];
|
||||||
|
g_arrQueuedMessages.GetString(0, sURL, sizeof(sURL));
|
||||||
|
g_arrQueuedMessages.Erase(0);
|
||||||
|
|
||||||
|
if (g_arrQueuedMessages.Length == 0)
|
||||||
|
g_bProcessingData = false;
|
||||||
|
|
||||||
|
//PrintToServer("[Timer_DataProcessor] Array Length #2: %d", g_arrQueuedMessages.Length);
|
||||||
|
|
||||||
|
//PrintToServer("%s | %s", sURL, sContent);
|
||||||
|
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, sURL);
|
||||||
|
|
||||||
|
JSONObject RequestJSON = view_as<JSONObject>(json_load(sContent));
|
||||||
|
|
||||||
|
if (!hRequest ||
|
||||||
|
!SteamWorks_SetHTTPRequestContextValue(hRequest, RequestJSON) ||
|
||||||
|
!SteamWorks_SetHTTPCallbacks(hRequest, OnHTTPRequestCompleted) ||
|
||||||
|
!SteamWorks_SetHTTPRequestRawPostBody(hRequest, "application/json", sContent, strlen(sContent)) ||
|
||||||
|
!SteamWorks_SetHTTPRequestNetworkActivityTimeout(hRequest, 10) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
LogError("Discord SteamWorks_CreateHTTPRequest failed.");
|
||||||
|
|
||||||
|
delete RequestJSON;
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Action Hook_UserMessage(UserMsg msg_id, Handle bf, const players[], int playersNum, bool reliable, bool init)
|
||||||
|
{
|
||||||
|
char sMessageName[32];
|
||||||
|
char sMessageSender[64];
|
||||||
|
int iAuthor = BfReadByte(bf);
|
||||||
|
bool bIsChat = view_as<bool>(BfReadByte(bf)); if (bIsChat) bIsChat=false; //fucking compiler shut the fuck up REEEEEE
|
||||||
|
BfReadString(bf, sMessageName, sizeof(sMessageName), false);
|
||||||
|
BfReadString(bf, sMessageSender, sizeof(sMessageSender), false);
|
||||||
|
|
||||||
|
if (iAuthor <= 0 || iAuthor > MaxClients)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strlen(sMessageName) == 0 || strlen(sMessageSender) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strcmp(sMessageName, "#Cstrike_Name_Change") == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sMessageName[13] == 'C' || sMessageName[13] == 'T' || sMessageName[13] == 'S')
|
||||||
|
g_bTeamChat = true;
|
||||||
|
else
|
||||||
|
g_bTeamChat = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EventHook_PlayerSay(Event hThis, const char[] sName, bool bDontBroadcast)
|
||||||
|
{
|
||||||
|
int iUserID = GetEventInt(hThis, "userid");
|
||||||
|
int iClient = GetClientOfUserId(iUserID);
|
||||||
|
char sMessageText[192];
|
||||||
|
|
||||||
|
GetEventString(hThis, "text", sMessageText, sizeof(sMessageText));
|
||||||
|
|
||||||
|
//PrintToServer("[EventHook_PlayerSay] Fired for %N: %s", iClient, sMessageText);
|
||||||
|
|
||||||
|
TrimString(sMessageText);
|
||||||
|
|
||||||
|
if (strlen(sMessageText) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char sClientName[64];
|
||||||
|
|
||||||
|
GetClientName(iClient, sClientName, sizeof(sClientName));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (g_bGotReplaceFile)
|
||||||
|
{
|
||||||
|
char sPart[192];
|
||||||
|
char sBuff[192];
|
||||||
|
int CurrentIndex = 0;
|
||||||
|
int NextIndex = 0;
|
||||||
|
|
||||||
|
while(NextIndex != -1 && CurrentIndex < sizeof(sMessageText))
|
||||||
|
{
|
||||||
|
NextIndex = BreakString(sMessageText[CurrentIndex], sPart, sizeof(sPart));
|
||||||
|
|
||||||
|
KvGetString(g_hReplaceConfigFile, sPart, sBuff, sizeof(sBuff), NULL_STRING);
|
||||||
|
|
||||||
|
if(sBuff[0])
|
||||||
|
{
|
||||||
|
ReplaceString(sMessageText[CurrentIndex], sizeof(sMessageText) - CurrentIndex, sPart, sBuff);
|
||||||
|
CurrentIndex += strlen(sBuff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
CurrentIndex += NextIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_bTeamChat)
|
||||||
|
{
|
||||||
|
if (sMessageText[0] == '@')
|
||||||
|
return;
|
||||||
|
|
||||||
|
char sMessageFinal[256];
|
||||||
|
char sTeamName[32];
|
||||||
|
|
||||||
|
GetTeamName(GetClientTeam(iClient), sTeamName, sizeof(sTeamName));
|
||||||
|
|
||||||
|
if (sTeamName[0] == 'C')
|
||||||
|
Format(sMessageFinal, sizeof(sMessageFinal), "(Counter-Terrorist) %s", sMessageText);
|
||||||
|
else if (sTeamName[0] == 'T')
|
||||||
|
Format(sMessageFinal, sizeof(sMessageFinal), "(Terrorist) %s", sMessageText);
|
||||||
|
else
|
||||||
|
Format(sMessageFinal, sizeof(sMessageFinal), "(Spectator) %s", sMessageText);
|
||||||
|
|
||||||
|
if (g_sAvatarURL[iClient][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_LIVEWEBHOOK_URL, sMessageFinal, true, sClientName, true, g_sAvatarURL[iClient]);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_LIVEWEBHOOK_URL, sMessageFinal, true, sClientName);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_sAvatarURL[iClient][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_LIVEWEBHOOK_URL, sMessageText, true, sClientName, true, g_sAvatarURL[iClient]);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_LIVEWEBHOOK_URL, sMessageText, true, sClientName);
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool Steam32IDtoSteam64ID(const char[] sSteam32ID, char[] sSteam64ID, int Size)
|
||||||
|
{
|
||||||
|
if (strlen(sSteam32ID) < 11 || strncmp(sSteam32ID[0], "STEAM_0:", 8) || strcmp(sSteam32ID, "STEAM_ID_PENDING") == 0)
|
||||||
|
{
|
||||||
|
sSteam64ID[0] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iUpper = 765611979;
|
||||||
|
int isSteam64ID = StringToInt(sSteam32ID[10]) * 2 + 60265728 + sSteam32ID[8] - 48;
|
||||||
|
|
||||||
|
int iDiv = isSteam64ID / 100000000;
|
||||||
|
int iIdx = 9 - (iDiv ? (iDiv / 10 + 1) : 0);
|
||||||
|
iUpper += iDiv;
|
||||||
|
|
||||||
|
IntToString(isSteam64ID, sSteam64ID[iIdx], Size - iIdx);
|
||||||
|
iIdx = sSteam64ID[9];
|
||||||
|
IntToString(iUpper, sSteam64ID, Size);
|
||||||
|
sSteam64ID[9] = iIdx;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void Discord_MakeStringSafe(const char[] sOrigin, char[] sOut, int iOutSize)
|
||||||
|
{
|
||||||
|
int iDataLen = strlen(sOrigin);
|
||||||
|
int iCurIndex;
|
||||||
|
|
||||||
|
for (int i = 0; i < iDataLen && iCurIndex < iOutSize; i++)
|
||||||
|
{
|
||||||
|
if (sOrigin[i] < 0x20 && sOrigin[i] != 0x0)
|
||||||
|
{
|
||||||
|
//sOut[iCurIndex] = 0x20;
|
||||||
|
//iCurIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sOrigin[i])
|
||||||
|
{
|
||||||
|
// case '"':
|
||||||
|
// {
|
||||||
|
// strcopy(sOut[iCurIndex], iOutSize, "\\u0022");
|
||||||
|
// iCurIndex += 6;
|
||||||
|
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// case '\\':
|
||||||
|
// {
|
||||||
|
// strcopy(sOut[iCurIndex], iOutSize, "\\u005C");
|
||||||
|
// iCurIndex += 6;
|
||||||
|
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
case '@':
|
||||||
|
{
|
||||||
|
strcopy(sOut[iCurIndex], iOutSize, "@"); //@ + zero-width space
|
||||||
|
iCurIndex += 4;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case '`':
|
||||||
|
{
|
||||||
|
strcopy(sOut[iCurIndex], iOutSize, "\\`");
|
||||||
|
iCurIndex += 2;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case '_':
|
||||||
|
{
|
||||||
|
strcopy(sOut[iCurIndex], iOutSize, "\\_");
|
||||||
|
iCurIndex += 2;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case '~':
|
||||||
|
{
|
||||||
|
strcopy(sOut[iCurIndex], iOutSize, "\\~");
|
||||||
|
iCurIndex += 2;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
sOut[iCurIndex] = sOrigin[i];
|
||||||
|
iCurIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stock int OnTransferComplete(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, int client)
|
||||||
|
{
|
||||||
|
if (bFailure || !bRequestSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
|
||||||
|
{
|
||||||
|
if (eStatusCode != k_EHTTPStatusCode429TooManyRequests)
|
||||||
|
LogError("SteamAPI HTTP Response failed: %d", eStatusCode);
|
||||||
|
|
||||||
|
delete hRequest;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iBodyLength;
|
||||||
|
SteamWorks_GetHTTPResponseBodySize(hRequest, iBodyLength);
|
||||||
|
|
||||||
|
char[] sData = new char[iBodyLength];
|
||||||
|
SteamWorks_GetHTTPResponseBodyData(hRequest, sData, iBodyLength);
|
||||||
|
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
APIWebResponse(sData, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void APIWebResponse(const char[] sData, int client)
|
||||||
|
{
|
||||||
|
KeyValues kvResponse = new KeyValues("SteamAPIResponse");
|
||||||
|
|
||||||
|
if (!kvResponse.ImportFromString(sData, "SteamAPIResponse"))
|
||||||
|
{
|
||||||
|
//LogError("kvResponse.ImportFromString(\"SteamAPIResponse\") in APIWebResponse failed.");
|
||||||
|
|
||||||
|
delete kvResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kvResponse.JumpToKey("players"))
|
||||||
|
{
|
||||||
|
//LogError("kvResponse.JumpToKey(\"players\") in APIWebResponse failed.");
|
||||||
|
|
||||||
|
delete kvResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kvResponse.GotoFirstSubKey())
|
||||||
|
{
|
||||||
|
//LogError("kvResponse.GotoFirstSubKey() in APIWebResponse failed.");
|
||||||
|
|
||||||
|
delete kvResponse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
kvResponse.GetString("avatarfull", g_sAvatarURL[client], sizeof(g_sAvatarURL[]));
|
||||||
|
|
||||||
|
delete kvResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void HTTPPostJSON(const char[] sURL, const char[] sText)
|
||||||
|
{
|
||||||
|
// if (g_iRatelimitRemaining > 0 && !g_bProcessingData && GetTime() < g_iRatelimitReset)
|
||||||
|
// {
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, sURL);
|
||||||
|
|
||||||
|
JSONObject RequestJSON = view_as<JSONObject>(json_load(sText));
|
||||||
|
|
||||||
|
if (!hRequest ||
|
||||||
|
!SteamWorks_SetHTTPRequestContextValue(hRequest, RequestJSON) ||
|
||||||
|
!SteamWorks_SetHTTPCallbacks(hRequest, OnHTTPRequestCompleted) ||
|
||||||
|
!SteamWorks_SetHTTPRequestRawPostBody(hRequest, "application/json", sText, strlen(sText)) ||
|
||||||
|
!SteamWorks_SetHTTPRequestNetworkActivityTimeout(hRequest, 15) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
LogError("Discord SteamWorks_CreateHTTPRequest failed.");
|
||||||
|
|
||||||
|
delete RequestJSON;
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// g_arrQueuedMessages.PushString(sText);
|
||||||
|
// g_arrQueuedMessages.PushString(sURL);
|
||||||
|
// g_bProcessingData = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//delete hRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock void Discord_POST(const char[] sURL, char[] sText, bool bUsingUsername=false, char[] sUsername=NULL_STRING, bool bUsingAvatar=false, char[] sAvatarURL=NULL_STRING, bool bSafe=true, bool bTimestamp=true)
|
||||||
|
{
|
||||||
|
//PrintToServer("[Discord_POST] Called with text: %s", sText);
|
||||||
|
|
||||||
|
JSONRootNode hJSONRoot = new JSONObject();
|
||||||
|
|
||||||
|
char sSafeText[4096];
|
||||||
|
char sFinal[4096];
|
||||||
|
|
||||||
|
if (bUsingUsername)
|
||||||
|
{
|
||||||
|
TrimString(sUsername);
|
||||||
|
|
||||||
|
if (g_Regex_Clyde.Match(sUsername) > 0 || strlen(sUsername) < 2)
|
||||||
|
(view_as<JSONObject>(hJSONRoot)).SetString("username", "Invalid Name");
|
||||||
|
else
|
||||||
|
(view_as<JSONObject>(hJSONRoot)).SetString("username", sUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUsingAvatar)
|
||||||
|
(view_as<JSONObject>(hJSONRoot)).SetString("avatar_url", sAvatarURL);
|
||||||
|
|
||||||
|
if (bSafe)
|
||||||
|
{
|
||||||
|
Discord_MakeStringSafe(sText, sSafeText, sizeof(sSafeText));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Format(sSafeText, sizeof(sSafeText), "%s", sText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bTimestamp)
|
||||||
|
{
|
||||||
|
int iTime = GetTime();
|
||||||
|
char sTime[32];
|
||||||
|
FormatTime(sTime, sizeof(sTime), "%r", iTime);
|
||||||
|
Format(sSafeText, sizeof(sSafeText), "[ *%s* ] %s", sTime, sText);
|
||||||
|
}
|
||||||
|
|
||||||
|
(view_as<JSONObject>(hJSONRoot)).SetString("content", sSafeText);
|
||||||
|
(view_as<JSONObject>(hJSONRoot)).ToString(sFinal, sizeof(sFinal), 0);
|
||||||
|
|
||||||
|
//hJSONRoot.DumpToServer();
|
||||||
|
|
||||||
|
delete hJSONRoot;
|
||||||
|
|
||||||
|
if ((g_iRatelimitRemaining > 0 || GetTime() >= g_iRatelimitReset) && !g_bProcessingData)
|
||||||
|
{
|
||||||
|
//PrintToServer("[Discord_POST] Have allowances and not processing data");
|
||||||
|
|
||||||
|
Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodPOST, sURL);
|
||||||
|
|
||||||
|
JSONObject RequestJSON = view_as<JSONObject>(json_load(sFinal));
|
||||||
|
|
||||||
|
if (!hRequest ||
|
||||||
|
!SteamWorks_SetHTTPRequestContextValue(hRequest, RequestJSON) ||
|
||||||
|
!SteamWorks_SetHTTPCallbacks(hRequest, OnHTTPRequestCompleted) ||
|
||||||
|
!SteamWorks_SetHTTPRequestRawPostBody(hRequest, "application/json", sFinal, strlen(sFinal)) ||
|
||||||
|
!SteamWorks_SetHTTPRequestNetworkActivityTimeout(hRequest, 10) ||
|
||||||
|
!SteamWorks_SendHTTPRequest(hRequest))
|
||||||
|
{
|
||||||
|
LogError("Discord SteamWorks_CreateHTTPRequest failed.");
|
||||||
|
|
||||||
|
delete RequestJSON;
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//PrintToServer("[Discord_POST] Have allowances? [%s] | Is processing data? [%s]", g_iRatelimitRemaining > 0 ? "YES":"NO", g_bProcessingData?"YES":"NO");
|
||||||
|
g_arrQueuedMessages.PushString(sFinal);
|
||||||
|
g_arrQueuedMessages.PushString(sURL);
|
||||||
|
g_bProcessingData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete hRequest; //nonono
|
||||||
|
}
|
||||||
|
|
||||||
|
public int OnHTTPRequestCompleted(Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, JSONObject RequestJSON)
|
||||||
|
{
|
||||||
|
if (bFailure || !bRequestSuccessful || (eStatusCode != k_EHTTPStatusCode200OK && eStatusCode != k_EHTTPStatusCode204NoContent))
|
||||||
|
{
|
||||||
|
if (eStatusCode != k_EHTTPStatusCode429TooManyRequests)
|
||||||
|
LogError("Discord HTTP request failed: %d", eStatusCode);
|
||||||
|
|
||||||
|
if (eStatusCode == k_EHTTPStatusCode400BadRequest)
|
||||||
|
{
|
||||||
|
char sData[2048];
|
||||||
|
|
||||||
|
(view_as<JSONRootNode>(RequestJSON)).ToString(sData, sizeof(sData), 0);
|
||||||
|
|
||||||
|
LogError("Malformed request? Dumping request data:\n%s", sData);
|
||||||
|
}
|
||||||
|
else if (eStatusCode == k_EHTTPStatusCode429TooManyRequests)
|
||||||
|
{
|
||||||
|
g_iRatelimitRemaining = 0;
|
||||||
|
g_iRatelimitReset = GetTime() + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete RequestJSON;
|
||||||
|
delete hRequest;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iLastRatelimitRemaining = 0;
|
||||||
|
static int iLastRatelimitReset = 0;
|
||||||
|
char sTmp[32];
|
||||||
|
bool bHeaderExists = SteamWorks_GetHTTPResponseHeaderValue(hRequest, "x-ratelimit-remaining", sTmp, sizeof(sTmp));
|
||||||
|
|
||||||
|
if (!bHeaderExists)
|
||||||
|
LogError("x-ratelimit-remaining header value could not be retrieved");
|
||||||
|
|
||||||
|
int iRatelimitRemaining = StringToInt(sTmp);
|
||||||
|
|
||||||
|
bHeaderExists = SteamWorks_GetHTTPResponseHeaderValue(hRequest, "x-ratelimit-reset", sTmp, sizeof(sTmp));
|
||||||
|
|
||||||
|
if (!bHeaderExists)
|
||||||
|
LogError("x-ratelimit-reset header value could not be retrieved");
|
||||||
|
|
||||||
|
int iRatelimitReset = StringToInt(sTmp);
|
||||||
|
|
||||||
|
if (iRatelimitRemaining < iLastRatelimitRemaining || iRatelimitReset >= iLastRatelimitReset) //don't be fooled by different completion times
|
||||||
|
{
|
||||||
|
g_iRatelimitRemaining = iRatelimitRemaining;
|
||||||
|
g_iRatelimitReset = iRatelimitReset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PrintToServer("limit: %d | remaining: %d || reset %d - now %d", g_iRatelimitLimit, g_iRatelimitRemaining, g_iRatelimitReset, GetTime());
|
||||||
|
|
||||||
|
delete RequestJSON;
|
||||||
|
delete hRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
stock bool IsValidClient(int client)
|
||||||
|
{
|
||||||
|
return (client > 0 && client <= MaxClients && IsClientInGame(client));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnLogAction(Handle hSource, Identity ident, int client, int target, const char[] sMsg)
|
||||||
|
{
|
||||||
|
if (client <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((StrContains(sMsg, "sm_psay", false)!= -1) || (StrContains(sMsg, "sm_chat", false)!= -1))
|
||||||
|
return;// dont log sm_psay and sm_chat
|
||||||
|
|
||||||
|
char sFinal[256];
|
||||||
|
char sCurrentMap[32];
|
||||||
|
char sClientName[64];
|
||||||
|
|
||||||
|
GetCurrentMap(sCurrentMap, sizeof(sCurrentMap));
|
||||||
|
Format(sFinal, sizeof(sFinal), "[ %s ]```%s```", sCurrentMap, sMsg);
|
||||||
|
|
||||||
|
GetClientName(client, sClientName, sizeof(sClientName));
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ADMINLOGS_WEBHOOKURL, sFinal, true, sClientName, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ADMINLOGS_WEBHOOKURL, sFinal, true, sClientName, false, "", false);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action CommandListener_SmChat(int client, const char[] sCommand, int argc)
|
||||||
|
{
|
||||||
|
if (client <= 0)
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
char sText[256];
|
||||||
|
char sUsername[32];
|
||||||
|
|
||||||
|
GetCmdArgString(sText, sizeof(sText));
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ADMINCHAT_WEBHOOKURL, sText, true, sUsername, true, g_sAvatarURL[client]);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ADMINCHAT_WEBHOOKURL, sText, true, sUsername);
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action OnClientSayCommand(int client, const char[] sCommand, const char[] sArgs)
|
||||||
|
{
|
||||||
|
if (client <= 0 || !IsClientInGame(client) || BaseComm_IsClientGagged(client))
|
||||||
|
return Plugin_Continue;
|
||||||
|
|
||||||
|
char sFinal[256];
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
if (strcmp(sCommand, "say_team") == 0)
|
||||||
|
{
|
||||||
|
if (sArgs[0] == '@')
|
||||||
|
{
|
||||||
|
bool bAdmin = CheckCommandAccess(client, "", ADMFLAG_GENERIC, true);
|
||||||
|
Format(sFinal, sizeof(sFinal), "%s%s", bAdmin ? "" : "To Admins: ", sArgs[1]);
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ADMINCHAT_WEBHOOKURL, sFinal, true, sUsername, true, g_sAvatarURL[client]);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ADMINCHAT_WEBHOOKURL, sFinal, true, sUsername);
|
||||||
|
|
||||||
|
if (!bAdmin)
|
||||||
|
{
|
||||||
|
//g_iReplyTargetSerial = GetClientSerial(client);
|
||||||
|
//g_iReplyType = REPLYTYPE_CHAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sTeamName[32];
|
||||||
|
|
||||||
|
GetTeamName(GetClientTeam(client), sTeamName, sizeof(sTeamName));
|
||||||
|
Format(sFinal, sizeof(sFinal), "(%s) ", sTeamName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin_Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CallAdmin_OnReportPost(int client, int target, const char[] reason)
|
||||||
|
{
|
||||||
|
char sClientName[MAX_NAME_LENGTH];
|
||||||
|
char sClientID[21];
|
||||||
|
|
||||||
|
char sTargetName[MAX_NAME_LENGTH];
|
||||||
|
char sTargetID[21];
|
||||||
|
|
||||||
|
char sServerIP[16];
|
||||||
|
int serverPort;
|
||||||
|
char sServerName[128];
|
||||||
|
|
||||||
|
CallAdmin_GetHostIP(sServerIP, sizeof(sServerIP));
|
||||||
|
serverPort = CallAdmin_GetHostPort();
|
||||||
|
CallAdmin_GetHostName(sServerName, sizeof(sServerName));
|
||||||
|
|
||||||
|
// Reporter wasn't a real client (initiated by a module)
|
||||||
|
if (client == REPORTER_CONSOLE)
|
||||||
|
{
|
||||||
|
strcopy(sClientName, sizeof(sClientName), "Server/Console");
|
||||||
|
strcopy(sClientID, sizeof(sClientID), "Server/Console");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetClientName(client, sClientName, sizeof(sClientName));
|
||||||
|
GetClientAuthId(client, AuthId_Steam2, sClientID, sizeof(sClientID));
|
||||||
|
}
|
||||||
|
|
||||||
|
GetClientName(target, sTargetName, sizeof(sTargetName));
|
||||||
|
GetClientAuthId(target, AuthId_Steam2, sTargetID, sizeof(sTargetID));
|
||||||
|
|
||||||
|
g_iLastReportID = CallAdmin_GetReportID();
|
||||||
|
|
||||||
|
char currentMap[64];
|
||||||
|
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||||
|
|
||||||
|
char sMessage[4096];
|
||||||
|
Format(sMessage, sizeof(sMessage), "@here\n```%s - Tick: %d``````New report on server: %s (%s:%d)\nReportID: %d\nReporter: %s (%s)\nTarget: %s (%s)\nReason: %s\nJoin Server: steam://connect/%s:%d\nwhen in game, type !calladmin_handle %d or /calladmin_handle %d in chat to handle this report```", currentMap, GetGameTickCount(), sServerName, sServerIP, serverPort, g_iLastReportID, sClientName, sClientID, sTargetName, sTargetID, reason, sServerIP, serverPort, g_iLastReportID, g_iLastReportID);
|
||||||
|
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_CALLADMIN_WEBHOOKURL, sMessage, true, sUsername, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_CALLADMIN_WEBHOOKURL, sMessage, true, sUsername, false, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CallAdmin_OnReportHandled(int client, int id)
|
||||||
|
{
|
||||||
|
if (id != g_iLastReportID)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char sMessage[1024];
|
||||||
|
Format(sMessage, sizeof(sMessage), "```Last report (%d) was handled by: %N```", g_iLastReportID, client);
|
||||||
|
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_CALLADMIN_WEBHOOKURL, sMessage, true, sUsername, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_CALLADMIN_WEBHOOKURL, sMessage, true, sUsername, false, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AntiBhopCheat_OnClientDetected(int client, char[] sReason, char[] sStats)
|
||||||
|
{
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
char currentMap[64];
|
||||||
|
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||||
|
|
||||||
|
char sMessage[4096];
|
||||||
|
Format(sMessage, sizeof(sMessage), "```%s - Tick: %d``````%s\n%s```", currentMap, GetGameTickCount(), sReason, sStats);
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ANTIBHOPCHEAT_WEBHOOKURL, sMessage, true, sUsername, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ANTIBHOPCHEAT_WEBHOOKURL, sMessage, true, sUsername, false, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entWatch_OnClientBanned(int admin, int iLenght, int client)
|
||||||
|
{
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
char currentMap[64];
|
||||||
|
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||||
|
|
||||||
|
char sMessageTmp[4096];
|
||||||
|
|
||||||
|
if (iLenght == 0)
|
||||||
|
{
|
||||||
|
Format(sMessageTmp, sizeof(sMessageTmp), "%L got temporarily restricted by %L", client, admin);
|
||||||
|
}
|
||||||
|
else if (iLenght == -1)
|
||||||
|
{
|
||||||
|
Format(sMessageTmp, sizeof(sMessageTmp), "%L got PERMANENTLY restricted by %L", client, admin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Format(sMessageTmp, sizeof(sMessageTmp), "%L got restricted by %L for %d minutes", client, admin, iLenght);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char sMessage[4096];
|
||||||
|
Format(sMessage, sizeof(sMessage), "```%s - Tick: %d``````%s```", currentMap, GetGameTickCount(), sMessageTmp);
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ENTWATCH_WEBHOOKURL, sMessage, true, sUsername, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ENTWATCH_WEBHOOKURL, sMessage, true, sUsername, false, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int entWatch_OnClientUnbanned(int admin, int client)
|
||||||
|
{
|
||||||
|
char sUsername[MAX_NAME_LENGTH];
|
||||||
|
GetClientName(client, sUsername, sizeof(sUsername));
|
||||||
|
|
||||||
|
char currentMap[64];
|
||||||
|
GetCurrentMap(currentMap, sizeof(currentMap));
|
||||||
|
|
||||||
|
char sMessageTmp[4096];
|
||||||
|
Format(sMessageTmp, sizeof(sMessageTmp), "%L got unrestricted by %L", client, admin);
|
||||||
|
|
||||||
|
char sMessage[4096];
|
||||||
|
Format(sMessage, sizeof(sMessage), "```%s - Tick: %d``````%s```", currentMap, GetGameTickCount(), sMessageTmp);
|
||||||
|
|
||||||
|
if (g_sAvatarURL[client][0] != '\0')
|
||||||
|
Discord_POST(DISCORD_ENTWATCH_WEBHOOKURL, sMessage, true, sUsername, true, g_sAvatarURL[client], false);
|
||||||
|
else
|
||||||
|
Discord_POST(DISCORD_ENTWATCH_WEBHOOKURL, sMessage, true, sUsername, false, "", false);
|
||||||
|
}
|
6
includes/AntiBhopCheat.inc
Normal file
6
includes/AntiBhopCheat.inc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#if defined _AntiBhopCheat_Included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _AntiBhopCheat_Included
|
||||||
|
|
||||||
|
forward void AntiBhopCheat_OnClientDetected(int client, char[] sReason, char[] sStats);
|
289
includes/calladmin.inc
Normal file
289
includes/calladmin.inc
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/** Include guard */
|
||||||
|
#if defined _calladmin_included
|
||||||
|
#endinput
|
||||||
|
#endif
|
||||||
|
#define _calladmin_included
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Global calladmin version, do not change */
|
||||||
|
#define CALLADMIN_VERSION "0.1.5"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Pass this as a clientindex to the ReportPlayer native if you don't have a client, eg report from server automatically */
|
||||||
|
#define REPORTER_CONSOLE 0
|
||||||
|
|
||||||
|
|
||||||
|
/** Maximum size a reason string can be in length */
|
||||||
|
#define REASON_MAX_LENGTH 128
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the main CallAdmin client selection menu is about to be drawn for a client.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
|
||||||
|
*/
|
||||||
|
forward Action CallAdmin_OnDrawMenu(int client);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the own reason selection is enabled and the select item for it is about to be drawn for a client.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
|
||||||
|
*/
|
||||||
|
forward Action CallAdmin_OnDrawOwnReason(int client);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a target is about to be drawn to the target selection menu for a client.
|
||||||
|
* Note: Called *n-1 times for the client selection menu where n is the amount of valid targets including the caller.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @param target Client index of the target about to be drawed.
|
||||||
|
* @return Plugin_Continue to allow the target to be drawn, Plugin_Handled otherwise.
|
||||||
|
*/
|
||||||
|
forward Action CallAdmin_OnDrawTarget(int client, int target);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the trackercount was changed.
|
||||||
|
*
|
||||||
|
* @param oldVal Trackercount before update.
|
||||||
|
* @param newVal Trackercount after update.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnTrackerCountChanged(int oldVal, int newVal);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before a client (or module) has reported another client.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @param target Client index of the target.
|
||||||
|
* @param reason Reason selected by the client for the report.
|
||||||
|
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
|
||||||
|
*/
|
||||||
|
forward Action CallAdmin_OnReportPre(int client, int target, const char[] reason);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after a client (or module) has reported another client.
|
||||||
|
* Be sure to check that client != REPORTER_CONSOLE if you expect a valid client index.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @param target Client index of the target.
|
||||||
|
* @param reason Reason selected by the client for the report.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnReportPost(int client, int target, const char[] reason);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates an report call.
|
||||||
|
* If you report automatically (via a module for example) set the clientindex to REPORTER_CONSOLE.
|
||||||
|
*
|
||||||
|
* @param client Client index of the caller.
|
||||||
|
* @param target Client index of the target.
|
||||||
|
* @param reason Reason for the report.
|
||||||
|
* @return True if target could be reported, false otherwise.
|
||||||
|
*/
|
||||||
|
native bool CallAdmin_ReportClient(int client, int target, const char[] reason);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an admin is about to be added to the in-game admin count.
|
||||||
|
*
|
||||||
|
* @param client Client index of the admin.
|
||||||
|
* @return Plugin_Continue to allow, Plugin_Handled otherwise.
|
||||||
|
*/
|
||||||
|
forward Action CallAdmin_OnAddToAdminCount(int client);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cached count of current trackers.
|
||||||
|
*
|
||||||
|
* @return Count of current trackers.
|
||||||
|
*/
|
||||||
|
native int CallAdmin_GetTrackersCount();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests a forced refresh of the trackers count.
|
||||||
|
* Note that most modules work asynchronous and only return their own cached count.
|
||||||
|
*
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native void CallAdmin_RequestTrackersCountRefresh();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the trackercount of a module is requested.
|
||||||
|
* This is either called periodically via the base calladmin, or when RequestTrackersCountRefresh is invoked.
|
||||||
|
*
|
||||||
|
* @param trackers By ref value of your trackers.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnRequestTrackersCountRefresh(int &trackers);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum ServerData
|
||||||
|
{
|
||||||
|
ServerData_HostName, /**< This is the hostname of the server, gathered from the `hostname` convar */
|
||||||
|
ServerData_HostIP, /**< This is the hostip of the server, gathered and converted from the `hostip` convar */
|
||||||
|
ServerData_HostPort /**< This is the hostport of the server, gathered from the `hostport` convar */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the serverdata data is changed.
|
||||||
|
*
|
||||||
|
* @param convar Handle to the convar which was changed.
|
||||||
|
* @param type Type of data which was changed.
|
||||||
|
* @param oldVal Value of data before change.
|
||||||
|
* @param newVal Value of data after change.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnServerDataChanged(ConVar convar, ServerData type, const char[] oldVal, const char[] newVal);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server's hostname.
|
||||||
|
*
|
||||||
|
* @param buffer String to copy hostname to.
|
||||||
|
* @param max_size Maximum size of buffer.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native void CallAdmin_GetHostName(char[] buffer, int max_size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server's IP String.
|
||||||
|
*
|
||||||
|
* @param buffer String to copy hostip to.
|
||||||
|
* @param max_size Maximum size of buffer.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native void CallAdmin_GetHostIP(char[] buffer, int max_size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server's HostPort.
|
||||||
|
*
|
||||||
|
* @return Hostport.
|
||||||
|
*/
|
||||||
|
native int CallAdmin_GetHostPort();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message to the calladmin logfile.
|
||||||
|
* The message has this format "[Pluginname] Message", where the plugin name is detected automatically.
|
||||||
|
*
|
||||||
|
* @param format Formatting rules.
|
||||||
|
* @param ... Variable number of format parameters.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native void CallAdmin_LogMessage(const char[] format, any ...);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a message was logged to the calladmin logfile.
|
||||||
|
*
|
||||||
|
* @param plugin Handle to the plugin which logged a message.
|
||||||
|
* @param message Message which was logged.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnLogMessage(Handle plugin, const char[] message);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the server's current report id.
|
||||||
|
* This is a temporary value and is increased with each report.
|
||||||
|
*
|
||||||
|
* @return Current report id of the server.
|
||||||
|
*/
|
||||||
|
native int CallAdmin_GetReportID();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a report was handled.
|
||||||
|
*
|
||||||
|
* @param client Admin who handled the report.
|
||||||
|
* @param id ID of the handled report.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
forward void CallAdmin_OnReportHandled(int client, int id);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Do not edit below this line */
|
||||||
|
public SharedPlugin __pl_calladmin =
|
||||||
|
{
|
||||||
|
name = "calladmin",
|
||||||
|
file = "calladmin.smx",
|
||||||
|
#if defined REQUIRE_PLUGIN
|
||||||
|
required = 1,
|
||||||
|
#else
|
||||||
|
required = 0,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined REQUIRE_PLUGIN
|
||||||
|
public __pl_calladmin_SetNTVOptional()
|
||||||
|
{
|
||||||
|
MarkNativeAsOptional("CallAdmin_GetTrackersCount");
|
||||||
|
MarkNativeAsOptional("CallAdmin_RequestTrackersCountRefresh");
|
||||||
|
MarkNativeAsOptional("CallAdmin_GetHostName");
|
||||||
|
MarkNativeAsOptional("CallAdmin_GetHostIP");
|
||||||
|
MarkNativeAsOptional("CallAdmin_GetHostPort");
|
||||||
|
MarkNativeAsOptional("CallAdmin_ReportClient");
|
||||||
|
MarkNativeAsOptional("CallAdmin_LogMessage");
|
||||||
|
MarkNativeAsOptional("CallAdmin_GetReportID");
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user