404 lines
12 KiB
SourcePawn
404 lines
12 KiB
SourcePawn
//====================================================================================================
|
|
//
|
|
// Name: UNLOZE Forum Integration.
|
|
// Author: .George & zaCade (Original by Botox)
|
|
// Description: Handles forum access ingame.
|
|
//
|
|
//====================================================================================================
|
|
#include <sourcemod>
|
|
#include <ripext>
|
|
#include <unloze>
|
|
#include <UNLOZE.secret> //#define UNLOZE_APIKEY here
|
|
#include <cstrike>
|
|
|
|
#pragma newdecls required
|
|
|
|
/* STRINGS */
|
|
char G_sGroup[MAXPLAYERS+1][64];
|
|
char G_sName[MAXPLAYERS+1][32];
|
|
|
|
/* BOOLS */
|
|
bool G_bPreAdminChecked[MAXPLAYERS+1];
|
|
bool G_bResponseFailed[MAXPLAYERS+1];
|
|
bool G_bResponsePassed[MAXPLAYERS+1];
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public Plugin myinfo =
|
|
{
|
|
name = "UNLOZE Forum Integration",
|
|
author = ".George & zaCade (Original by Botox)",
|
|
description = "Handles forum access ingame",
|
|
version = "1.2.1"
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose: Late load
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnPluginStart()
|
|
{
|
|
|
|
/* Late load */
|
|
for(int client = 1; client <= MaxClients; client++)
|
|
{
|
|
if(IsClientConnected(client))
|
|
OnClientConnected(client);
|
|
|
|
if(IsClientAuthorized(client) && !IsFakeClient(client))
|
|
{
|
|
char sSteamID32[32];
|
|
if(GetClientAuthId(client, AuthId_Steam2, sSteamID32, sizeof(sSteamID32)))
|
|
OnClientAuthorized(client, sSteamID32);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
|
{
|
|
CreateNative("AsyncHasSteamIDReservedSlot", Native_AsyncHasSteamIDReservedSlot);
|
|
CreateNative("GetClientForumName", Native_GetClientForumName);
|
|
|
|
RegPluginLibrary("UNLOZE_ForumIntegration");
|
|
|
|
return APLRes_Success;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnRebuildAdminCache(AdminCachePart part)
|
|
{
|
|
if (part != AdminCache_Admins)
|
|
return;
|
|
|
|
CreateTimer(1.0, OnRebuildAdminCachePost, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public Action OnRebuildAdminCachePost(Handle hTimer)
|
|
{
|
|
for (int client = 1; client <= MaxClients; client++)
|
|
{
|
|
if(G_bResponsePassed[client] && G_bPreAdminChecked[client])
|
|
ApplyGroupFlags(client);
|
|
}
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnClientConnected(int client)
|
|
{
|
|
G_bPreAdminChecked[client] = false;
|
|
G_bResponseFailed[client] = false;
|
|
G_bResponsePassed[client] = false;
|
|
|
|
G_sGroup[client][0] = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnClientDisconnect(int client)
|
|
{
|
|
G_bPreAdminChecked[client] = false;
|
|
G_bResponseFailed[client] = false;
|
|
G_bResponsePassed[client] = false;
|
|
|
|
G_sGroup[client][0] = 0;
|
|
G_sName[client][0] = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnClientAuthorized(int client, const char[] sSteamID32)
|
|
{
|
|
if (IsFakeClient(client))
|
|
return;
|
|
char sSteamID64[32];
|
|
SteamID32toSteamID64(sSteamID32, sSteamID64, sizeof(sSteamID64));
|
|
|
|
char sRequest[256];
|
|
FormatEx(sRequest, sizeof(sRequest), "https://unloze.com/api/private_api.php?api_key=%s&steam_id=%s", UNLOZE_APIKEY, sSteamID64);
|
|
|
|
int iSerial = GetClientSerial(client);
|
|
|
|
char sPath[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, sPath, sizeof(sPath), "data/unloze_forum_%d.tmp", iSerial);
|
|
|
|
HTTPRequest hRequest = new HTTPRequest(sRequest);
|
|
hRequest.DownloadFile(sPath, OnClientAuthorized_OnDownloaded, iSerial);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose: ripexts HTTPResponse only exposes the body as decoded JSON, unlike
|
|
// SteamWorks' GetHTTPResponseBodyCallback which handed back a plain char[].
|
|
// Rather than change private_api.php's response format, we use
|
|
// HTTPRequest.DownloadFile() to write the raw "GROUP\r\nNAME" body to a temp
|
|
// file and parse it back exactly like the original SteamWorks version did.
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnClientAuthorized_OnDownloaded(HTTPStatus status, any iSerial)
|
|
{
|
|
char sPath[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, sPath, sizeof(sPath), "data/unloze_forum_%d.tmp", iSerial);
|
|
|
|
int client = GetClientFromSerial(iSerial);
|
|
|
|
if (!client) //Player disconnected.
|
|
{
|
|
DeleteFile(sPath);
|
|
return;
|
|
}
|
|
|
|
if (status != HTTPStatus_OK)
|
|
{
|
|
DeleteFile(sPath);
|
|
G_bResponseFailed[client] = true;
|
|
|
|
if (G_bPreAdminChecked[client])
|
|
NotifyPostAdminCheck(client);
|
|
|
|
return;
|
|
}
|
|
|
|
char sGroup[64], sName[32];
|
|
sGroup[0] = '\0';
|
|
sName[0] = '\0';
|
|
|
|
File hFile = OpenFile(sPath, "r");
|
|
if (hFile != null)
|
|
{
|
|
hFile.ReadLine(sGroup, sizeof(sGroup));
|
|
hFile.ReadLine(sName, sizeof(sName));
|
|
delete hFile;
|
|
}
|
|
DeleteFile(sPath);
|
|
|
|
TrimString(sGroup);
|
|
StripQuotes(sGroup);
|
|
TrimString(sName);
|
|
StripQuotes(sName);
|
|
|
|
LogMessage("reached sData with status 200: %s", sGroup);
|
|
|
|
if (strlen(sName) > 0)
|
|
strcopy(G_sName[client], sizeof(G_sName[]), sName);
|
|
|
|
if (!StrEqual(sGroup, "NOGROUP"))
|
|
{
|
|
strcopy(G_sGroup[client], sizeof(G_sGroup[]), sGroup);
|
|
|
|
G_bResponsePassed[client] = true;
|
|
|
|
if (G_bPreAdminChecked[client])
|
|
NotifyPostAdminCheck(client);
|
|
}
|
|
else
|
|
G_bResponseFailed[client] = true; //users with just a forum name did not pass the VIP check! so the response "failed" (but we store their forum name for later!)
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public Action OnClientPreAdminCheck(int client)
|
|
{
|
|
G_bPreAdminChecked[client] = true;
|
|
|
|
if (G_bResponsePassed[client] || G_bResponseFailed[client])
|
|
return Plugin_Continue;
|
|
|
|
RunAdminCacheChecks(client);
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void OnClientPostAdminFilter(int client)
|
|
{
|
|
ApplyGroupFlags(client);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
stock void ApplyGroupFlags(int client)
|
|
{
|
|
if (!G_bResponsePassed[client])
|
|
return;
|
|
|
|
AdminId AdmID;
|
|
GroupId GrpID;
|
|
|
|
if ((AdmID = GetUserAdmin(client)) == INVALID_ADMIN_ID)
|
|
{
|
|
LogMessage("Creating new admin for %L", client);
|
|
|
|
AdmID = CreateAdmin();
|
|
SetUserAdmin(client, AdmID, true);
|
|
}
|
|
|
|
|
|
if ((GrpID = FindAdmGroup(G_sGroup[client])) != INVALID_GROUP_ID)
|
|
{
|
|
if (AdminInheritGroup(AdmID, GrpID))
|
|
{
|
|
LogMessage("%L added to group %s", client, G_sGroup[client]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogMessage("%L group not found %s", client, G_sGroup[client]);
|
|
}
|
|
}
|
|
|
|
public int Native_GetClientForumName(Handle plugin, int numParams)
|
|
{
|
|
int len = GetNativeCell(2);
|
|
int client = GetNativeCell(1);
|
|
|
|
SetNativeString(2, G_sName[client], len+1);
|
|
return 0;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
public int Native_AsyncHasSteamIDReservedSlot(Handle plugin, int numParams)
|
|
{
|
|
char sSteamID32[32];
|
|
GetNativeString(1, sSteamID32, sizeof(sSteamID32));
|
|
|
|
Function callback; //https://github.com/alliedmodders/sourcepawn/issues/778
|
|
callback = GetNativeFunction(2);
|
|
|
|
any data;
|
|
data = GetNativeCell(3);
|
|
|
|
char sSteamID64[32];
|
|
SteamID32toSteamID64(sSteamID32, sSteamID64, sizeof(sSteamID64));
|
|
|
|
char sRequest[256];
|
|
FormatEx(sRequest, sizeof(sRequest), "https://unloze.com/api/private_api.php?api_key=%s&steam_id=%s", UNLOZE_APIKEY, sSteamID64);
|
|
|
|
DataPack hDataPack = new DataPack();
|
|
hDataPack.WriteString(sSteamID32);
|
|
hDataPack.WriteFunction(callback);
|
|
hDataPack.WriteCell(plugin);
|
|
hDataPack.WriteCell(data);
|
|
|
|
// The DataPack handle value is unique among currently-open handles, so it
|
|
// doubles as a collision-free key for the temp file this specific
|
|
// in-flight request will use.
|
|
char sPath[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, sPath, sizeof(sPath), "data/unloze_reslot_%d.tmp", view_as<int>(hDataPack));
|
|
|
|
HTTPRequest hRequest = new HTTPRequest(sRequest);
|
|
hRequest.DownloadFile(sPath, Native_AsyncHasSteamIDReservedSlot_OnDownloaded, hDataPack);
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose: same DownloadFile-to-tempfile approach as OnClientAuthorized_OnDownloaded
|
|
// above - keeps private_api.php's raw "GROUP\r\nNAME" text response untouched.
|
|
//----------------------------------------------------------------------------------------------------
|
|
public void Native_AsyncHasSteamIDReservedSlot_OnDownloaded(HTTPStatus status, DataPack hDataPack)
|
|
{
|
|
char sPath[PLATFORM_MAX_PATH];
|
|
BuildPath(Path_SM, sPath, sizeof(sPath), "data/unloze_reslot_%d.tmp", view_as<int>(hDataPack));
|
|
|
|
char sData[32] = "NOGROUP";
|
|
|
|
if (status == HTTPStatus_OK)
|
|
{
|
|
File hFile = OpenFile(sPath, "r");
|
|
if (hFile != null)
|
|
{
|
|
hFile.ReadLine(sData, sizeof(sData));
|
|
delete hFile;
|
|
}
|
|
}
|
|
DeleteFile(sPath);
|
|
|
|
hDataPack.Reset();
|
|
|
|
char sSteamID32[32];
|
|
hDataPack.ReadString(sSteamID32, sizeof(sSteamID32));
|
|
|
|
Function callback;
|
|
callback = hDataPack.ReadFunction();
|
|
|
|
Handle plugin;
|
|
plugin = hDataPack.ReadCell();
|
|
|
|
any data;
|
|
data = hDataPack.ReadCell();
|
|
|
|
char splitData[32];
|
|
|
|
TrimString(sData);
|
|
StripQuotes(sData);
|
|
|
|
SplitString(sData, "\r\n", splitData, sizeof(splitData));
|
|
|
|
int result;
|
|
if (StrEqual(splitData, "Game-Donator", false))
|
|
result = 1;
|
|
else
|
|
result = 0;
|
|
|
|
Call_StartFunction(plugin, callback);
|
|
Call_PushString(sSteamID32);
|
|
Call_PushCell(result);
|
|
Call_PushCell(data);
|
|
Call_Finish();
|
|
|
|
delete hDataPack;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
// Purpose:
|
|
//----------------------------------------------------------------------------------------------------
|
|
stock bool SteamID32toSteamID64(const char[] sSteamID32, char[] sSteamID64, int iSize)
|
|
{
|
|
if (strlen(sSteamID32) < 11 || strncmp(sSteamID32[0], "STEAM_", 6))
|
|
{
|
|
sSteamID64[0] = 0;
|
|
return false;
|
|
}
|
|
|
|
int iUpper = 765611979;
|
|
int isSteam64ID = StringToInt(sSteamID32[10]) * 2 + 60265728 + sSteamID32[8] - 48;
|
|
|
|
int iDiv = isSteam64ID / 100000000;
|
|
int iIdx = 9 - (iDiv ? (iDiv / 10 + 1) : 0);
|
|
|
|
iUpper += iDiv;
|
|
|
|
IntToString(isSteam64ID, sSteamID64[iIdx], iSize - iIdx);
|
|
iIdx = sSteamID64[9];
|
|
|
|
IntToString(iUpper, sSteamID64, iSize);
|
|
sSteamID64[9] = iIdx;
|
|
|
|
return true;
|
|
}
|
|
|
|
stock bool IsValidClient(int client)
|
|
{
|
|
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
|
return true;
|
|
return false;
|
|
}
|
|
|