2023-02-02 00:19:27 +01:00
# pragma semicolon 1
# define PLUGIN_AUTHOR "jenz"
# define g_dLength 400
2023-08-04 23:34:50 +02:00
# define PLUGIN_VERSION "1.1"
2023-02-02 00:19:27 +01:00
# pragma newdecls required
# include <sourcemod>
2023-02-14 21:29:45 +01:00
# include <sourcebanspp>
2023-02-02 00:19:27 +01:00
# include <clientprefs>
# include <cstrike>
# include <sdktools>
Database g_dDatabase ;
2023-08-04 23:34:50 +02:00
int g_disable_html_motd [ MAXPLAYERS + 1 ] ;
2023-02-03 11:38:47 +01:00
Handle g_hOnReportBanPostForward ;
2023-02-02 00:19:27 +01:00
public Plugin myinfo =
{
name = " jenz ban detector " ,
author = PLUGIN_AUTHOR ,
description = " my ban detector maybe catches you " ,
version = PLUGIN_VERSION ,
url = " www.unloze.com "
} ;
2023-02-03 11:38:47 +01:00
public APLRes AskPluginLoad2 ( Handle myself , bool late , char [ ] error , int err_max )
{
RegPluginLibrary ( " jenz_ban_detector " ) ;
return APLRes_Success ;
}
2023-02-02 00:19:27 +01:00
public void OnPluginStart ( )
{
2023-02-03 11:38:47 +01:00
g_hOnReportBanPostForward = CreateGlobalForward ( " BanDetectorPost " , ET_Ignore , Param_Cell , Param_String ) ;
2023-02-02 00:19:27 +01:00
if ( ! g_dDatabase )
{
Database . Connect ( SQL_OnDatabaseConnect , " jenz_ban_detector " ) ;
}
2023-08-01 22:15:35 +02:00
}
public void OnMapStart ( )
{
if ( ! g_dDatabase )
2023-02-02 00:19:27 +01:00
{
2023-08-01 22:15:35 +02:00
Database . Connect ( SQL_OnDatabaseConnect , " jenz_ban_detector " ) ;
}
}
public void SQL_OnDatabaseConnect ( Database db , const char [ ] error , any data )
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Database error: %s " , error ) ;
return ;
}
g_dDatabase = db ;
}
2023-08-04 23:34:50 +02:00
public void OnClientDisconnect ( int client )
{
g_disable_html_motd [ client ] = 0 ;
}
2023-08-01 22:15:35 +02:00
public void OnClientPostAdminCheck ( int client )
{
2023-08-04 23:34:50 +02:00
g_disable_html_motd [ client ] = 0 ;
2023-08-01 22:15:35 +02:00
if ( ! IsFakeClient ( client ) & & ! IsClientSourceTV ( client ) )
{
SQL_addEntry ( client ) ;
2023-08-04 23:34:50 +02:00
}
}
public void SQL_addEntry ( int client )
{
char sQuery [ g_dLength ] ;
char sSID [ MAX_NAME_LENGTH ] ;
char sIP [ MAX_NAME_LENGTH ] ;
char sName [ MAX_NAME_LENGTH ] ;
GetClientName ( client , sName , sizeof ( sName ) ) ;
int size2 = 2 * strlen ( sName ) + 1 ;
char [ ] sEscapedName = new char [ size2 + 1 ] ;
GetClientAuthId ( client , AuthId_Steam2 , sSID , sizeof ( sSID ) ) ;
g_dDatabase . Escape ( sName , sEscapedName , size2 + 1 ) ;
GetClientIP ( client , sIP , sizeof ( sIP ) ) ;
Format ( sQuery , sizeof ( sQuery ) , " insert ignore into `ban_detector` (`steamid`, `ip`, `name`) SELECT '%s', '%s','%s' " , sSID , sIP , sEscapedName ) ;
g_dDatabase . Query ( SQL_callback_insert_ignore , sQuery , GetClientSerial ( client ) , DBPrio_Low ) ;
}
public void SQL_callback_insert_ignore ( Database db , DBResultSet results , const char [ ] error , int Serial )
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Database error: %s " , error ) ;
delete results ;
return ;
}
delete results ;
int client ;
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
return ;
}
if ( IsValidClient ( client ) )
{
2023-08-01 23:49:29 +02:00
QueryClientConVar ( client , " cl_disablehtmlmotd " , CvarQueryFinished ) ;
2023-02-02 00:19:27 +01:00
}
}
2023-08-01 23:49:29 +02:00
public void CvarQueryFinished ( QueryCookie cookie , int client , ConVarQueryResult res , const char [ ] sCvarName , const char [ ] sCvarVal )
{
if ( res ! = ConVarQuery_Okay )
{
return ;
}
int disable_html_motd = StringToInt ( sCvarVal ) ;
if ( IsValidClient ( client ) )
{
2023-08-04 23:34:50 +02:00
g_disable_html_motd [ client ] = disable_html_motd ;
2023-08-01 23:49:29 +02:00
char sQuery [ g_dLength ] ;
char sSID [ MAX_NAME_LENGTH ] ;
GetClientAuthId ( client , AuthId_Steam2 , sSID , sizeof ( sSID ) ) ;
Format ( sQuery , sizeof ( sQuery ) , " UPDATE ban_detector SET last_connect = now(), disable_html_motd = '%i' where steamid = '%s' " , disable_html_motd , sSID ) ;
2023-08-04 23:34:50 +02:00
g_dDatabase . Query ( SQL_callback_update , sQuery , GetClientSerial ( client ) , DBPrio_Low ) ;
2023-08-01 23:49:29 +02:00
}
}
2023-08-04 23:34:50 +02:00
public void SQL_callback_update ( Database db , DBResultSet results , const char [ ] error , int Serial )
2023-02-02 00:19:27 +01:00
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Database error: %s " , error ) ;
2023-04-30 12:14:28 +02:00
delete results ;
return ;
}
2023-08-01 22:15:35 +02:00
delete results ;
2023-08-04 23:34:50 +02:00
int client ;
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
return ;
}
if ( IsValidClient ( client ) & & ! g_disable_html_motd [ client ] )
2023-08-14 12:55:53 +02:00
{
CreateTimer ( 7.0 , re_open_motd , GetClientSerial ( client ) ) ;
}
}
public Action re_open_motd ( Handle hTimer , int Serial )
{
int client ;
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
2023-08-29 18:11:52 +02:00
return Plugin_Handled ;
2023-08-14 12:55:53 +02:00
}
if ( IsValidClient ( client ) )
2023-08-04 23:34:50 +02:00
{
//reopening the menu again after info got stored. it still generates the same fingerprint despite not showing the client any menu.
Handle panel = CreateKeyValues ( " data " ) ;
KvSetString ( panel , " title " , " " ) ;
KvSetString ( panel , " type " , " 2 " ) ;
KvSetString ( panel , " msg " , " https://unloze.com/motd/CSS_ZE_MOTD.html " ) ;
ShowVGUIPanel ( client , " info " , panel , false ) ;
CloseHandle ( panel ) ;
CreateTimer ( 5.0 , SQL_Select_fingerprints , GetClientSerial ( client ) ) ;
}
2023-08-29 18:11:52 +02:00
return Plugin_Handled ;
2023-08-01 22:15:35 +02:00
}
public Action SQL_Select_fingerprints ( Handle hTimer , int Serial )
{
int client ;
2023-04-30 12:14:28 +02:00
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
2023-08-29 18:11:52 +02:00
return Plugin_Handled ;
2023-02-02 00:19:27 +01:00
}
2023-02-03 01:44:45 +01:00
if ( IsValidClient ( client ) )
{
char sQuery [ g_dLength ] ;
char sSID [ MAX_NAME_LENGTH ] ;
2023-02-07 20:45:15 +01:00
char sIP [ MAX_NAME_LENGTH ] ;
GetClientIP ( client , sIP , sizeof ( sIP ) ) ;
2023-02-03 01:44:45 +01:00
GetClientAuthId ( client , AuthId_Steam2 , sSID , sizeof ( sSID ) ) ;
2023-08-01 22:15:35 +02:00
Format ( sQuery , sizeof ( sQuery ) , " select fingerprint from ban_detector.ban_detector where steamid = '%s' " , sSID ) ;
2023-02-03 01:44:45 +01:00
//PrintToChatAll("sQuery: %s", sQuery);
2023-04-30 12:14:28 +02:00
g_dDatabase . Query ( SQL_FindFingerPrints , sQuery , GetClientSerial ( client ) , DBPrio_Low ) ;
2023-02-03 01:44:45 +01:00
}
2023-08-29 18:11:52 +02:00
return Plugin_Handled ;
2023-02-03 01:44:45 +01:00
}
2023-04-30 12:14:28 +02:00
public void SQL_FindFingerPrints ( Database db , DBResultSet results , const char [ ] error , int Serial )
2023-02-03 01:44:45 +01:00
{
if ( ! db | | strlen ( error ) )
{
LogError ( " Database error: %s " , error ) ;
2023-04-30 12:14:28 +02:00
delete results ;
return ;
}
int client ;
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
delete results ;
return ;
}
if ( ! IsValidClient ( client ) )
{
delete results ;
2023-02-03 01:44:45 +01:00
return ;
}
2023-06-20 23:47:39 +02:00
2023-06-25 17:21:34 +02:00
//god knows how big this might need to be
char sQuery [ 4344 ] ;
2023-08-01 22:15:35 +02:00
//cant rely on IP cause several chinese players share VPN and end up with same IP despite clearly being different people.
Format ( sQuery , sizeof ( sQuery ) , " select sb.authid from ban_detector.ban_detector bd inner join unloze_sourceban.sb_bans sb on sb.authid = bd.steamid where fingerprint in ( " ) ;
2023-06-20 23:47:39 +02:00
bool first = true ;
2023-08-04 23:34:50 +02:00
//this is kinda obsolete now because it always just returns a single fingerprint. it was made for the intention of multiple fingerprints being returned.
//does not change that the IN clause still works, it will always just be a single element in the IN clause.
2023-02-07 20:45:15 +01:00
while ( results . RowCount > 0 & & results . FetchRow ( ) )
2023-02-03 01:44:45 +01:00
{
2023-06-20 23:47:39 +02:00
char fingerprint [ 1024 ] ;
2023-02-03 01:44:45 +01:00
results . FetchString ( 0 , fingerprint , sizeof ( fingerprint ) ) ;
char [ ] sEscapedFingerPrint = new char [ 1024 ] ;
g_dDatabase . Escape ( fingerprint , sEscapedFingerPrint , 1024 ) ;
2023-06-20 23:47:39 +02:00
if ( first )
{
Format ( sEscapedFingerPrint , 1024 , " '%s' " , sEscapedFingerPrint ) ;
}
else
2023-02-07 20:45:15 +01:00
{
2023-06-20 23:47:39 +02:00
Format ( sEscapedFingerPrint , 1024 , " ,'%s' " , sEscapedFingerPrint ) ;
2023-02-07 20:45:15 +01:00
}
2023-06-20 23:47:39 +02:00
StrCat ( sQuery , sizeof ( sQuery ) , sEscapedFingerPrint ) ;
first = false ;
2023-02-03 01:44:45 +01:00
}
2023-06-25 17:21:34 +02:00
StrCat ( sQuery , sizeof ( sQuery ) , " ) and (RemoveType != 'U' or RemoveType is NULL) and (ends > UNIX_TIMESTAMP() + 3600 or ends = created) order by created desc limit 1 " ) ;
//LogError("LOOK HERE: %s", sQuery);
if ( ! first )
2023-02-03 01:44:45 +01:00
{
2023-06-25 17:21:34 +02:00
g_dDatabase . Query ( sql_select_sb_bans , sQuery , GetClientSerial ( client ) , DBPrio_Low ) ;
2023-06-20 23:47:39 +02:00
}
2023-02-03 01:44:45 +01:00
delete results ;
}
2023-04-30 12:14:28 +02:00
public void sql_select_sb_bans ( Database db , DBResultSet results , const char [ ] error , int Serial )
2023-02-03 01:44:45 +01:00
{
if ( ! db | | strlen ( error ) )
{
2023-04-30 12:14:28 +02:00
delete results ;
2023-06-25 17:21:34 +02:00
LogError ( " Database error 2: %s " , error ) ;
2023-02-03 01:44:45 +01:00
return ;
}
2023-04-30 12:14:28 +02:00
int client ;
if ( ( client = GetClientFromSerial ( Serial ) ) = = 0 )
{
delete results ;
return ;
}
2023-02-03 01:44:45 +01:00
if ( ! IsValidClient ( client ) )
{
delete results ;
return ;
}
2023-08-04 23:34:50 +02:00
if ( results . RowCount & & results . FetchRow ( ) )
2023-02-03 01:44:45 +01:00
{
char sSID [ MAX_NAME_LENGTH ] ;
results . FetchString ( 0 , sSID , sizeof ( sSID ) ) ;
2023-02-03 11:38:47 +01:00
Call_StartForward ( g_hOnReportBanPostForward ) ;
Call_PushCell ( client ) ;
2023-08-01 22:15:35 +02:00
Call_PushString ( sSID ) ;
2023-02-03 11:38:47 +01:00
Call_Finish ( ) ;
2023-02-14 21:29:45 +01:00
//bans need to be over 1 hour long for getting detected
2023-08-01 22:15:35 +02:00
char message [ 1024 ] ;
Format ( message , sizeof ( message ) , " Ban avoiding (Jenz ban detector). SteamID avoiding ban: %s " , sSID ) ;
SBPP_BanPlayer ( 0 , client , 0 , message ) ;
2023-02-03 01:44:45 +01:00
}
delete results ;
2023-02-02 00:19:27 +01:00
}
stock bool IsValidClient ( int client )
{
2023-08-01 22:15:35 +02:00
if ( client > 0 & & client < = MaxClients & & IsClientConnected ( client ) & & IsClientInGame ( client ) & & ! IsFakeClient ( client ) )
return true ;
return false ;
2023-02-02 00:19:27 +01:00
}