Files
sm-plugins/Leader3/scripting/leader3/whitelist.sp
T
2026-10-22 16:17:56 +01:00

372 lines
11 KiB
SourcePawn

//----------------------------------------------------------------------------------------------------
// Leader3 whitelist: players allowed to self-assign leader without a vote or admin flags.
// Stored in the SourceMod database ("sourcemod" config when defined, else storage-local).
//----------------------------------------------------------------------------------------------------
void Whitelist_OnPluginStart()
{
char conf[64];
strcopy(conf, sizeof(conf), SQL_CheckConfig("sourcemod") ? "sourcemod" : "storage-local");
Database.Connect(Whitelist_OnDBConnected, conf);
}
public void Whitelist_OnDBConnected(Database db, const char[] error, any data)
{
if (db == null)
{
LogError("[Leader3] Whitelist database connection failed: %s", error);
return;
}
g_hWhitelistDB = db;
g_hWhitelistDB.SetCharset("utf8");
g_hWhitelistDB.Query(Whitelist_OnTableCreated,
"CREATE TABLE IF NOT EXISTS leader_whitelist ("
... "steam_id VARCHAR(32) NOT NULL PRIMARY KEY, "
... "name VARCHAR(64) NOT NULL DEFAULT '', "
... "added_by VARCHAR(96) NOT NULL DEFAULT '', "
... "added_at INTEGER NOT NULL DEFAULT 0)");
}
public void Whitelist_OnTableCreated(Database db, DBResultSet results, const char[] error, any data)
{
if (results == null)
{
LogError("[Leader3] Failed to create leader_whitelist table: %s", error);
delete g_hWhitelistDB;
return;
}
// Late load / slow connect: check everyone already on.
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i) && IsClientAuthorized(i))
Whitelist_CheckClient(i);
}
}
void Whitelist_CheckClient(int client)
{
g_bLeaderWhitelisted[client] = false;
char auth[32];
if (g_hWhitelistDB == null || IsFakeClient(client) || !GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth)))
return;
char query[128];
g_hWhitelistDB.Format(query, sizeof(query), "SELECT 1 FROM leader_whitelist WHERE steam_id = '%s'", auth);
g_hWhitelistDB.Query(Whitelist_OnCheckDone, query, GetClientUserId(client));
}
public void Whitelist_OnCheckDone(Database db, DBResultSet results, const char[] error, any userid)
{
if (results == null)
{
LogError("[Leader3] Whitelist lookup failed: %s", error);
return;
}
int client = GetClientOfUserId(userid);
if (client > 0)
g_bLeaderWhitelisted[client] = results.FetchRow();
}
bool Whitelist_IsWhitelisted(int client)
{
return client >= 1 && client <= MaxClients && g_bLeaderWhitelisted[client];
}
void Whitelist_Add(int admin, int target)
{
if (g_hWhitelistDB == null)
{
ReplyToCommand(admin, "%s The whitelist database is not available.", PREFIX_PLAIN);
return;
}
char auth[32];
if (!GetClientAuthId(target, AuthId_Steam2, auth, sizeof(auth)))
{
ReplyToCommand(admin, "%s %N is not authorized with Steam yet, try again shortly.", PREFIX_PLAIN, target);
return;
}
if (g_bLeaderWhitelisted[target])
{
ReplyToCommand(admin, "%s %N is already on the leader whitelist.", PREFIX_PLAIN, target);
return;
}
char name[MAX_NAME_LENGTH], adminAuth[96];
GetClientName(target, name, sizeof(name));
if (admin > 0)
GetClientAuthId(admin, AuthId_Steam2, adminAuth, sizeof(adminAuth));
else
strcopy(adminAuth, sizeof(adminAuth), "CONSOLE");
char query[512];
g_hWhitelistDB.Format(query, sizeof(query),
"REPLACE INTO leader_whitelist (steam_id, name, added_by, added_at) VALUES ('%s', '%s', '%s', %d)",
auth, name, adminAuth, GetTime());
g_hWhitelistDB.Query(Whitelist_OnWriteDone, query);
g_bLeaderWhitelisted[target] = true;
ReplyToCommand(admin, "%s Added %N (%s) to the leader whitelist.", PREFIX_PLAIN, target, auth);
PrintToChat(target, "%sYou are now on the \x04leader whitelist\x01! Type \x04!leader\x01 to lead at any time.", PREFIX);
LogAction(admin, target, "\"%L\" added \"%L\" to the leader whitelist", admin, target);
}
// Normalize a typed SteamID to canonical upper-case Steam2 form (STEAM_X:Y:Z).
// The steam_id column comparison is case-sensitive, so lower-case input must not reach the DB.
static bool Whitelist_NormalizeSteam2(const char[] input, char[] auth, int maxlen)
{
strcopy(auth, maxlen, input);
for (int i = 0; auth[i] != '\0'; i++)
auth[i] = CharToUpper(auth[i]);
if (StrContains(auth, "STEAM_", true) != 0)
return false;
if (!IsCharNumeric(auth[6]) || auth[7] != ':' || (auth[8] != '0' && auth[8] != '1') || auth[9] != ':' || !IsCharNumeric(auth[10]))
return false;
for (int i = 11; auth[i] != '\0'; i++)
{
if (!IsCharNumeric(auth[i]))
return false;
}
return true;
}
// Add a possibly offline player by SteamID (sm_addleaderwhitelist STEAM_0:X:XXXX [name]).
void Whitelist_AddAuth(int admin, const char[] authArg, const char[] name)
{
if (g_hWhitelistDB == null)
{
ReplyToCommand(admin, "%s The whitelist database is not available.", PREFIX_PLAIN);
return;
}
char auth[32];
if (!Whitelist_NormalizeSteam2(authArg, auth, sizeof(auth)))
{
ReplyToCommand(admin, "%s '%s' is not a valid SteamID (expected STEAM_0:X:XXXX).", PREFIX_PLAIN, authArg);
return;
}
char adminAuth[96];
if (admin > 0)
GetClientAuthId(admin, AuthId_Steam2, adminAuth, sizeof(adminAuth));
else
strcopy(adminAuth, sizeof(adminAuth), "CONSOLE");
char query[512];
g_hWhitelistDB.Format(query, sizeof(query),
"REPLACE INTO leader_whitelist (steam_id, name, added_by, added_at) VALUES ('%s', '%s', '%s', %d)",
auth, name, adminAuth, GetTime());
g_hWhitelistDB.Query(Whitelist_OnWriteDone, query);
// Update the cache should that player be connected under this ID.
char clientAuth[32];
for (int i = 1; i <= MaxClients; i++)
{
if (!g_bLeaderWhitelisted[i] && IsClientInGame(i) && !IsFakeClient(i)
&& GetClientAuthId(i, AuthId_Steam2, clientAuth, sizeof(clientAuth))
&& StrEqual(auth, clientAuth))
{
g_bLeaderWhitelisted[i] = true;
PrintToChat(i, "%sYou are now on the \x04leader whitelist\x01! Type \x04!leader\x01 to lead at any time.", PREFIX);
}
}
ReplyToCommand(admin, "%s Added %s to the leader whitelist.", PREFIX_PLAIN, auth);
LogAction(admin, -1, "\"%L\" added \"%s\" to the leader whitelist", admin, auth);
}
// Remove a connected client from the whitelist. Returns true if they were on it.
bool Whitelist_Remove(int admin, int target)
{
if (!g_bLeaderWhitelisted[target])
return false;
g_bLeaderWhitelisted[target] = false;
char auth[32];
if (GetClientAuthId(target, AuthId_Steam2, auth, sizeof(auth)))
Whitelist_DeleteAuth(auth);
ReplyToCommand(admin, "%s Removed %N from the leader whitelist.", PREFIX_PLAIN, target);
LogAction(admin, target, "\"%L\" removed \"%L\" from the leader whitelist", admin, target);
return true;
}
// Remove an offline player by SteamID (sm_removeleaderwhitelist STEAM_0:X:XXXX).
void Whitelist_RemoveAuth(int admin, const char[] authArg)
{
if (g_hWhitelistDB == null)
{
ReplyToCommand(admin, "%s The whitelist database is not available.", PREFIX_PLAIN);
return;
}
char auth[32];
if (!Whitelist_NormalizeSteam2(authArg, auth, sizeof(auth)))
{
ReplyToCommand(admin, "%s '%s' is not a valid SteamID (expected STEAM_0:X:XXXX).", PREFIX_PLAIN, authArg);
return;
}
Whitelist_DeleteAuth(auth);
// Clear the cache should that player be connected under this ID.
char clientAuth[32];
for (int i = 1; i <= MaxClients; i++)
{
if (g_bLeaderWhitelisted[i] && IsClientInGame(i)
&& GetClientAuthId(i, AuthId_Steam2, clientAuth, sizeof(clientAuth))
&& StrEqual(auth, clientAuth))
{
g_bLeaderWhitelisted[i] = false;
}
}
ReplyToCommand(admin, "%s Removed %s from the leader whitelist (if present).", PREFIX_PLAIN, auth);
LogAction(admin, -1, "\"%L\" removed \"%s\" from the leader whitelist", admin, auth);
}
void Whitelist_DeleteAuth(const char[] auth)
{
if (g_hWhitelistDB == null)
return;
char query[128];
g_hWhitelistDB.Format(query, sizeof(query), "DELETE FROM leader_whitelist WHERE steam_id = '%s'", auth);
g_hWhitelistDB.Query(Whitelist_OnWriteDone, query);
}
public void Whitelist_OnWriteDone(Database db, DBResultSet results, const char[] error, any data)
{
if (results == null)
LogError("[Leader3] Whitelist write failed: %s", error);
}
//----------------------------------------------------------------------------------------------------
// Commands
//----------------------------------------------------------------------------------------------------
public Action Cmd_AddLeaderWhitelist(int client, int args)
{
if (args < 1)
{
ReplyToCommand(client, "%s Usage: sm_addleaderwhitelist <target|steamid> [name] - adds a player to the leader whitelist.", PREFIX_PLAIN);
return Plugin_Handled;
}
char arg[65], targetName[MAX_TARGET_LENGTH];
int targets[MAXPLAYERS];
bool tnIsMl;
GetCmdArg(1, arg, sizeof(arg));
int count = ProcessTargetString(arg, client, targets, sizeof(targets),
COMMAND_FILTER_CONNECTED | COMMAND_FILTER_NO_BOTS, targetName, sizeof(targetName), tnIsMl);
if (count <= 0)
{
// Offline whitelist add by SteamID.
if (StrContains(arg, "STEAM_", false) == 0)
{
char name[MAX_NAME_LENGTH];
if (args >= 2)
GetCmdArg(2, name, sizeof(name));
Whitelist_AddAuth(client, arg, name);
return Plugin_Handled;
}
ReplyToTargetError(client, count);
return Plugin_Handled;
}
for (int i = 0; i < count; i++)
Whitelist_Add(client, targets[i]);
return Plugin_Handled;
}
public Action Cmd_RemoveLeaderWhitelist(int client, int args)
{
if (args < 1)
{
ReplyToCommand(client, "%s Usage: sm_removeleaderwhitelist <target|steamid> - removes a player from the leader whitelist.", PREFIX_PLAIN);
return Plugin_Handled;
}
char arg[65], targetName[MAX_TARGET_LENGTH];
int targets[MAXPLAYERS];
bool tnIsMl;
GetCmdArg(1, arg, sizeof(arg));
int count = ProcessTargetString(arg, client, targets, sizeof(targets),
COMMAND_FILTER_CONNECTED | COMMAND_FILTER_NO_BOTS, targetName, sizeof(targetName), tnIsMl);
if (count <= 0)
{
// Offline whitelist removal by SteamID.
if (StrContains(arg, "STEAM_", false) == 0)
{
Whitelist_RemoveAuth(client, arg);
return Plugin_Handled;
}
ReplyToTargetError(client, count);
return Plugin_Handled;
}
for (int i = 0; i < count; i++)
{
if (!Whitelist_Remove(client, targets[i]))
ReplyToCommand(client, "%s %N is not on the leader whitelist.", PREFIX_PLAIN, targets[i]);
}
return Plugin_Handled;
}
public Action Cmd_LeaderWhitelist(int client, int args)
{
if (g_hWhitelistDB == null)
{
ReplyToCommand(client, "%s The whitelist database is not available.", PREFIX_PLAIN);
return Plugin_Handled;
}
g_hWhitelistDB.Query(Whitelist_OnListDone,
"SELECT steam_id, name FROM leader_whitelist ORDER BY added_at DESC",
client > 0 ? GetClientUserId(client) : 0);
return Plugin_Handled;
}
public void Whitelist_OnListDone(Database db, DBResultSet results, const char[] error, any userid)
{
int client = (userid == 0) ? 0 : GetClientOfUserId(userid);
if (userid != 0 && client == 0)
return;
if (results == null)
{
LogError("[Leader3] Whitelist listing failed: %s", error);
ReplyToCommand(client, "%s Failed to read the leader whitelist.", PREFIX_PLAIN);
return;
}
if (results.RowCount == 0)
{
ReplyToCommand(client, "%s The leader whitelist is empty.", PREFIX_PLAIN);
return;
}
ReplyToCommand(client, "%s Leader whitelist (%d):", PREFIX_PLAIN, results.RowCount);
char auth[32], name[MAX_NAME_LENGTH];
while (results.FetchRow())
{
results.FetchString(0, auth, sizeof(auth));
results.FetchString(1, name, sizeof(name));
ReplyToCommand(client, " %s - %s", auth, name);
}
}