/// <summary> /// Handles the outgoing player connection, either by disconnect or kick. /// </summary> /// <param name="player">The player.</param> public async Task HandleOutgoingPlayerConnection(string player) { Log.Write("Detected outgoing connection for " + player, _logClassType, _logPrefix); player = player.ToLowerInvariant(); // The outgoing player was actually in the game, and not a spectator var outgoingWasActive = _sst.ServerInfo.IsActivePlayer(player); // Get the outgoing player's team before he disconnected var outgoingTeam = _sst.ServerInfo.CurrentPlayers[player].Team; // Evaluate the player's no-show/sub status for pickup module, if active if (_sst.Mod.Pickup.Active) { await _sst.Mod.Pickup.Manager.EvalOutgoingPlayer(player, outgoingWasActive, outgoingTeam); _sst.Mod.Pickup.Manager.RemoveActivePickupPlayer(player); _sst.Mod.Pickup.Manager.RemoveEligibility(player); } // Remove player from our internal list RemovePlayer(player); // If player was/is currently being spectated, clear the internal tracker if (!string.IsNullOrEmpty(_sst.ServerInfo.PlayerFollowedForAccuracy) && _sst.ServerInfo.PlayerFollowedForAccuracy.Equals(player)) { _sst.ServerInfo.PlayerFollowedForAccuracy = string.Empty; } // If IRC module is active, send the message to the IRC channel if (_sst.Mod.Irc.Active && _sst.Mod.Irc.IsConnectedToIrc) { _sst.Mod.Irc.IrcManager.SendIrcMessage(_sst.Mod.Irc.IrcManager.IrcSettings.ircChannel, string.Format("{0} has left my QL server.", player)); } // Evaluate player's early quit situation if that module is active if (!_sst.Mod.EarlyQuit.Active) { return; } if (!outgoingWasActive) { return; } // Do not increase player's early quit count if already banned. var banDb = new DbBans(); if (banDb.UserAlreadyBanned(player)) { return; } var eqh = new EarlyQuitHandler(_sst); await eqh.EvalCountdownQuitter(player); await eqh.EvalInProgressQuitter(player); }
/// <summary> /// Bans the early quitter. /// </summary> /// <param name="player">The player.</param> private async Task BanEarlyQuitter(string player) { // User already banned by admin (or by another module); do nothing if (_bansDb.UserAlreadyBanned(player)) { Log.Write(string.Format( "{0} already existed in ban database; skipping early quit ban.", player), _logClassType, _logPrefix); return; } // Do the ban var expirationDate = ExpirationDateGenerator.GenerateExpirationDate(_banTime, _banTimeScale); _bansDb.AddUserToDb(player, "earlyQuitMod", DateTime.Now, expirationDate, BanType.AddedByEarlyQuit); await _sst.QlCommands.QlCmdSay( string.Format( "^5[EARLYQUIT]^7 ^3{0}^7 has quit too many games early and is now banned until:^1 {1}", player, expirationDate.ToString("G", DateTimeFormatInfo.InvariantInfo)), false); // The player might have not actually disconnected but spectated instead, so kickban(QL) immediately await _sst.QlCommands.CustCmdKickban(player); // UI: reflect changes _sst.UserInterface.RefreshCurrentBansDataSource(); }
/// <summary> /// Check to see whether a time-ban exists for the specified user and kickbans the player /// from the server if so; if ban has expired then remove ban. /// </summary> /// <param name="player">The player to check.</param> public async Task CheckForBans(string player) { player = player.ToLowerInvariant(); if (!_banDb.UserAlreadyBanned(player)) { return; } var banInfo = _banDb.GetBanInfo(player); if (banInfo == null) { return; } if (banInfo.BanExpirationDate == default(DateTime)) { return; } if (DateTime.Now <= banInfo.BanExpirationDate) { string reason; switch (banInfo.BanType) { case BanType.AddedByAdmin: reason = "admin ban"; break; case BanType.AddedByEarlyQuit: reason = "early quits"; break; default: reason = "unspecified"; break; } await _sst.QlCommands.QlCmdSay( string.Format( "^3[=> TIMEBAN IN {0} SECS] ^7Player: ^3{1}^7 was banned on ^1{2}^7. Ban expires: ^2{3}^7. For: ^3{4}", _kickDelaySecs, player, banInfo.BanAddedDate.ToString("G", DateTimeFormatInfo.InvariantInfo), banInfo.BanExpirationDate.ToString("G", DateTimeFormatInfo.InvariantInfo), reason), false); // Wait prior to kicking, so recipient's screen doesn't freeze on 'awaiting snapshot' await _sst.QlCommands.QlCmdDelayedTell(string.Format( "^3You will be banned shortly. You were time-banned on {0} for: {1}, ban expires: {2}", banInfo.BanAddedDate.ToString("G", DateTimeFormatInfo.InvariantInfo), reason, banInfo.BanExpirationDate.ToString("G", DateTimeFormatInfo.InvariantInfo)), player, _kickTellDelaySecs); await _sst.QlCommands.CustCmdDelayedKickban(player, (_kickDelaySecs + 2)); } else { await RemoveBan(banInfo); } }
/// <summary> /// Adds the ban. /// </summary> /// <param name="c">The command argument information.</param> /// <returns><c>true</c> if the ban was successfully added, otherwise <c>false</c>.</returns> private async Task <bool> AddBan(Cmd c) { // Kickban user immediately using internal QL command await _sst.QlCommands.CustCmdKickban(Helpers.GetArgVal(c, 2)); if (_banDb.UserAlreadyBanned(Helpers.GetArgVal(c, 2))) { var deleted = await DeleteIfExpired(Helpers.GetArgVal(c, 2)); if (deleted) { StatusMessage = string.Format("^5[TIMEBAN]^7 A previous ban for^3 {0}^7 has expired. Now removing." + " Re-add if you wish to re-ban.", Helpers.GetArgVal(c, 2)); await SendServerTell(c, StatusMessage); return(false); } var banInfo = _banDb.GetBanInfo(Helpers.GetArgVal(c, 2)); if (banInfo == null) { StatusMessage = "^1[ERROR]^3 Unable to retrieve ban information while attempting to add ban."; await SendServerTell(c, StatusMessage); return(false); } StatusMessage = string.Format( "^5[TIMEBAN]^7 Time-ban already exists for player: ^3{0}^7, who was banned by admin: ^3{1}^7 on ^1{2}^7." + " Ban will expire on: ^2{3}.^7 Use ^3{4}{5} del {0}^7 to remove ban.", Helpers.GetArgVal(c, 2), banInfo.BannedBy, banInfo.BanAddedDate.ToString("G", DateTimeFormatInfo.InvariantInfo), banInfo.BanExpirationDate.ToString("G", DateTimeFormatInfo.InvariantInfo), CommandList.GameCommandPrefix, ((c.FromIrc) ? (string.Format("{0} {1}", c.CmdName, c.Args[1])) : c.CmdName)); await SendServerTell(c, StatusMessage); return(false); } // length was already verified to be a double in Eval method var length = double.Parse(Helpers.GetArgVal(c, 3)); var scale = Helpers.GetArgVal(c, 4); var expirationDate = ExpirationDateGenerator.GenerateExpirationDate(length, scale); if ( _banDb.AddUserToDb(Helpers.GetArgVal(c, 2), c.FromUser, DateTime.Now, expirationDate, BanType.AddedByAdmin) == UserDbResult.Success) { StatusMessage = string.Format( "^2[SUCCESS]^7 Added time-ban for player: {0}. Ban will expire in {1} {2} on {3}", Helpers.GetArgVal(c, 2), Math.Truncate(length), scale, expirationDate.ToString("G", DateTimeFormatInfo.InvariantInfo)); await SendServerSay(c, StatusMessage); // UI: reflect changes _sst.UserInterface.RefreshCurrentBansDataSource(); return(true); } StatusMessage = string.Format( "^1[ERROR]^3 An error occurred while attempting to add a time-ban for player:^1 {0}", Helpers.GetArgVal(c, 2)); await SendServerTell(c, StatusMessage); return(false); }