Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --------------------
- -- Config --
- --------------------
- local host = "123.456.789.012"
- local username = "user"
- local password = "pass"
- local database = "bans"
- local port = 3306
- local table = "gbans"
- local updatetime = 1 -- How often, in minutes, it updates the bans from mysql.
- -- (So if a person banned from one server joins another server using the same DB, it could take up to this long to get rid of him/her)
- local persistent = true -- Use a persistent MySQL connection?
- local baninterval = 44000 -- Ban time to report to console. We can't use 0 because we don't want it to be saved with writeid. 44k minutes == 1 month.
- -- If you plan on keeping your server on one map without restarting for more than a month at a time (hah) then you'll need to up this value.
- --[[
- Table structure:
- CREATE TABLE gbans (
- id INT UNSIGNED PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,
- steamid CHAR( 12 ) NOT NULL,
- name CHAR( 31 ),
- time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
- unban_time TIMESTAMP NOT NULL DEFAULT 0,
- comment CHAR( 128 ),
- serverip INT UNSIGNED NOT NULL,
- serverport SMALLINT UNSIGNED NOT NULL DEFAULT 27015,
- adminname CHAR( 31 ),
- adminsteamid CHAR( 12 )
- );
- ]]--
- require( "mysql" )
- module( "UBan", package.seeall )
- local db
- Bans = {} -- Keep track of all the last known bans
- function DoQuery( query, type )
- local result, isok, err = mysql.query( db, query, type or mysql.QUERY_NUMERIC )
- if not isok and err == "" then isok = true end -- False positive
- if not isok then
- error( tostring( err ), 2 )
- return nil
- end
- if result then
- -- print( query ) -- For debug
- -- PrintTable( result )
- end
- return result
- end
- function Connect()
- if db then return db end -- Still connected
- db, err = mysql.connect( host, username, password, database, port )
- if db == 0 then
- db = nil
- error( tostring( err ), 1 )
- return
- end
- return db
- end
- function Disconnect( force )
- if not db then return end -- Already disconnected
- if persistent and not force then return end -- Don't disconnect, persistent
- local succ, err = mysql.disconnect( db )
- if not succ then
- error( tostring( err ), 2 )
- end
- db = nil
- end
- hook.Add( "ShutDown", "UBanClose", function() Disconnect( true ) end ) -- Force closed on shutdown.
- function Escape( str )
- if not db then
- Msg( "Not connected to DB.\n" )
- return
- end
- if not str then return end
- local esc, err = mysql.escape( db, str )
- if not esc then
- error( tostring( err ), 2 )
- return nil
- end
- -- print( "esc=" .. esc ) -- For debug
- return esc
- end
- -- Because we use this a lot
- function Format( str )
- if not str then return "NULL" end
- return string.format( "%q", str )
- end
- -- Ban user
- function BanUser( banner, ply, time, comment )
- local time2
- if not time or time == 0 then
- time2 = baninterval
- else
- time2 = math.min( time / 60, baninterval )
- end
- local str = string.format( "kickid %s Banned on global ban list\n", ply:SteamID() )
- game.ConsoleCommand( str )
- local str = string.format( "banid %f %s kick\n", time2, ply:SteamID() ) -- Convert time to minutes
- game.ConsoleCommand( str )
- return ManualBan( banner, ply:SteamID(), ply:Nick(), time, comment )
- end
- function ManualBan( banner, steamid, name, time, comment )
- if not steamid then
- error( "Bad arguments passed to UBan.ManualBan", 2 )
- return
- end
- Connect() -- Make sure we're connected
- local curuser = DoQuery( "SELECT CURRENT_USER()" )
- curuser = curuser[ 1 ][ 1 ] -- Get to the info we want
- local curip = curuser:gsub( ".-@", "" ) or "127.0.0.1"
- local curport = GetConVarNumber( "hostport" )
- steamid = steamid:upper():gsub( "STEAM_", "" )
- local bannername
- local bannersteam
- if banner and banner:IsValid() and banner:IsPlayer() then
- bannername = banner:Nick()
- bannersteam = banner:SteamID():upper():gsub( "STEAM_", "" )
- end
- local timestring = "0" -- ban duration part
- if time and time > 0 then
- timestring = "ADDTIME( NOW(), SEC_TO_TIME( " .. time .. " ) )"
- end
- local result
- result = DoQuery( "INSERT INTO " .. table .. " ( steamid, name, unban_time, comment, serverip, serverport, adminname, adminsteamid ) VALUES( \"" ..
- Escape( steamid ) .. "\", " .. Format( Escape( name ) ) .. ", " .. timestring .. ", " .. Format( Escape( comment ) ) .. ", INET_ATON( \"" .. curip .. "\" ), " .. curport .. ", " .. Format( Escape( bannername ) ) .. ", " .. Format( Escape( bannersteam ) ) .. " )" )
- if time == 0 then
- Bans[ steamid ] = baninterval
- else
- Bans[ steamid ] = time
- end
- Disconnect() -- Make sure we're disconnected
- return result
- end
- function ClearBan( steamid )
- steamid = steamid:upper():gsub( "STEAM_", "" )
- Connect() -- Make sure we're connected
- local results = DoQuery( "UPDATE " .. table .. " SET unban_time=NOW(), comment=CONCAT( \"(ban lifted before expired) \", comment ) WHERE (NOW() < unban_time OR unban_time = 0) AND steamid=\"" .. Escape( steamid ) .. "\"", mysql.QUERY_FIELDS ) -- Select active bans
- game.ConsoleCommand( "removeid STEAM_" .. steamid .. "\n" )
- Bans[ steamid ] = nil
- Disconnect() -- Make sure we're disconnected
- end
- function GetBans()
- Connect() -- Make sure we're connected
- local results = DoQuery( "SELECT id, steamid, TIME_TO_SEC( TIMEDIFF( unban_time, NOW() ) ) as timeleft, name, time, unban_time, comment, INET_NTOA( serverip ) as serverip, serverport, adminname, adminsteamid FROM " .. table .. " WHERE NOW() < unban_time OR unban_time = 0", mysql.QUERY_FIELDS ) -- Select active bans
- Disconnect() -- Make sure we're disconnected
- return results
- end
- function DoBans()
- Connect()
- local results = DoQuery( "SELECT steamid, TIME_TO_SEC( TIMEDIFF( unban_time, NOW() ) ) as timeleft FROM " .. table .. " WHERE NOW() < unban_time OR unban_time = 0", mysql.QUERY_FIELDS ) -- Select active bans
- local steamids = {}
- for _, t in ipairs( results ) do
- local steamid = t.steamid
- local time = t.timeleft
- if not time or time == 0 then
- time = baninterval
- else
- time = math.min( time / 60, baninterval )
- end
- steamids[ steamid ] = math.max( time, steamids[ steamid ] or 0 ) -- We're doing this so oddly so we can catch multiple results and use the largest one.
- end
- -- We're using this following chunk of code to identify current steamids in the server
- local cursteamids = {}
- local players = player.GetAll()
- for _, ply in ipairs( players ) do
- cursteamids[ ply:SteamID() ] = ply
- end
- for steamid, time in pairs( steamids ) do -- loop through all currently banned ids
- if cursteamids[ "STEAM_" .. steamid ] then -- Currently connected
- local str = string.format( "kickid STEAM_%s Banned on global ban list\n", steamid )
- game.ConsoleCommand( str )
- Bans[ steamid ] = nil -- Clear their ban info to make sure they get banned. (A 'reban' should only ever arise if console removeid's a steamid)
- end
- if not Bans[ steamid ] or Bans[ steamid ] < time or Bans[ steamid ] > time + baninterval * 2 then -- If we don't already have them marked as banned or it's a new time
- local str = string.format( "banid %f STEAM_%s kick\n", time, steamid )
- game.ConsoleCommand( str )
- -- print( str ) -- For debug
- end
- Bans[ steamid ] = time
- end
- for steamid in pairs( Bans ) do -- loop through all recorded bans
- if not steamids[ steamid ] then -- If they're not on the ban list we just pulled off the server, they're out of jail!
- game.ConsoleCommand( "removeid STEAM_" .. steamid .. "\n" )
- Bans[ steamid ] = nil
- end
- end
- Disconnect()
- end
- DoBans() -- Initial
- timer.Create( "UBantimer", updatetime * 60, 0, DoBans ) -- Updates
Add Comment
Please, Sign In to add comment