#pragma semicolon 1
#define TABLE_NAME "amx_offline_bans"
#define LOG_PREFIX "Offline Bans"
#define BAN_CMD "fb_ban %d #%d ^"%s^""
#define MAX_REASON_LENGTH 32
#define LOAD_TIMEOUT 15.0
#define IGNORE_FLAG (ADMIN_BAN | ADMIN_LEVEL_H)
#include <amxmodx>
#include <sqlx>
#if !defined MAX_PLAYERS
#define MAX_PLAYERS 32
#endif
#if !defined MAX_NAME_LENGTH
#define MAX_NAME_LENGTH 32
#endif
forward fbans_sql_connected(Handle:sqlTuple);
new Handle:g_DBTuple;
new bool:g_Loaded = false;
enum _: BAN_DATA {
BAN_ID,
BAN_LENGTH,
BAN_REASON[MAX_REASON_LENGTH]
}
new Trie:g_BanList;
public plugin_init()
{
register_plugin("Offline Bans", "1.0.1", "F@nt0M");
register_concmd("amx_reloadofflinebans", "cmdReload", ADMIN_CFG);
}
public plugin_end()
{
if (g_BanList != Invalid_Trie) {
TrieDestroy(g_BanList);
}
}
public client_putinserver(id)
{
if (g_Loaded && !is_user_bot(id) && !is_user_hltv(id)) {
CheckPlayer(id);
}
}
public cmdReload(id, level)
{
if (~get_user_flags(id) & level) {
console_print(id, "You have no access to that command");
return PLUGIN_HANDLED;
}
DbLoad();
new name[MAX_NAME_LENGTH], authid[22], ip[16];
get_user_name(id, name, charsmax(name));
get_user_authid(id, authid, charsmax(authid));
get_user_ip(id, ip, charsmax(ip), 1);
log_amx("[%s] Admin <%s><%s><%s> run reload bans", LOG_PREFIX, name, authid, ip);
console_print(id, "[%s] Offline bans reloaded successfully", LOG_PREFIX);
return PLUGIN_HANDLED;
}
public fbans_sql_connected(Handle:sqlTuple)
{
g_Loaded = false;
g_DBTuple = sqlTuple;
#if defined LOAD_TIMEOUT
set_task(LOAD_TIMEOUT, "DbLoad");
#else
DbLoad();
#endif
}
public DbLoad()
{
if (g_DBTuple != Empty_Handle) {
new pquery[512];
formatex(pquery, charsmax(pquery), "SELECT id, authid, length, CONVERT(reason, BINARY) reason FROM %s WHERE banned != 1", TABLE_NAME);
SQL_ThreadQuery(g_DBTuple, "DBLoadPost", pquery);
} else {
log_amx("[%s] Bad tuple", LOG_PREFIX);
}
}
public DBLoadPost(failstate, Handle:query, const error[], errornum, const data[], size, Float:querytime)
{
if (failstate) {
SQL_Error(query, error, errornum, failstate);
} else if (SQL_NumResults(query) > 0) {
if (g_BanList == Invalid_Trie) {
g_BanList = TrieCreate();
} else {
TrieClear(g_BanList);
}
new authid[22];
new banData[BAN_DATA];
new num;
while (SQL_MoreResults(query)) {
setc(banData[BAN_REASON], sizeof banData[BAN_REASON], 0);
banData[BAN_ID] = SQL_ReadResult(query, 0);
SQL_ReadResult(query, 1, authid, charsmax(authid));
banData[BAN_LENGTH] = SQL_ReadResult(query, 2);
SQL_ReadResult(query, 3, banData[BAN_REASON], charsmax(banData[BAN_REASON]));
TrieSetArray(g_BanList, authid, banData, sizeof banData);
SQL_NextRow(query);
num++;
}
log_amx("[%s] Load %d bans", LOG_PREFIX, num);
CheckPlayers();
g_Loaded = true;
} else {
log_amx("[%s] Load 0 bans", LOG_PREFIX);
}
SQL_FreeHandle(query);
}
SQL_Error(Handle:query, const error[], errornum, failstate)
{
if (failstate == TQUERY_CONNECT_FAILED) {
log_amx("[%s] QueryConnection failed!", LOG_PREFIX);
log_amx("[%s] QueryMessage: %s (%d)", LOG_PREFIX, error, errornum);
} else if (failstate == TQUERY_QUERY_FAILED) {
new qstring[1024];
SQL_GetQueryString(query, qstring, 1023);
log_amx("[%s] Query failed!", LOG_PREFIX);
log_amx("[%s] QueryMessage: %s (%d)", LOG_PREFIX, error, errornum);
log_amx("[%s] QueryQuery statement: %s", LOG_PREFIX, qstring);
}
}
CheckPlayers()
{
new players[MAX_PLAYERS], num;
get_players(players, num, "ch");
for (new i = 0; i < num; i++) {
CheckPlayer(players[i]);
}
}
CheckPlayer(id)
{
if (g_BanList == Invalid_Trie) {
return 0;
}
#if defined IGNORE_FLAG
if ((get_user_flags(id) & IGNORE_FLAG) == IGNORE_FLAG) {
return 0;
}
#endif
new authid[22];
get_user_authid(id, authid, charsmax(authid));
if (!TrieKeyExists(g_BanList, authid)) {
return 0;
}
new banData[BAN_DATA];
TrieGetArray(g_BanList, authid, banData, sizeof banData);
BanPlayer(id, banData[BAN_ID], banData[BAN_LENGTH], banData[BAN_REASON]);
return 1;
}
BanPlayer(const id, const banId, const length, const reason[])
{
server_cmd(BAN_CMD, length, get_user_userid(id), reason);
if (g_DBTuple != Empty_Handle) {
new pquery[512];
formatex(pquery, charsmax(pquery), "UPDATE %s SET banned = 1 WHERE id = %d LIMIT 1", TABLE_NAME, banId);
SQL_ThreadQuery(g_DBTuple, "QueryIngnoredHandle", pquery);
} else {
log_amx("[%s] Bad tuple", LOG_PREFIX);
}
}
public QueryIngnoredHandle(failstate, Handle:query, const error[], errornum, const data[], size, Float:querytime)
{
if (failstate) {
SQL_Error(query, error, errornum, failstate);
}
SQL_FreeHandle(query);
}