Advertisement
Guest User

Untitled

a guest
Aug 4th, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.97 KB | None | 0 0
  1. --[[
  2. ~ Sourcebans GLua Module ~
  3. Copyright (c) 2011 Lexi Robinson
  4.  
  5. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
  6. associated documentation files (the "Software"), to deal in the Software without restriction,
  7. including without limitation the rights to use, copy, modify, merge, publish, distribute,
  8. sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10.  
  11. The above copyright notice and this permission notice shall be included in all copies or
  12. substantial portions of the Software.
  13.  
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
  15. NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  16. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  17. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  18. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19.  
  20. WARNING:
  21. Do *NOT* run with sourcemod active. It will have unpredictable effects!
  22. --]]
  23.  
  24. require("mysqloo");
  25. require("gatekeeper");
  26.  
  27. -- These are put here to lower the amount of upvalues and so they're grouped together
  28. -- They provide something like the documentation the SM ones do.
  29. CreateConVar("sb_version", "1.531", FCVAR_SPONLY + FCVAR_REPLICATED + FCVAR_NOTIFY, "The current version of the SourceBans.lua module");
  30. -- This creates a fake concommand that doesn't exist but makes the engine think it does. Useful.
  31. AddConsoleCommand("sb_reload", "Doesn't do anything - Legacy from the SourceMod version.");
  32.  
  33. local error, ErrorNoHalt, GetConVarNumber, GetConVarString, Msg, pairs, print, ServerLog, tonumber, tostring, tobool, unpack =
  34. error, ErrorNoHalt, GetConVarNumber, GetConVarString, Msg, pairs, print, ServerLog, tonumber, tostring, tobool, unpack ;
  35.  
  36. local concommand, game, hook, math, os, player, string, table, timer, mysqloo, gatekeeper =
  37. concommand, game, hook, math, os, player, string, table, timer, mysqloo, gatekeeper ;
  38.  
  39. local HUD_PRINTCONSOLE, HUD_PRINTCENTER, HUD_PRINTNOTIFY, HUD_PRINTTALK =
  40. HUD_PRINTCONSOLE, HUD_PRINTCENTER, HUD_PRINTNOTIFY, HUD_PRINTTALK ;
  41.  
  42. local nocmds;
  43. if (SBANS_NO_COMMANDS) then
  44. nocmds = true;
  45. SBANS_NO_COMMANDS = nil;
  46. end
  47.  
  48. -- Sourcebans.lua provides an interface to SourceBans through GLua, so that SourceMod is not required.
  49. -- It also attempts to duplicate the effects that would be had by running SourceBans, such as the concommand and convars it creates.
  50. -- @release version 1.531, now GM13 compatible!
  51. module("sourcebans");
  52. --[[
  53. CHANGELOG
  54. 1.531 Tiny change to make the source GM13 compatible (no more | operator!)
  55. 1.53 sm_rehash now goes through all online players and makes sure their group is up to date.
  56. 1.521 Fixed a hang if an admin had no srv_flags and no srv_group
  57. 1.52 Added various sm_#say commands at a request, and added a SBANS_NO_COMMANDS global variable to disable all admin commands (for pure lua usage)
  58. 1.51 Made it work again
  59. 1.5 Made it support gatekeeper
  60. 1.41 Fixed yet another 'stop loading admins' glitch
  61. 1.4 Added GetAdmins(), made it work a bit more.
  62. 1.317 Added even more error prevention when an admin doesn't have a server group but is assigned to the server
  63. 1.316 Added error prevention when an admin doesn't have a server group but is assigned to the server
  64. 1.315 Made sure callback was always actually a function even when not passed one, fixed a typo.
  65. 1.31 Added some error checks, removed some sloppy assumptions and fixed queued ban checks not working.
  66. 1.3 Pimped up the concommands and made them report more details
  67. 1.22 Added dogroups to the config to disable automatic usergroup setting
  68. 1.21 Made it so that the player is only kicked if their user object is available
  69. 1.2 Made CheckForBan() and BanPlayerBySteamIDAndIP() accessable
  70. 1.12 Made the concommands check that the right amount of arguments had been passed.
  71. 1.11 Fixed a typo that stopped the fix working
  72. 1.1 Fixed the module freezing the server by pinging the database 10 times a second
  73. --]]
  74. --[[
  75.  
  76. CreateConVar("sb_version", SB_VERSION, _, FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
  77. RegServerCmd("sm_rehash",sm_rehash,"Reload SQL admins");
  78. RegAdminCmd("sm_ban", CommandBan, ADMFLAG_BAN, "sm_ban <#userid|name> <minutes|0> [reason]");
  79. RegAdminCmd("sm_banip", CommandBanIp, ADMFLAG_BAN, "sm_banip <ip|#userid|name> <time> [reason]");
  80. RegAdminCmd("sm_addban", CommandAddBan, ADMFLAG_RCON, "sm_addban <time> <steamid> [reason]");
  81. RegAdminCmd("sb_reload", ADMFLAG_RCON, "Reload sourcebans config and ban reason menu options");
  82. RegAdminCmd("sm_unban", CommandUnban, ADMFLAG_UNBAN, "sm_unban <steamid|ip> [reason]");
  83. --]]
  84. --[[ Config ]]--
  85. local config = {
  86. hostname = "localhost";
  87. username = "root";
  88. password = "";
  89. database = "sourcebans";
  90. dbprefix = "sbans";
  91. website = "the website.";
  92. portnumb = 3306;
  93. serverid = -1;
  94. dogroups = false;
  95. showbanreason = false;
  96. };
  97. --[[ Automatic IP Locator ]]--
  98. local serverport = GetConVarNumber("hostport");
  99. local serverip;
  100. do -- Thanks raBBish! http://www.facepunch.com/showpost.php?p=23402305&postcount=1382
  101. local function band( x, y )
  102. local z, i, j = 0, 1
  103. for j = 0,31 do
  104. if ( x%2 == 1 and y%2 == 1 ) then
  105. z = z + i
  106. end
  107. x = math.floor( x/2 )
  108. y = math.floor( y/2 )
  109. i = i * 2
  110. end
  111. return z
  112. end
  113. local hostip = tonumber(string.format("%u", GetConVarString("hostip")))
  114. local parts = {
  115. band( hostip / 2^24, 0xFF );
  116. band( hostip / 2^16, 0xFF );
  117. band( hostip / 2^8, 0xFF );
  118. band( hostip, 0xFF );
  119. }
  120.  
  121. serverip = string.format( "%u.%u.%u.%u", unpack( parts ) )
  122. end
  123. --]]
  124.  
  125. --[[ Tables ]]--
  126. local admins, adminsByID, adminGroups, database;
  127. local queries = {
  128. -- BanChkr
  129. ["Check for Bans"] = "SELECT bid, name, ends, authid, ip FROM %s_bans WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL AND (authid = '%s' OR ip = '%s') LIMIT 1";
  130. ["Check for Bans by IP"] = "SELECT bid, name, ends, authid, ip FROM %s_bans WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL AND ip = '%s' LIMIT 1";
  131. ["Check for Bans by SteamID"] = "SELECT bid, name, ends, authid, ip FROM %s_bans WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL AND authid = '%s' LIMIT 1";
  132. ["Get All Active Bans"] = "SELECT ip, authid, name, created, ends, length, reason, aid FROM %s_bans WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL;";
  133.  
  134. ["Log Join Attempt"] = "INSERT INTO %s_banlog (sid, time, name, bid) VALUES( %i, %i, '%s', %i)";
  135.  
  136. -- Admins
  137. ["Select Admin Groups"] = "SELECT flags, immunity, name FROM %s_srvgroups";
  138. ["Select Admins"] = "SELECT a.aid, a.user, a.authid, a.srv_group, a.srv_flags, a.immunity FROM %s_admins a, %s_admins_servers_groups g WHERE g.server_id = %i AND g.admin_id = a.aid";
  139.  
  140. -- Bannin
  141. ["Ban Player"] = "INSERT INTO %s_bans (ip, authid, name, created, ends, length, reason, aid, adminIp, sid, country) VALUES('%s', '%s', '%s', %i, %i, %i, '%s', %i, '%s', %i, ' ')";
  142. -- Unbannin
  143. ["Unban SteamID"] = "UPDATE %s_bans SET RemovedBy = %i, RemoveType = 'U', RemovedOn = UNIX_TIMESTAMP(), ureason = '%s' WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL AND authid = '%s'";
  144. ["Unban IPAddress"] = "UPDATE %s_bans SET RemovedBy = %i, RemoveType = 'U', RemovedOn = UNIX_TIMESTAMP(), ureason = '%s' WHERE (length = 0 OR ends > UNIX_TIMESTAMP()) AND removetype IS NULL AND ip = '%s'";
  145. };
  146. local idLookup = {};
  147.  
  148. --[[ ENUMs ]]--
  149. -- Sourcebans
  150. FLAG_BAN = "d";
  151. FLAG_PERMA = "e";
  152. FLAG_UNBAN = "e";
  153. FLAG_ADDBAN = "m";
  154. FLAG_CHAT = "j";
  155.  
  156. -- The mysqloo ones are descriptive, but a mouthful.
  157. STATUS_READY = mysqloo.DATABASE_CONNECTED;
  158. STATUS_WORKING = mysqloo.DATABASE_CONNECTING;
  159. STATUS_OFFLINE = mysqloo.DATABASE_NOT_CONNECTED;
  160. STATUS_ERROR = mysqloo.DATABASE_INTERNAL_ERROR;
  161.  
  162. --[[ Convenience Functions ]]--
  163. local function notifyerror(...)
  164. ErrorNoHalt("[", os.date(), "][SourceBans.lua] ", ...);
  165. ErrorNoHalt("\n");
  166. print();
  167. end
  168. local function notifymessage(...)
  169. local words = table.concat({"[",os.date(),"][SourceBans.lua] ",...},"").."\n";
  170. ServerLog(words);
  171. Msg(words);
  172. end
  173. local function banid(id)
  174. game.ConsoleCommand(string.format("banid 5 %s \n", id));
  175. end
  176. local function kickid(id, reason)
  177. -- Returns reason if reason isn't "" and isn't nil, or the other message.
  178. -- Probably shouldn't be allowed to do things like this but I am so hahahaha >:]
  179. reason = (reason ~= "" and reason) or "You are BANNED! Please check " .. config.website;
  180. local uid = idLookup[id];
  181. if (uid and gatekeeper) then
  182. gatekeeper.Drop(uid, reason);
  183. idLookup[id] = nil;
  184. else
  185. game.ConsoleCommand(string.format("kickid %s %s\n", id, reason));
  186. end
  187. end
  188. local function cleanIP(ip)
  189. return string.match(ip, "(%d+%.%d+%.%d+%.%d+)");
  190. end
  191. local function getIP(ply)
  192. return cleanIP(ply:IPAddress());
  193. end
  194. local function getAdminDetails(admin)
  195. if (admin and admin:IsValid()) then
  196. local data = admins[admin:SteamID()]
  197. if (data) then
  198. return data.aid, getIP(admin);
  199. end
  200. end
  201. return 0, serverip;
  202. end
  203. local function blankCallback() end
  204.  
  205.  
  206. --[[ Query Functions ]]--
  207. local checkBan, banCheckerOnData, banCheckerOnFailure;
  208. local joinAttemptLoggerOnFailure;
  209. local adminGroupLoaderOnSuccess, adminGroupLoaderOnFailure;
  210. local loadAdmins, adminLoaderOnSuccess, adminLoaderOnData, adminLoaderOnFailure;
  211. local doBan, banOnSuccess, banOnFailure;
  212. local startDatabase, databaseOnConnected, databaseOnFailure;
  213. local activeBansOnSuccess, activeBansOnFailure;
  214. local doUnban, unbanOnFailure;
  215. local checkBanBySteamID, checkSIDOnSuccess, checkSIDOnFailure;
  216.  
  217. -- Functions --
  218. function checkBan(ply, steamID, ip, name)
  219. local queryText = queries["Check for Bans"]:format(config.dbprefix, steamID, ip);
  220. local query = database:query(queryText);
  221. if (query) then
  222. query.steamID = steamID;
  223. query.player = ply;
  224. query.name = name;
  225. query.onData = banCheckerOnData;
  226. query.onFailure = banCheckerOnFailure;
  227. query:start();
  228. else
  229. table.insert(database.pending, {queryText, steamID, name, ply});
  230. CheckStatus();
  231. end
  232. end
  233.  
  234. function checkBanBySteamID(steamID, callback)
  235. local query = database:query(queries["Check for Bans by SteamID"]:format(config.dbprefix, steamID));
  236. query.steamID = steamID;
  237. query.callback = callback;
  238. query.onSuccess = checkSIDOnSuccess;
  239. query.onFailure = checkSIDOnFailure;
  240. query:start();
  241. end
  242.  
  243. function loadAdmins()
  244. admins = {};
  245. adminGroups = {};
  246. adminsByID = {};
  247. local query = database:query(queries["Select Admin Groups"]:format(config.dbprefix));
  248. query.onFailure = adminGroupLoaderOnFailure;
  249. query.onSuccess = adminGroupLoaderOnSuccess;
  250. query:start();
  251. notifymessage("Loading Admin Groups . . .");
  252. end
  253.  
  254. function startDatabase()
  255. database = mysqloo.connect(config.hostname, config.username, config.password, config.database, config.portnumb);
  256. database.onConnected = databaseOnConnected;
  257. database.onConnectionFailed = databaseOnFailure;
  258. database.pending = {};
  259. database:connect();
  260. end
  261.  
  262. function doUnban(query, id, reason, admin)
  263. local aid = getAdminDetails(admin)
  264. query = database:query(query:format(config.dbprefix, aid, database:escape(reason), id));
  265. query.onFailure = unbanOnFailure;
  266. query.id = id;
  267. query:start();
  268. end
  269.  
  270. function doBan(steamID, ip, name, length, reason, admin, callback)
  271. local time = os.time();
  272. local adminID, adminIP = getAdminDetails(admin);
  273. name = name or "";
  274. local query = database:query(queries["Ban Player"]:format(config.dbprefix, ip, steamID, database:escape(name), time, time + length, length, database:escape(reason), adminID, adminIP, config.serverid));
  275. query.onSuccess = banOnSuccess;
  276. query.onFailure = banOnFailure;
  277. query.callback = callback;
  278. query.name = name;
  279. query:start();
  280. if (config.showbanreason) then
  281. if (reason and string.Trim(reason) == "") then
  282. reason = nil;
  283. end
  284. if (reason == nil) then
  285. reason = "No reason specified.";
  286. end
  287. reason = "BANNED: " .. reason;
  288. else
  289. reason = nil;
  290. end
  291. if (steamID ~= "") then
  292. kickid(steamID, reason);
  293. banid(steamID);
  294. end
  295. end
  296. -- Data --
  297. function banCheckerOnData(self, data)
  298. notifymessage(self.name, " has been identified as ", data.name, ", who is banned. Kicking ... ");
  299. kickid(self.steamID);
  300. banid(self.steamID);
  301. local query = database:query(queries["Log Join Attempt"]:format(config.dbprefix, config.serverid, os.time(), self.name, data.bid));
  302. query.onFailure = joinAttemptLoggerOnFailure;
  303. query.name = self.name;
  304. query:start();
  305. end
  306.  
  307. function adminLoaderOnSuccess(self)
  308. notifymessage("Finished loading admins!");
  309. for _, ply in pairs(player.GetAll()) do
  310. local info = admins[ply:SteamID()];
  311. if (info) then
  312. if (config.dogroups) then
  313. ply:SetUserGroup(string.lower(info.srv_group))
  314. end
  315. ply.sourcebansinfo = info;
  316. notifymessage(ply:Name() .. " is now a " .. info.srv_group .. "!");
  317. end
  318. end
  319. end
  320.  
  321. function adminLoaderOnData(self, data)
  322. data.srv_group = data.srv_group or "NO GROUP ASSIGNED";
  323. data.srv_flags = data.srv_flags or "";
  324. local group = adminGroups[data.srv_group];
  325. if (group) then
  326. data.srv_flags = data.srv_flags .. (group.flags or "");
  327. if (data.immunity < group.immunity) then
  328. data.immunity = group.immunity;
  329. end
  330. end
  331. if (string.find(data.srv_flags, 'z')) then
  332. data.zflag = true;
  333. end
  334. admins[data.authid] = data;
  335. adminsByID[data.aid] = data;
  336. notifymessage("Loaded admin ", data.user, " with group ", tostring(data.srv_group), ".");
  337. end
  338.  
  339. -- Success --
  340. function adminGroupLoaderOnSuccess(self)
  341. local data = self:getData();
  342. for _, data in pairs(data) do
  343. adminGroups[data.name] = data;
  344. notifymessage("Loaded admin group ", data.name);
  345. end
  346. local query = database:query(queries["Select Admins"]:format(config.dbprefix,config.dbprefix,config.serverid));
  347. query.onSuccess = adminLoaderOnSuccess;
  348. query.onFailure = adminLoaderOnFailure;
  349. query.onData = adminLoaderOnData;
  350. query:start();
  351. notifymessage("Loading Admins . . .");
  352. end
  353.  
  354. function banOnSuccess(self)
  355. self.callback(true);
  356. end
  357.  
  358. function databaseOnConnected(self)
  359. self.automaticretry = nil;
  360. if (config.serverid < 0) then
  361. local query = self:query("SELECT sid FROM %s_servers WHERE ip = '" .. serverip .. "' AND port = '" .. serverport .. "' LIMIT 1")
  362. query.onSuccess = function(self, data) config.sererid = data.sid; end;
  363. query:start();
  364. end
  365. if (not admins) then
  366. loadAdmins();
  367. end
  368. if (#self.pending == 0) then return; end
  369. local query, ply, steamID;
  370. for _, info in pairs(self.pending) do
  371. query = self:query(info[1]);
  372. query.steamID = info[2];
  373. query.name = info[3];
  374. query.player = info[4];
  375. query.onData = banCheckerOnData;
  376. query.onFailure = banCheckerOnFailure;
  377. query:start();
  378. end
  379. self.pending = {};
  380. end
  381.  
  382. function activeBansOnSuccess(self)
  383. local ret = {}
  384. local adminName, adminID;
  385. for _, data in pairs(self:getData()) do
  386. if (data.aid ~= 0) then
  387. local admin = adminsByID[data.aid];
  388. if (not admin) then --
  389. adminName = "Unknown";
  390. adminID = "STEAM_ID_UNKNOWN";
  391. else
  392. adminName = admin.user;
  393. adminID = admin.authid
  394. end
  395. else
  396. adminName = "Console";
  397. adminID = "STEAM_ID_SERVER";
  398. end
  399.  
  400. ret[#ret + 1] = {
  401. IPAddress = data.ip;
  402. SteamID = data.authid;
  403. Name = data.name;
  404. BanStart = data.created;
  405. BanEnd = data.ends;
  406. BanLength = data.length;
  407. BanReason = data.reason;
  408. AdminName = adminName;
  409. AdminID = adminID;
  410. }
  411. end
  412. self.callback(ret);
  413. end
  414.  
  415. function checkSIDOnSuccess(self)
  416. self.callback(#self:getData() > 0);
  417. end
  418.  
  419. -- Failure --
  420. function banCheckerOnFailure(self, err)
  421. notifyerror("SQL Error while checking ", self.name, "'s ban status! ", err);
  422. kickid(self.steamID, "Failed to detect if you are banned!");
  423. end
  424.  
  425. function joinAttemptLoggerOnFailure(self, err)
  426. notifyerror("SQL Error while storing ", self.name, "'s foiled join attempt! ", err);
  427. end
  428.  
  429. function adminGroupLoaderOnFailure(self, err)
  430. notifyerror("SQL Error while loading the admin groups! ", err);
  431. end
  432.  
  433. function adminLoaderOnFailure(self, err)
  434. notifyerror("SQL Error while loading the admins! ", err);
  435. end
  436.  
  437. function banOnFailure(self, err)
  438. notifyerror("SQL Error while storing ", self.name, "'s ban! ", err);
  439. self.callback(false, err);
  440. end
  441.  
  442. function databaseOnFailure(self, err)
  443. notifyerror("Failed to connect to the database: ", err, ". Retrying in 60 seconds.");
  444. self.automaticretry = true;
  445. timer.Simple(60, self.connect, self);
  446. end
  447.  
  448. function activeBansOnFailure(self, err)
  449. notifyerror("SQL Error while loading all active bans! ", err);
  450. self.callback(false, err);
  451. end
  452.  
  453. function unbanOnFailure(self, err)
  454. notifyerror("SQL Error while removing the ban for ", self.id, "! ", err);
  455. end
  456.  
  457. function checkSIDOnFailure(self, err)
  458. notifyerror("SQL Error while checking ", self.steamID, "'s ban status! ", err);
  459. self.callback(false, err);
  460. end
  461. --[[ Hooks ]]--
  462. do
  463. local function ShutDown()
  464. if (database) then
  465. database:abortAllQueries();
  466. end
  467. end
  468.  
  469. local function PlayerAuthed(ply, steamID)
  470. -- Always have this running.
  471. idLookup[steamID] = ply:UserID();
  472.  
  473. if (not database) then
  474. notifyerror("Player ", ply:Name(), " joined, but SourceBans.lua is not active!");
  475. return;
  476. end
  477. checkBan(ply, steamID, getIP(ply), ply:Name());
  478. if (not admins) then
  479. return;
  480. end
  481. local info = admins[ply:SteamID()];
  482. if (info) then
  483. if (config.dogroups) then
  484. ply:SetUserGroup(string.lower(info.srv_group))
  485. end
  486. ply.sourcebansinfo = info;
  487. notifymessage(ply:Name(), " has joined, and they are a ", tostring(info.srv_group), "!");
  488. end
  489. end
  490.  
  491. local function PlayerDisconnected(ply)
  492. idLookup[ply:SteamID()] = nil;
  493. end
  494.  
  495.  
  496. hook.Add("ShutDown", "SourceBans.lua - ShutDown", ShutDown);
  497. hook.Add("PlayerAuthed", "SourceBans.lua - PlayerAuthed", PlayerAuthed);
  498. hook.Add("PlayerDisconnected", "SourceBans.lua - PlayerDisconnected", PlayerDisconnected);
  499. end
  500.  
  501.  
  502. --[[ Exported Functions ]]--
  503. local function checkConnection()
  504. return database and database:query("") ~= nil;
  505. end
  506.  
  507. ---
  508. -- Starts the database and activates the module's functionality.
  509. function Activate()
  510. startDatabase();
  511. notifymessage("Starting the database.");
  512. end
  513.  
  514. ---
  515. -- Bans a player by object
  516. -- @param ply The player to ban
  517. -- @param time How long to ban the player for (in seconds)
  518. -- @param reason Why the player is being banned
  519. -- @param admin (Optional) The admin who did the ban. Leave nil for CONSOLE.
  520. -- @param callback (Optional) A function to call with the results of the ban. Passed true if it worked, false and a message if it didn't.
  521. function BanPlayer(ply, time, reason, admin, callback)
  522. callback = callback or blankCallback;
  523. if (not checkConnection()) then
  524. return callback(false, "No Database Connection");
  525. elseif (not ply:IsValid()) then
  526. error("Expected player, got NULL!", 2);
  527. end
  528. doBan(ply:SteamID(), getIP(ply), ply:Name(), time, reason, admin, callback);
  529. end
  530.  
  531. ---
  532. -- Bans a player by steamID
  533. -- @param steamID The SteamID to ban
  534. -- @param time How long to ban the player for (in seconds)
  535. -- @param reason Why the player is being banned
  536. -- @param admin (Optional) The admin who did the ban. Leave nil for CONSOLE.
  537. -- @param name (Optional) The name to give the ban if no active player matches the SteamID.
  538. -- @param callback (Optional) A function to call with the results of the ban. Passed true if it worked, false and a message if it didn't.
  539. function BanPlayerBySteamID(steamID, time, reason, admin, name, callback)
  540. callback = callback or blankCallback;
  541. if (not checkConnection()) then
  542. return callback(false, "No Database Connection");
  543. end
  544. for _, ply in pairs(player.GetAll()) do
  545. if (ply:SteamID() == steamID) then
  546. return BanPlayer(ply, time, reason, admin, callback);
  547. end
  548. end
  549. doBan(steamID, '', name, time, reason, admin, callback)
  550. end
  551.  
  552. ---
  553. -- Bans a player by IPAddress
  554. -- @param ip The IPAddress to ban
  555. -- @param time How long to ban the player for (in seconds)
  556. -- @param reason Why the player is being banned
  557. -- @param admin (Optional) The admin who did the ban. Leave nil for CONSOLE.
  558. -- @param name (Optional) The name to give the ban if no active player matches the IP.
  559. -- @param callback (Optional) A function to call with the results of the ban. Passed true if it worked, false and a message if it didn't.
  560. function BanPlayerByIP(ip, time, reason, admin, name, callback)
  561. callback = callback or blankCallback;
  562. if (not checkConnection()) then
  563. return callback(false, "No Database Connection");
  564. end
  565. for _, ply in pairs(player.GetAll()) do
  566. if (getIP(ply) == ip) then
  567. return BanPlayer(ply, time, reason, admin, callback);
  568. end
  569. end
  570. doBan('', cleanIP(ip), name, time, reason, admin, callback);
  571. game.ConsoleCommand("addip 5 " .. ip .. "\n");
  572. end
  573.  
  574. ---
  575. -- Bans a player by SteamID and IPAddress
  576. -- @param steamID The SteamID to ban
  577. -- @param ip The IPAddress to ban
  578. -- @param time How long to ban the player for (in seconds)
  579. -- @param reason Why the player is being banned
  580. -- @param admin (Optional) The admin who did the ban. Leave nil for CONSOLE.
  581. -- @param name (Optional) The name to give the ban
  582. -- @param callback (Optional) A function to call with the results of the ban. Passed true if it worked, false and a message if it didn't.
  583. function BanPlayerBySteamIDAndIP(steamID, ip, time, reason, admin, name, callback)
  584. callback = callback or blankCallback;
  585. if (not checkConnection()) then
  586. return callback(false, "No Database Connection");
  587. end
  588. doBan(steamID, cleanIP(ip), name, time, reason, admin, callback);
  589. end
  590.  
  591.  
  592. ---
  593. -- Unbans a player by SteamID
  594. -- @param steamID The SteamID to unban
  595. -- @param reason The reason they are being unbanned.
  596. -- @param admin (Optional) The admin who did the unban. Leave nil for CONSOLE.
  597. function UnbanPlayerBySteamID(steamID, reason, admin)
  598. if (not checkConnection()) then
  599. return false, "No Database Connection";
  600. end
  601. doUnban(queries["Unban SteamID"], steamID, reason, admin);
  602. game.ConsoleCommand("removeid " .. steamID .. "\n");
  603. end
  604.  
  605. ---
  606. -- Unbans a player by IPAddress. If multiple players match the IP, they will all be unbanned.
  607. -- @param ip The IPAddress to unban
  608. -- @param reason The reason they are being unbanned.
  609. -- @param admin (Optional) The admin who did the unban. Leave nil for CONSOLE.
  610. function UnbanPlayerByIPAddress(ip, reason, admin)
  611. if (not checkConnection()) then
  612. return false, "No Database Connection";
  613. end
  614. doUnban(queries["Unban IPAddress"], ip, reason, admin);
  615. game.ConsoleCommand("removeip " .. ip .. "\n");
  616. end
  617.  
  618. ---
  619. -- Fetches all currently active bans in a table.
  620. -- If the ban was inacted by the server, the AdminID will be "STEAM_ID_SERVER".<br />
  621. -- If the server does not know who the admin who commited the ban is, the AdminID will be "STEAM_ID_UNKNOWN".<br/>
  622. -- Example table structure: <br/>
  623. -- <pre>{ <br/>
  624. -- &nbsp; BanStart = 1271453312, <br/>
  625. -- &nbsp; BanEnd = 1271453312, <br/>
  626. -- &nbsp; BanLength = 0, <br/>
  627. -- &nbsp; BanReason = "'Previously banned for repeately crashing the server'", <br/>
  628. -- &nbsp; IPAddress = "99.101.125.168", <br/>
  629. -- &nbsp; SteamID = "STEAM_0:0:20924001", <br/>
  630. -- &nbsp; Name = "MINOTAUR", <br/>
  631. -- &nbsp; AdminName = "Lexi", <br/>
  632. -- &nbsp; AdminID = "STEAM_0:1:16678762" <br/>
  633. -- }</pre> <br/>
  634. -- Bear in mind that SteamID or IPAddress may be a blank string.
  635. -- @param callback The function to be given the table
  636. function GetAllActiveBans(callback)
  637. if (not callback) then
  638. error("Function expected, got nothing!", 2);
  639. elseif (not checkConnection()) then
  640. return callback(false, "No Database Connection");
  641. end
  642. local query = database:query(queries["Get All Active Bans"]:format(config.dbprefix));
  643. query.onSuccess = activeBansOnSuccess;
  644. query.onFailure = activeBansOnFailure;
  645. query.callback = callback;
  646. query:start();
  647. end
  648.  
  649. ---
  650. -- Set the config variables. Most will not take effect until the next database connection.<br />
  651. -- NOTE: These settings do *NOT* persist. You will need to set them all each time.
  652. -- @param key The settings key to set
  653. -- @param value The value to set the key to.
  654. -- @usage Acceptable keys: hostname, username, password, database, dbprefix, portnumb, serverid, website, showbanreason and dogroups.
  655. function SetConfig(key, value)
  656. if (config[key] == nil) then
  657. error("Invalid key provided. Please check your information.",2);
  658. end
  659. if (key == "portnumb" or key == "serverid") then
  660. value = tonumber(value);
  661. elseif (key == "showbanreason" or key == "dogroups") then
  662. value = tobool(value);
  663. end
  664. config[key] = value;
  665. end
  666.  
  667.  
  668. ---
  669. -- Checks the status of the database and recovers if there are errors
  670. -- WARNING: This function is blocking. It is auto-called every 5 minutes.
  671. function CheckStatus()
  672. if (not database or database.automaticretry) then return; end
  673. local status = database:status();
  674. if (status == STATUS_WORKING or status == STATUS_READY) then
  675. return;
  676. elseif (status == STATUS_ERROR) then
  677. notifyerror("The database object has suffered an inernal error and will be recreated.");
  678. local pending = database.pending;
  679. startDatabase();
  680. database.pending = pending;
  681. else
  682. notifyerror("The server has lost connection to the database. Retrying...")
  683. database:connect();
  684. end
  685. end
  686. timer.Create("SourceBans.lua - Status Checker", 300, 0, CheckStatus);
  687.  
  688. ---
  689. -- Checks to see if a SteamID is banned from the system
  690. -- @param steamID The SteamID to check
  691. -- @param callback The callback function to tell the results to
  692. function CheckForBan(steamID, callback)
  693. if (not checkConnection()) then
  694. return callback(false, "No Database Connection");
  695. elseif (not callback) then
  696. error("Callback function required!", 2);
  697. elseif (not steamID) then
  698. error("SteamID required!", 2);
  699. end
  700. checkBanBySteamID(steamID, callback);
  701. end
  702.  
  703. ---
  704. -- Gets all the admins active on this server
  705. -- @returns A table.
  706. function GetAdmins()
  707. local ret = {}
  708. for id,data in pairs(admins) do
  709. ret[id] = {
  710. Name = data.user;
  711. SteamID = id;
  712. UserGroup = data.srv_group;
  713. AdminID = data.aid;
  714. Flags = data.srv_flags;
  715. ZFlagged = data.zflag;
  716. Immunity = data.immunity;
  717. }
  718. end
  719. return ret;
  720. end
  721.  
  722.  
  723.  
  724. --[[ ConCommands ]]--
  725.  
  726.  
  727.  
  728. -- Borrowed from my gamemode
  729. local function playerGet(id)
  730. local res, len, name, num, pname, lon;
  731. id = string.Trim(id);
  732. name = string.lower(id);
  733. num = tonumber(id);
  734. id = string.upper(id);
  735. for _, ply in pairs(player.GetAll()) do
  736. pname = ply:Name():lower();
  737. if (ply:UserID() == num or ply:SteamID() == id or pname == name) then
  738. return ply;
  739. elseif (string.find(pname, name, 1, true)) then
  740. lon = pname:len();
  741. if (res) then
  742. if (lon < len) then
  743. res = ply;
  744. len = lon;
  745. end
  746. else
  747. res = ply;
  748. len = lon;
  749. end
  750. end
  751. end
  752. return res;
  753. end
  754. local function complain(ply, msg, lvl)
  755. if (not (ply and ply:IsValid())) then
  756. print(msg);
  757. else
  758. ply:PrintMessage(lvl or HUD_PRINTCONSOLE, msg);
  759. end
  760. return false;
  761. end
  762. local function not4u(ply, cmd)
  763. ply:ChatPrint("Unknown Command: '" .. cmd .. "'\n");
  764. end
  765. -- Gets a steamID from concommand calls that don't bother to quote it.
  766. local function getSteamID(tab)
  767. local a,b,c,d,e = tab[1], tab[2], tonumber(tab[3]), tab[4], tonumber(tab[5]);
  768. if (string.find(a, "STEAM_%d:%d:%d+")) then
  769. return table.remove(tab, 1);
  770. elseif (string.find(a, "STEAM_") and b == ":" and c and d == ":" and e) then
  771. -- Kill the five entries as if they were one
  772. table.remove(tab, 1);
  773. table.remove(tab, 1);
  774. table.remove(tab, 1);
  775. table.remove(tab, 1);
  776. table.remove(tab, 1);
  777. return a .. b .. c .. d .. e;
  778. end
  779. end
  780. -- Check if a player has authorisation to run the command.
  781. local function authorised(ply, flag)
  782. if (not (ply and ply:IsValid())) then
  783. return true;
  784. elseif (not ply.sourcebansinfo) then
  785. return false;
  786. end
  787. return ply.sourcebansinfo.zflag or string.find(ply.sourcebansinfo.srv_flags, flag);
  788. end
  789.  
  790. local function complainer(ply, pl, time, reason, usage)
  791. if (not pl) then
  792. return complain(ply, "Invalid player!" .. usage);
  793. elseif (not time or time < 0) then
  794. return complain(ply, "Invalid time!" .. usage);
  795. elseif (reason == "") then
  796. return complain(ply, "Invalid reason!" .. usage);
  797. elseif (time == 0 and not authorised(ply, FLAG_PERMA)) then
  798. return complain(ply, "You are not authorised to permaban!");
  799. end
  800. return true;
  801. end
  802.  
  803. concommand.Add("sm_rehash", function(ply, cmd)
  804. if (ply:IsValid()) then return not4u(ply, cmd); end
  805. notifymessage("Rehash command recieved, reloading admins:");
  806. loadAdmins();
  807. end, nil, "Reload the admin list from the SQL");
  808.  
  809. local usage = "\n - Usage: sm_psay <#userid|name|steamid> <words>";
  810. concommand.Add("sm_psay", function(ply, _, args)
  811. if (nocmds and ply:IsValid()) then
  812. return not4u(ply);
  813. elseif (#args < 2) then
  814. return complain(ply, usage:sub(4));
  815. elseif (not authorised(ply, FLAG_CHAT)) then
  816. return complain(ply, "You do not have access to this command!");
  817. end
  818. local pl, words = table.remove(args,1), table.concat(args, " "):Trim();
  819. pl = playerGet(pl);
  820. if (not pl) then
  821. return complain(ply, "Invalid player!" .. usage);
  822. elseif (words == "") then
  823. return complain(ply, "Invalid message!".. usage);
  824. end
  825. local name1 = ply:IsValid() and ply:Name() or "CONSOLE";
  826. local name2 = pl:Name();
  827. complain(ply, "(Private: " .. name2 .. ") " .. name1 .. ": " .. words, HUD_PRINTCHAT);
  828. complain(pl, "(Private: " .. name2 .. ") " .. name1 .. ": " .. words, HUD_PRINTCHAT);
  829. notifymessage(name1, " triggered sm_psay to ", name2, " (text ", words, ")");
  830. end, nil, "Sends a private message to a player" .. usage);
  831.  
  832. local usage = "\n - Usage: sm_say <words>";
  833. concommand.Add("sm_say", function(ply, _, args)
  834. if (nocmds and ply:IsValid()) then
  835. return not4u(ply);
  836. elseif (#args < 1) then
  837. return complain(ply, usage:sub(4));
  838. elseif (not authorised(ply, FLAG_CHAT)) then
  839. return complain(ply, "You do not have access to this command!");
  840. end
  841. local words = table.concat(args, " "):Trim();
  842. if (words == "") then
  843. return complain(ply, "Invalid message!"..usage);
  844. end
  845. local name1 = ply:IsValid() and ply:Name() or "CONSOLE";
  846. for _, pl in pairs(player.GetAll()) do
  847. if (pl:IsValid() and not pl:IsBot()) then
  848. complain(pl, name1 .. ": " .. words, HUD_PRINTCHAT);
  849. end
  850. end
  851. notifymessage(name1, " triggered sm_say (text ", words, ")");
  852. end, nil, "Sends a message to everyone" .. usage);
  853.  
  854. local usage = "\n - Usage: sm_csay <words>";
  855. concommand.Add("sm_csay", function(ply, _, args)
  856. if (nocmds and ply:IsValid()) then
  857. return not4u(ply);
  858. elseif (#args < 1) then
  859. return complain(ply, usage:sub(4));
  860. elseif (not authorised(ply, FLAG_CHAT)) then
  861. return complain(ply, "You do not have access to this command!");
  862. end
  863. local words = table.concat(args, " "):Trim();
  864. if (words == "") then
  865. return complain(ply, "Invalid message!"..usage);
  866. end
  867. local name1 = ply:IsValid() and ply:Name() or "CONSOLE";
  868. for _, pl in pairs(player.GetAll()) do
  869. if (pl:IsValid() and not pl:IsBot()) then
  870. complain(pl, name1 .. ": " .. words, HUD_PRINTCENTER);
  871. end
  872. end
  873. notifymessage(name1, " triggered sm_csay (text ", words, ")");
  874. end, nil, "Sends a message to everyone in the center of their screen" .. usage);
  875.  
  876. local usage = "\n - Usage: sm_chat <words>";
  877. concommand.Add("sm_chat", function(ply, _, args)
  878. if (nocmds and ply:IsValid()) then
  879. return not4u(ply);
  880. elseif (#args < 1) then
  881. return complain(ply, usage:sub(4));
  882. elseif (not authorised(ply, FLAG_CHAT)) then
  883. return complain(ply, "You do not have access to this command!");
  884. end
  885. local words = table.concat(args, " "):Trim();
  886. if (words == "") then
  887. return complain(ply, "Invalid message!"..usage);
  888. end
  889. local name1 = ply:IsValid() and ply:Name() or "CONSOLE";
  890. for _, pl in pairs(player.GetAll()) do
  891. if (pl:IsValid() and pl:IsAdmin()) then
  892. complain(pl, "(ADMINS) " .. name1 .. ": " .. words, HUD_PRINTCHAT);
  893. end
  894. end
  895. notifymessage(name1, " triggered sm_chat (text ", words, ")");
  896. end, nil, "Sends a message to all online admins" .. usage);
  897.  
  898. if (nocmds) then
  899. return;
  900. end
  901.  
  902. local usage = "\n - Usage: sm_ban <#userid|name> <minutes|0> <reason>";
  903. concommand.Add("sm_ban", function(ply, _, args)
  904. if (#args < 3) then
  905. return complain(ply, usage:sub(4));
  906. elseif (not checkConnection()) then
  907. return complain(ply, "The database is not active at the moment. Your command could not be completed.");
  908. elseif (not authorised(ply, FLAG_BAN)) then
  909. return complain(ply, "You do not have access to this command!");
  910. end
  911. local pl, time, reason = table.remove(args,1), tonumber(table.remove(args,1)), table.concat(args, " "):Trim();
  912. pl = playerGet(pl);
  913. if (not complainer(ply, pl, time, reason, usage)) then
  914. return;
  915. end
  916. local name = pl:Name();
  917. local function callback(res, err)
  918. if (res) then
  919. complain(ply, "sm_ban: " .. name .. " has been banned successfully.")
  920. else
  921. complain(ply, "sm_ban: " .. name .. " has not been banned. " .. err);
  922. end
  923. end
  924. BanPlayer(pl, time * 60, reason, ply, callback);
  925. complain(ply, "sm_ban: Your ban request has been sent to the database.");
  926. end, nil, "Bans a player" .. usage);
  927.  
  928. -- Author's note: Why would you want to only ban someone by only their IP when you have their SteamID? This is a stupid concommand. Hopefully no one will use it.
  929. local usage = "\n - Usage: sm_banip <ip|#userid|name> <minutes|0> <reason>";
  930. concommand.Add("sm_banip", function(ply, _, args)
  931. if (#args < 3) then
  932. return complain(ply, usage:sub(4));
  933. elseif (not checkConnection()) then
  934. return complain(ply, "The database is not active at the moment. Your command could not be completed.");
  935. elseif (not authorised(ply, FLAG_BAN)) then
  936. return complain(ply, "You do not have access to this command!");
  937. end
  938. local id, time, reason = table.remove(args,1), tonumber(table.remove(args,1)), table.concat(args, " "):Trim();
  939. local pl;
  940. if (string.find(id, "%d+%.%d+%.%d+%.%d+")) then
  941. for _, ply in pairs(player.GetAll()) do
  942. if (ply:SteamID() == id) then
  943. pl = ply;
  944. break;
  945. end
  946. end
  947. id = cleanIP(id);
  948. else
  949. pl = playerGet(id)
  950. id = nil;
  951. if (pl) then
  952. id = getIP(pl);
  953. end
  954. end
  955. if (not complainer(ply, pl, time, reason, usage)) then
  956. return;
  957. end
  958. local name = pl:Name();
  959. kickid(pl:SteamID(), config.showbanreason and "Banned: " .. reason);
  960. game.ConsoleCommand("addip 5 " .. id .. "\n");
  961. local function callback(res, err)
  962. if (res) then
  963. complain(ply, "sm_banip: " .. name .. " has been IP banned successfully.")
  964. else
  965. complain(ply, "sm_banip: " .. name .. " has not been IP banned. " .. err);
  966. end
  967. end
  968. doBan('', id, name, time * 60, reason, ply, callback)
  969. complain(ply, "sm_banip: Your ban request has been sent to the database.");
  970. end, nil, "Bans a player by only their IP" .. usage);
  971.  
  972. local usage = "\n - Usage: sm_addban <minutes|0> <steamid> <reason>";
  973. concommand.Add("sm_addban", function(ply, _, args)
  974. if (#args < 3) then
  975. return complain(ply, usage:sub(4));
  976. elseif (not checkConnection()) then
  977. return complain(ply, "The database is not active at the moment. Your command could not be completed.");
  978. elseif (not authorised(ply, FLAG_ADDBAN)) then
  979. return complain(ply, "You do not have access to this command!");
  980. end
  981. local time, id, reason = tonumber(table.remove(args,1)), getSteamID(args), table.concat(args, " "):Trim();
  982. if (not id) then
  983. return complain(ply, "Invalid SteamID!" .. usage);
  984. elseif (not time or time < 0) then
  985. return complain(ply, "Invalid time!" .. usage);
  986. elseif (reason == "") then
  987. return complain(ply, "Invalid reason!" .. usage);
  988. elseif (time == 0 and not authorised(ply, FLAG_PERMA)) then
  989. return complain(ply, "You are not authorised to permaban!");
  990. end
  991. local function callback(res, err)
  992. if (res) then
  993. complain(ply, "sm_addban: " .. id .. " has been banned successfully.")
  994. else
  995. complain(ply, "sm_addban: " .. id .. " has not been banned. " .. err);
  996. end
  997. end
  998. BanPlayerBySteamID(id, time * 60, reason, ply, '', callback);
  999. complain(ply, "sm_addban: Your ban request has been sent to the database.");
  1000. end, nil, "Bans a player by their SteamID" .. usage);
  1001.  
  1002. local usage = "\n - Usage: sm_unban <steamid|ip> <reason>";
  1003. concommand.Add("sm_unban", function(ply, _, args)
  1004. if (#args < 2) then
  1005. return complain(ply, usage:sub(4));
  1006. elseif (not checkConnection()) then
  1007. return complain(ply, "The database is not active at the moment. Your command could not be completed.");
  1008. elseif (not authorised(ply, FLAG_UNBAN)) then
  1009. return complain(ply, "You do not have access to this command!");
  1010. end
  1011. local id, reason, func;
  1012. if (string.find(args[1], "%d+%.%d+%.%d+%.%d+")) then
  1013. id = table.remove(args,1);
  1014. func = UnbanPlayerByIPAddress;
  1015. else
  1016. id = getSteamID(args);
  1017. func = UnbanPlayerBySteamID;
  1018. end
  1019. if (not id) then
  1020. return complain(ply, "Invalid SteamID!" .. usage);
  1021. end
  1022. reason = table.concat(args, " "):Trim()
  1023. if (reason == "") then
  1024. return complain(ply, "Invalid reason!" .. usage);
  1025. end
  1026. func(id, reason, ply);
  1027. complain(ply, "Your unban request has been sent to the database.");
  1028. end, nil, "Unbans a player" .. usage);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement