Exemple #1
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <returns><c>true</c> if the command was successfully executed, otherwise <c>false</c>.</returns>
        /// <remarks>Helpers.GetArgVal(c, 1) if specified: user to check</remarks>
        public async Task <bool> ExecAsync(Cmd c)
        {
            StatusMessage = c.Args.Length > ((c.FromIrc) ? 2 : 1)
                ? string.Format("^5{0}'s^7 user level is: ^5[{1}]", Helpers.GetArgVal(c, 1),
                                _users.GetUserLevel(Helpers.GetArgVal(c, 1)))
                : string.Format("^5{0}'s^7 user level is: ^5[{1}]", c.FromUser,
                                _users.GetUserLevel(c.FromUser));
            await SendServerSay(c, StatusMessage);

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Checks whether sufficient time has elapsed since the user last issued a command.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <returns><c>true</c> if sufficient time has elapsed, otherwise <c>false</c>.</returns>
        private bool SufficientTimeElapsed(string user)
        {
            if (!Helpers.KeyExists(user, _playerCommandTime) || _users.GetUserLevel(user) >= UserLevel.Admin)
            {
                return(true);
            }

            var cfg = _cfgHandler.ReadConfiguration();

            return(_playerCommandTime[user]
                   .AddSeconds(cfg.CoreOptions.requiredTimeBetweenCommands) < DateTime.Now);
        }
Exemple #3
0
        /// <summary>
        /// Verifies the user's registration date and kicks the user if the requirement is not met.
        /// </summary>
        /// <param name="user">The user.</param>
        /// <param name="regDate">The user's registration date.</param>
        private async Task VerifyUserDate(string user, DateTime regDate)
        {
            if (regDate == default(DateTime))
            {
                return;
            }
            if (_userDb.GetUserLevel(user) >= UserLevel.SuperUser)
            {
                return;
            }

            if ((DateTime.Now - regDate).TotalDays < MinimumDaysRequired)
            {
                if (_configHandler.ReadConfiguration().AccountDateOptions.showKickSoonMessage)
                {
                    await _sst.QlCommands.QlCmdSay(string.Format(
                                                       "^3[=> KICK SOON]: ^1{0}^7 (QL account date:^1 {1}^7)'s account is too new and does not meet the limit of ^2{2} ^7days",
                                                       user, regDate.ToString("d"), MinimumDaysRequired), false);
                }

                // Inform the user as a courtesy
                await _sst.QlCommands.QlCmdDelayedTell(
                    string.Format(
                        "^3You will be kicked because your account is too new (^1{0}^3) and doesn't meet this server's limit of ^1{1}^3 days.",
                        regDate.ToString("d"), MinimumDaysRequired), user, _kickTellDelaySecs);

                await _sst.QlCommands.CustCmdDelayedKickban(user, (_kickDelaySecs + 2));

                Log.Write(string.Format(
                              "Player {0}'s account is newer than minimum of {1} days that is required. Date created: {2}. Will attempt to kick player.",
                              user, MinimumDaysRequired,
                              regDate.ToString("G", DateTimeFormatInfo.InvariantInfo)), _logClassType, _logPrefix);
            }
        }
Exemple #4
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <returns><c>true</c> if the command was successfully executed, otherwise <c>false</c>.</returns>
        public async Task <bool> ExecAsync(Cmd c)
        {
            var todelUserLevel = _users.GetUserLevel(Helpers.GetArgVal(c, 1));
            var result         = _users.DeleteUserFromDb(Helpers.GetArgVal(c, 1), c.FromUser,
                                                         _users.GetUserLevel(c.FromUser));

            if (result == UserDbResult.Success)
            {
                StatusMessage = string.Format("^2[SUCCESS]^7 Removed user^2 {0}^7 from the^2 [{1}] ^7group.",
                                              Helpers.GetArgVal(c, 1), todelUserLevel);
                await SendServerSay(c, StatusMessage);

                // UI: reflect changes
                _sst.UserInterface.RefreshCurrentSstUsersDataSource();

                // de-op
                if (!_sst.IsMonitoringServer)
                {
                    return(true);
                }
                if (!_sst.ServerInfo.CurrentPlayers.ContainsKey(Helpers.GetArgVal(c, 1)))
                {
                    return(true);
                }
                var id = _sst.ServerEventProcessor.GetPlayerId(Helpers.GetArgVal(c, 1));
                if (id != -1)
                {
                    // doesn't matter if not opped, since QL shows no error message
                    await _sst.QlCommands.SendToQlAsync(string.Format("deop {0}", id), false);
                }

                return(true);
            }

            StatusMessage = string.Format(
                "^1[ERROR]^3 Unable to remove user^1 {0}^3 from the ^1[{1}]^3 group. Code:^1 {2}",
                Helpers.GetArgVal(c, 1), todelUserLevel, result);
            await SendServerTell(c, StatusMessage);

            return(false);
        }
Exemple #5
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <returns><c>true</c> if the command was successfully executed, otherwise <c>false</c>.</returns>
        public async Task <bool> ExecAsync(Cmd c)
        {
            if (!Helpers.GetArgVal(c, 2).Equals("1") && !Helpers.GetArgVal(c, 2).Equals("2") &&
                !Helpers.GetArgVal(c, 2).Equals("3"))
            {
                await DisplayArgLengthError(c);

                return(false);
            }
            if ((Helpers.GetArgVal(c, 2).Equals("3")))
            {
                var userLevel = IsIrcOwner(c) ? UserLevel.Owner : _users.GetUserLevel(c.FromUser);
                if (userLevel != UserLevel.Owner)
                {
                    StatusMessage = "^1[ERROR]^3 Only owners can add admins.";
                    await SendServerTell(c, StatusMessage);

                    Log.Write(string.Format("Non-owner {0} attempted to add an admin from {1} Ignoring.",
                                            c.FromUser, ((c.FromIrc) ? "IRC." : "in-game.")), _logClassType, _logPrefix);

                    return(false);
                }
            }
            var date   = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var result = _users.AddUserToDb(Helpers.GetArgVal(c, 1),
                                            (UserLevel)Convert.ToInt32(Helpers.GetArgVal(c, 2)), c.FromUser,
                                            date);

            if (result == UserDbResult.Success)
            {
                StatusMessage = string.Format("^2[SUCCESS]^7 Added user^2 {0} ^7to the ^2[{1}] ^7group.",
                                              Helpers.GetArgVal(c, 1), (UserLevel)Convert.ToInt32(Helpers.GetArgVal(c, 2)));
                await SendServerSay(c, StatusMessage);

                // UI: reflect changes
                _sst.UserInterface.RefreshCurrentSstUsersDataSource();

                // Auto-op if necessary
                if ((UserLevel)Convert.ToInt32(Helpers.GetArgVal(c, 2)) > UserLevel.SuperUser)
                {
                    await _sst.ServerEventProcessor.AutoOpActiveAdmin(Helpers.GetArgVal(c, 1));
                }

                return(true);
            }

            StatusMessage = string.Format(
                "^1[ERROR]^3 Unable to add user ^1{0}^3 to the ^1[{1}] ^3group. Code:^1 {2}",
                Helpers.GetArgVal(c, 1), (UserLevel)Convert.ToInt32(Helpers.GetArgVal(c, 2)), result);
            await SendServerTell(c, StatusMessage);

            return(false);
        }
Exemple #6
0
        /// <summary>
        /// Evaluates the ban addition command and executes it if all parameters are correct.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <returns>
        /// <c>true</c> if the ban addition evaluation successfully passed, otherwise <c>false</c>.
        /// </returns>
        private async Task <bool> EvalBanAddition(Cmd c)
        {
            // !timeban add user # scale
            if (c.Args.Length != (c.FromIrc ? 6 : 5))
            {
                StatusMessage =
                    string.Format(
                        "^1[ERROR]^3 Usage: {0}{1} <add> <name> <time> <scale> - name is without clan, time is a number," +
                        " scale: secs, mins, hours, days, months, or years.",
                        CommandList.GameCommandPrefix,
                        ((c.FromIrc) ? (string.Format("{0} {1}", c.CmdName, c.Args[1])) : c.CmdName));
                await SendServerTell(c, StatusMessage);

                return(false);
            }
            double time;

            if (!double.TryParse(Helpers.GetArgVal(c, 3), out time) || time <= 0)
            {
                StatusMessage = "^1[ERROR]^3 Time must be a positive number!";
                await SendServerTell(c, StatusMessage);

                return(false);
            }
            if (time > int.MaxValue)
            {
                // Just compare to int type's max size as in case of month and year it has to be
                // converted to int and can't be double anyway
                StatusMessage = "^1[ERROR]^3 Time is too large!";
                await SendServerTell(c, StatusMessage);

                return(false);
            }
            var validScale = Helpers.ValidTimeScales.Contains(Helpers.GetArgVal(c, 4));

            if (!validScale)
            {
                StatusMessage = "^1[ERROR]^3 Scale must be: secs, mins, hours, days, months, OR years";
                await SendServerTell(c, StatusMessage);

                return(false);
            }
            if (_userDb.GetUserLevel(Helpers.GetArgVal(c, 2)) >= UserLevel.Admin)
            {
                StatusMessage = "^1[ERROR]^3 Users with user level admin or higher may not be time-banned!";
                await SendServerTell(c, StatusMessage);

                return(false);
            }

            return(await AddBan(c));
        }
Exemple #7
0
        /// <summary>
        /// Determines whether the vote is an attempted clientkick of an administrator.
        /// </summary>
        /// <param name="details">The vote details.</param>
        /// <returns>
        /// <c>true</c> if the attempted clientkick is a kick of an administrator, otherwise <c>false</c>.
        /// </returns>
        private bool IsAdminClientKickAttempt(Match details)
        {
            var type    = details.Groups["votetype"].Value;
            var votearg = details.Groups["votearg"].Value;

            if (!type.Equals("clientkick", StringComparison.InvariantCultureIgnoreCase))
            {
                return(false);
            }
            int id;

            if (!int.TryParse(votearg, out id))
            {
                return(false);
            }
            var user = _sst.ServerEventProcessor.GetPlayerNameFromId(id);

            if (string.IsNullOrEmpty(user))
            {
                return(false);
            }

            return(_users.GetUserLevel(user) >= UserLevel.Admin);
        }
Exemple #8
0
        /// <summary>
        /// Processes the early quit.
        /// </summary>
        /// <param name="player">The player.</param>
        /// <param name="doublePenalty">
        /// if set to <c>true</c> double the penalty for particularly egregious early quits (i.e.
        /// during countdown).
        /// </param>
        private async Task ProcessEarlyQuit(string player, bool doublePenalty)
        {
            if (_usersDb.GetUserLevel(player) >= UserLevel.SuperUser)
            {
                Log.Write(string.Format(
                              "Player {0} quit early, but will not be evaluated for early quitting due to excluded userlevel",
                              player), _logClassType, _logPrefix);
                return;
            }
            if (_quitsDb.UserExistsInDb(player))
            {
                _quitsDb.IncrementUserQuitCount(player, doublePenalty);

                // UI: reflect changes
                _sst.UserInterface.RefreshCurrentQuittersDataSource();
            }
            else
            {
                _quitsDb.AddUserToDb(player, doublePenalty);

                // UI: reflect changes
                _sst.UserInterface.RefreshCurrentQuittersDataSource();
            }

            var qCount = await EvaluateUserQuitCount(player);

            if (doublePenalty)
            {
                await
                _sst.QlCommands.QlCmdSay(
                    string.Format(
                        "^3{0}'s^7 penalty was doubled for unbalancing teams during match start!",
                        player), false);

                Log.Write(string.Format("Active player {0} left during count-down. Penalty will be doubled.",
                                        player), _logClassType, _logPrefix);
            }
            // Only show the log msg if we're not banning the user this time (ban msg is shown in
            // that case)
            if (qCount < _maxQuitsAllowed)
            {
                await
                _sst.QlCommands.QlCmdSay(
                    string.Format("^5[EARLYQUIT]^7 Early quit detected and logged for player ^3{0}",
                                  player), false);
            }
        }
Exemple #9
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <returns><c>true</c> if the command was successfully executed, otherwise <c>false</c>.</returns>
        public async Task <bool> ExecAsync(Cmd c)
        {
            var userDb          = new DbUsers();
            var senderLevel     = userDb.GetUserLevel(c.FromUser);
            var senderLevelName = Enum.GetName(typeof(UserLevel), senderLevel);
            var cmds            = new StringBuilder();

            foreach (var cmd in _sst.CommandProcessor.Commands.Where(cmd => cmd.Value.UserLevel <= senderLevel))
            {
                cmds.Append(string.Format("^3{0}^5{1} ", CommandList.GameCommandPrefix, cmd.Key));
            }

            StatusMessage = string.Format(
                "^7Your user level - ^3{0}^7 - has access to these commands: {1}," +
                " ^7More help @ ^3sst.syncore.org^7, or ^3#sst^7 on QuakeNet.",
                (senderLevelName ?? "NONE"), cmds.ToString().TrimEnd(' '));
            await SendServerTell(c, StatusMessage);

            return(true);
        }
Exemple #10
0
        /// <summary>
        /// Automatically gives operator status using QL's internal op system to the specified
        /// player who is currently on the server and is an SST user with userlevel Admin or higher.
        /// </summary>
        public async Task AutoOpActiveAdmin(string player)
        {
            if (!_sst.IsMonitoringServer)
            {
                return;
            }

            var cfgHandler = new ConfigHandler();
            var cfg        = cfgHandler.ReadConfiguration();

            if (!cfg.CoreOptions.autoOpAdmins)
            {
                return;
            }

            var userDb    = new DbUsers();
            var userLevel = userDb.GetUserLevel(player);

            if (userLevel <= UserLevel.SuperUser)
            {
                return;
            }
            if (!_sst.ServerInfo.CurrentPlayers.ContainsKey(player))
            {
                return;
            }

            var id = GetPlayerId(player);

            if (id == -1)
            {
                return;
            }

            await _sst.QlCommands.SendToQlAsync(string.Format("op {0}", id), false);

            Log.Write(string.Format("Auto-opping {0} (user level: {1})",
                                    player, userLevel), _logClassType, _logPrefix);
        }
Exemple #11
0
        /// <summary>
        /// Executes the specified command.
        /// </summary>
        /// <param name="c">The cmd args.</param>
        /// <returns>
        /// <c>true</c> if the command was successfully executed, otherwise returns <c>false</c>.
        /// </returns>
        public bool Exec(Cmd c)
        {
            if (_sst.ServerInfo.CurrentPlayers.Count == 0)
            {
                _irc.SendIrcMessage(_irc.IrcSettings.ircChannel,
                                    "My server has no players at this time.");
            }
            else
            {
                var sb = new StringBuilder();
                foreach (var player in _sst.ServerInfo.CurrentPlayers)
                {
                    sb.Append(string.Format("\u0003\u0002{0}\u0002 ({1}), ",
                                            player.Key, _usersDb.GetUserLevel(player.Key)));
                }

                _irc.SendIrcMessage(_irc.IrcSettings.ircChannel,
                                    string.Format("\u0003My server's current players have the following access levels: {0}",
                                                  sb.ToString().TrimEnd(',', ' ')));
            }

            return(true);
        }
Exemple #12
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        public async Task <bool> ExecAsync(Cmd c)
        {
            if (!_sst.Mod.Pickup.Active)
            {
                StatusMessage = string.Format(
                    "^1[ERROR]^3 Pickup module is not active. An admin must first load it with:^7 {0}{1} {2}",
                    CommandList.GameCommandPrefix,
                    ((c.FromIrc)
                        ? (string.Format("{0} {1}",
                                         IrcCommandList.IrcCmdQl, CommandList.CmdModule))
                        : CommandList.CmdModule),
                    ModuleCmd.PickupArg);
                await SendServerTell(c, StatusMessage);

                Log.Write(
                    string.Format(
                        "{0} attempted {1} command from {2}, but {3} module is not loaded. Ignoring.",
                        c.FromUser, c.CmdName, ((c.FromIrc) ? "from IRC" : "from in-game"),
                        ModuleCmd.PickupArg), _logClassType, _logPrefix);

                return(false);
            }

            if (!Helpers.GetArgVal(c, 1).Equals("reset") && !Helpers.GetArgVal(c, 1).Equals("start") &&
                !Helpers.GetArgVal(c, 1).Equals("stop") &&
                !Helpers.GetArgVal(c, 1).Equals("unban") && !Helpers.GetArgVal(c, 1).Equals("help"))
            {
                await DisplayArgLengthError(c);

                return(false);
            }
            // These arguments to the the pickup command require elevated privileges.
            if (Helpers.GetArgVal(c, 1).Equals("reset") || Helpers.GetArgVal(c, 1).Equals("start") ||
                Helpers.GetArgVal(c, 1).Equals("stop") || Helpers.GetArgVal(c, 1).Equals("unban"))
            {
                var userLevel = IsIrcOwner(c) ? UserLevel.Owner : _userDb.GetUserLevel(c.FromUser);
                if (userLevel < UserLevel.SuperUser)
                {
                    await DisplayInsufficientAccessError(c);

                    Log.Write(
                        string.Format(
                            "{0} attempted to use a {1} command with args that require a higher user level than {0} has. Ignoring.",
                            c.FromUser, c.CmdName), _logClassType, _logPrefix);

                    return(false);
                }
            }
            if (Helpers.GetArgVal(c, 1).Equals("reset"))
            {
                return(await _sst.Mod.Pickup.Manager.EvalPickupReset(c));
            }
            if (Helpers.GetArgVal(c, 1).Equals("start"))
            {
                return(await _sst.Mod.Pickup.Manager.EvalPickupStart(c));
            }
            if (Helpers.GetArgVal(c, 1).Equals("stop"))
            {
                return(await _sst.Mod.Pickup.Manager.EvalPickupStop(c));
            }
            if (Helpers.GetArgVal(c, 1).Equals("unban"))
            {
                return(await _sst.Mod.Pickup.Manager.EvalPickupUnban(c));
            }
            if (Helpers.GetArgVal(c, 1).Equals("help"))
            {
                await DisplayPickupHelp(c);

                return(true);
            }
            return(false);
        }
Exemple #13
0
        /// <summary>
        /// Executes the specified command asynchronously.
        /// </summary>
        /// <param name="c">The command argument information.</param>
        /// <remarks>Helpers.GetArgVal(c, 1) if specified: user to check</remarks>
        public async Task <bool> ExecAsync(Cmd c)
        {
            // Must be a team gametype that is supported by QLRanks
            if (!_sst.ServerInfo.IsQlRanksGameType())
            {
                StatusMessage = "^1[ERROR]^3 Team balancing is not available on this server!";
                // send to everyone (/say; success)
                await SendServerSay(c, StatusMessage);

                Log.Write(string.Format(
                              "{0} attempted to request team balance suggestion, but server is running game type" +
                              " unsupported by QLRanks. Ignoring.", c.FromUser), _logClassType, _logPrefix);

                return(false);
            }

            // Disable this command if the pickup module is active
            if (_sst.Mod.Pickup.Active)
            {
                // send to everyone (/say; success)
                await SendServerSay(c, StatusMessage);

                StatusMessage = "^1[ERROR]^3 Team balancing is unavailable when pickup module is active!";

                Log.Write(string.Format(
                              "{0} attempted to request team balance suggestion, but balancing is unavailable when" +
                              " pickup module is active. Ignoring.", c.FromUser), _logClassType, _logPrefix);

                return(false);
            }

            await _sst.QlCommands.QlCmdSay("^2[TEAMBALANCE]^7 Please wait.... Calculating most even teams.", false);

            // Verify the teams (TEST)
            await _sst.QlCommands.QlCmdDelayedConfigStrings(1, 2);

            var blueTeam = _sst.ServerInfo.GetTeam(Team.Blue);
            var redTeam  = _sst.ServerInfo.GetTeam(Team.Red);

            if ((blueTeam.Count + redTeam.Count) % 2 != 0)
            {
                StatusMessage = "^1[ERROR]^3 Teams can only be suggested if there are a total even number of red and blue players!";
                // send to everyone (/say; success)
                await SendServerSay(c, StatusMessage);

                Log.Write(string.Format(
                              "{0} attempted to request team balance suggestion, but teams are uneven. Red ({1}), Blue ({2}), Rem ({3}). Ignoring.",
                              c.FromUser, blueTeam.Count, redTeam.Count, ((blueTeam.Count + redTeam.Count) % 2)), _logClassType, _logPrefix);

                return(false);
            }
            if ((blueTeam.Count + redTeam.Count) < 4)
            {
                StatusMessage = "^1[ERROR]^3 There must be at least 4 total players for the team suggestion!";
                // send to everyone (/say; success)
                await SendServerSay(c, StatusMessage);

                Log.Write(string.Format(
                              "{0} attempted to request team balance suggestion, but there are fewer than 4 players. Ignoring.",
                              c.FromUser), _logClassType, _logPrefix);

                return(false);
            }

            if (_sst.VoteManager.IsTeamSuggestionVotePending)
            {
                StatusMessage = "^1[ERROR]^3 A team balance vote is already pending!";
                // send to everyone (/say; success)
                await SendServerSay(c, StatusMessage);

                Log.Write(string.Format(
                              "{0} attempted to request team balance suggestion, but balance suggestion vote is already pending. Ignoring.",
                              c.FromUser), _logClassType, _logPrefix);

                return(false);
            }

            // SuperUser or higher... Force the vote
            if ((c.Args.Length == (c.FromIrc ? 3 : 2)) &&
                (Helpers.GetArgVal(c, 1).Equals("force", StringComparison.InvariantCultureIgnoreCase)))
            {
                var userLevel = IsIrcOwner(c) ? UserLevel.Owner : _users.GetUserLevel(c.FromUser);
                if (userLevel < UserLevel.SuperUser)
                {
                    StatusMessage = "^1[ERROR]^7 You do not have permission to use that command.";

                    Log.Write(string.Format(
                                  "{0} tried to force team balance suggestion, but has an insufficient access level. Ignoring.",
                                  c.FromUser), _logClassType, _logPrefix);

                    return(false);
                }

                Log.Write(string.Format("Player {0} with sufficient access level {1} forced balanced teams from {2}.",
                                        c.FromUser, Enum.GetName(typeof(UserLevel), userLevel),
                                        (c.FromIrc ? "IRC" : "in-game")), _logClassType, _logPrefix);

                await InitiateBalance(redTeam, blueTeam, true);

                return(true);
            }

            await InitiateBalance(redTeam, blueTeam, false);

            return(true);
        }
Exemple #14
0
        /// <summary>
        /// Kicks the player if player does not meet the server's elo requirements.
        /// </summary>
        /// <param name="player">The player.</param>
        private async Task KickPlayerIfEloNotMet(string player)
        {
            // Module values have(n't) been set?
            var hasMaxEloSpecified = MaximumRequiredElo != 0;
            var hasMinEloSpecified = MinimumRequiredElo != 0;

            if (!hasMinEloSpecified)
            {
                return;
            }

            // Elo limits don't apply to SuperUsers or higher
            if (_users.GetUserLevel(player) >= UserLevel.SuperUser)
            {
                return;
            }
            // Can't kick ourselves, though QL doesn't allow it anyway, don't show kick msg.
            if (player.Equals(_sst.AccountName, StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }
            // Get Elo for the current gametype
            var playerElo = QlRanksHelper.GetEloForGameType(_sst.ServerInfo, player);

            // Player Elo is either invalid or we're not in a QLRanks-supported gametype. Abort.
            if (playerElo == 0)
            {
                return;
            }
            // Handle minimum
            if (playerElo < MinimumRequiredElo)
            {
                Log.Write(
                    string.Format("{0}'s {1} Elo is less than minimum required ({2})...Will kick player shortly.",
                                  player,
                                  GameType.ToString().ToUpper(), MinimumRequiredElo), _logClassType, _logPrefix);

                if (_configHandler.ReadConfiguration().EloLimitOptions.showKickSoonMessage)
                {
                    await _sst.QlCommands.QlCmdSay(
                        string.Format(
                            "^3[=> KICK SOON]: ^1{0}^7 ({1} Elo:^1 {2}^7) does not meet this server's Elo requirements. Min:^2 {3} {4}",
                            player, GameType.ToString().ToUpper(), playerElo,
                            MinimumRequiredElo,
                            hasMaxEloSpecified ? string.Format("^7Max:^1 {0}", MaximumRequiredElo) : ""), false);
                }

                // Wait before notifying and kicking, so user's screen doesn't freeze on "awaiting
                // snapshot", especially when connecting
                await
                _sst.QlCommands.QlCmdDelayedTell(
                    string.Format(
                        "^3You will be kicked because your {0} QLRanks Elo (^1{1}^3) doesn't meet this server's requirements. Min: ^1{2} {3}",
                        GameType.ToString().ToUpper(), playerElo, MinimumRequiredElo,
                        hasMaxEloSpecified ? string.Format("^3Max:^1 {0}", MaximumRequiredElo) : ""), player, _kickTellDelaySecs);

                await _sst.QlCommands.CustCmdDelayedKickban(player, (_kickDelaySecs + 2));

                return;
            }
            // Handle range
            if (!hasMaxEloSpecified)
            {
                return;
            }
            if (playerElo <= MaximumRequiredElo)
            {
                return;
            }

            Log.Write(
                string.Format("{0}'s {1} Elo is greater than maximum allowed ({2})...Will kick player shortly.", player,
                              GameType.ToString().ToUpper(), MaximumRequiredElo), _logClassType, _logPrefix);

            if (_configHandler.ReadConfiguration().EloLimitOptions.showKickSoonMessage)
            {
                await _sst.QlCommands.QlCmdSay(
                    string.Format(
                        "^3[=> KICK SOON]: ^1{0}^7 ({1} Elo:^1 {2}^7) does not meet this server's Elo requirements. Min:^2 {3} ^7Max:^1 {4}",
                        player, GameType.ToString().ToUpper(), playerElo,
                        MinimumRequiredElo, MaximumRequiredElo), false);
            }

            await
            _sst.QlCommands.QlCmdDelayedTell(
                string.Format(
                    "^3You will be kicked because your {0} QLRanks Elo (^1{1}^3) doesn't meet this server's requirements. Min: ^1{2}^3 Max: ^1{3}",
                    GameType.ToString().ToUpper(), playerElo, MinimumRequiredElo, MaximumRequiredElo), player, _kickTellDelaySecs);

            await _sst.QlCommands.CustCmdDelayedKickban(player, (_kickDelaySecs + 2));
        }