mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-02-17 18:39:07 +00:00
【UPDATE 1.7.4a】
**🆕 What's new and what's changed:**
- Exposed event `OnAdminShowActivity` - fire when the function of informing players of admin action is performed
- Exposed `ShowAdminActivity`
- Added module to integration with AntiDLL
- Added module to integration with Redis (plugin send info about penalties between all servers)
512 lines
21 KiB
C#
512 lines
21 KiB
C#
using CounterStrikeSharp.API;
|
|
using CounterStrikeSharp.API.Core;
|
|
using CounterStrikeSharp.API.Modules.Admin;
|
|
using CounterStrikeSharp.API.Modules.Commands;
|
|
using CounterStrikeSharp.API.Modules.Entities;
|
|
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
|
using CS2_SimpleAdmin.Managers;
|
|
using CS2_SimpleAdmin.Menus;
|
|
using CS2_SimpleAdminApi;
|
|
|
|
namespace CS2_SimpleAdmin;
|
|
|
|
public partial class CS2_SimpleAdmin
|
|
{
|
|
[RequiresPermissions("@css/ban")]
|
|
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnBanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
if (command.ArgCount < 2)
|
|
return;
|
|
|
|
var targets = GetTarget(command);
|
|
if (targets == null) return;
|
|
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, IsHLTV: false }).ToList();
|
|
|
|
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var reason = command.ArgCount >= 3
|
|
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
|
|
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
var time = Helper.ParsePenaltyTime(command.GetArg(2));
|
|
|
|
playersToTarget.ForEach(player =>
|
|
{
|
|
if (!caller.CanTarget(player)) return;
|
|
|
|
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
|
{
|
|
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_ban"] ?? "Ban"}: {player.PlayerName}", player,
|
|
ManagePlayersMenu.BanMenu);
|
|
return;
|
|
}
|
|
|
|
Ban(caller, player, time, reason, callerName, BanManager, command);
|
|
});
|
|
}
|
|
|
|
internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null, bool silent = false)
|
|
{
|
|
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
if (!caller.CanTarget(player)) return;
|
|
if (!CheckValidBan(caller, time)) return;
|
|
|
|
// Set default caller name if not provided
|
|
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
? caller.PlayerName
|
|
: (_localizer?["sa_console"] ?? "Console");
|
|
|
|
// Get player and admin information
|
|
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
|
|
// Asynchronously handle banning logic
|
|
Task.Run(async () =>
|
|
{
|
|
int? penaltyId = await BanManager.BanPlayer(playerInfo, adminInfo, reason, time);
|
|
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
});
|
|
|
|
// Update banned players list
|
|
if (playerInfo.IpAddress != null && !BannedPlayers.Contains(playerInfo.IpAddress))
|
|
BannedPlayers.Add(playerInfo.IpAddress);
|
|
if (!BannedPlayers.Contains(player.SteamID.ToString()))
|
|
BannedPlayers.Add(player.SteamID.ToString());
|
|
|
|
// Determine message keys and arguments based on ban time
|
|
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
|
|
? ("sa_player_ban_message_perm", "sa_admin_ban_message_perm",
|
|
[reason, "CALLER"],
|
|
["CALLER", player.PlayerName, reason])
|
|
: ("sa_player_ban_message_time", "sa_admin_ban_message_time",
|
|
new object[] { reason, time, "CALLER" },
|
|
new object[] { "CALLER", player.PlayerName, reason, time });
|
|
|
|
// Display center message to the player
|
|
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
|
|
|
|
// Display admin activity message if necessary
|
|
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
{
|
|
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
}
|
|
|
|
// Schedule a kick timer
|
|
if (player.UserId.HasValue)
|
|
{
|
|
Helper.KickPlayer(player.UserId.Value, NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKBANADDED, Config.OtherSettings.KickTime);
|
|
}
|
|
|
|
// Execute ban command if necessary
|
|
if (UnlockedCommands)
|
|
{
|
|
Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}");
|
|
}
|
|
|
|
if (!silent)
|
|
{
|
|
if (command == null)
|
|
Helper.LogCommand(caller, $"css_ban {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
else
|
|
Helper.LogCommand(caller, command);
|
|
}
|
|
|
|
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Ban, _localizer);
|
|
}
|
|
|
|
internal void AddBan(CCSPlayerController? caller, SteamID steamid, int time, string reason, BanManager? banManager = null)
|
|
{
|
|
// Set default caller name if not provided
|
|
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
? caller.PlayerName
|
|
: (_localizer?["sa_console"] ?? "Console");
|
|
|
|
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
|
|
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
|
|
if (player != null && player.IsValid)
|
|
{
|
|
if (!caller.CanTarget(player))
|
|
return;
|
|
|
|
Ban(caller, player, time, reason, callerName, silent: true);
|
|
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
}
|
|
else
|
|
{
|
|
if (!caller.CanTarget(steamid))
|
|
return;
|
|
|
|
// Asynchronous ban operation if player is not online or not found
|
|
Task.Run(async () =>
|
|
{
|
|
int? penaltyId = await BanManager.AddBanBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
|
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
});
|
|
|
|
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Ban, _localizer);
|
|
}
|
|
}
|
|
|
|
[RequiresPermissions("@css/ban")]
|
|
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnAddBanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
if (Database == null) return;
|
|
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
|
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
|
{
|
|
command.ReplyToCommand("Invalid SteamID64.");
|
|
return;
|
|
}
|
|
|
|
var steamid = steamId.SteamId64.ToString();
|
|
var reason = command.ArgCount >= 3
|
|
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
|
|
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
|
|
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
|
|
if (!CheckValidBan(caller, time)) return;
|
|
|
|
var adminInfo = caller != null && caller.UserId.HasValue
|
|
? PlayersInfo[caller.UserId.Value]
|
|
: null;
|
|
|
|
var matches = Helper.GetPlayerFromSteamid64(steamid);
|
|
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
|
|
if (player != null && player.IsValid)
|
|
{
|
|
if (!caller.CanTarget(player))
|
|
return;
|
|
|
|
Ban(caller, player, time, reason, callerName, silent: true);
|
|
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
}
|
|
else
|
|
{
|
|
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
|
return;
|
|
|
|
// Asynchronous ban operation if player is not online or not found
|
|
Task.Run(async () =>
|
|
{
|
|
int? penaltyId = await BanManager.AddBanBySteamid(steamid, adminInfo, reason, time);
|
|
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
});
|
|
|
|
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Ban, _localizer);
|
|
|
|
command.ReplyToCommand($"Player with steamid {steamid} is not online. Ban has been added offline.");
|
|
}
|
|
|
|
Helper.LogCommand(caller, command);
|
|
|
|
if (UnlockedCommands)
|
|
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
|
|
}
|
|
|
|
[RequiresPermissions("@css/ban")]
|
|
[CommandHelper(minArgs: 1, usage: "<ip> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnBanIpCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
if (Database == null) return;
|
|
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
|
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
var ipAddress = command.GetArg(1);
|
|
|
|
if (!Helper.IsValidIp(ipAddress))
|
|
{
|
|
command.ReplyToCommand($"Invalid IP address.");
|
|
return;
|
|
}
|
|
|
|
var reason = command.ArgCount >= 3
|
|
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
|
|
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
|
|
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
|
|
if (!CheckValidBan(caller, time)) return;
|
|
|
|
var adminInfo = caller != null && caller.UserId.HasValue
|
|
? PlayersInfo[caller.UserId.Value]
|
|
: null;
|
|
|
|
var matches = Helper.GetPlayerFromIp(ipAddress);
|
|
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
|
|
if (player != null && player.IsValid)
|
|
{
|
|
if (!caller.CanTarget(player))
|
|
return;
|
|
|
|
Ban(caller, player, time, reason, callerName, silent: true);
|
|
}
|
|
else
|
|
{
|
|
// Asynchronous ban operation if player is not online or not found
|
|
Task.Run(async () =>
|
|
{
|
|
await BanManager.AddBanByIp(ipAddress, adminInfo, reason, time);
|
|
});
|
|
|
|
command.ReplyToCommand($"Player with ip {ipAddress} is not online. Ban has been added offline.");
|
|
}
|
|
|
|
Helper.LogCommand(caller, command);
|
|
}
|
|
|
|
private bool CheckValidBan(CCSPlayerController? caller, int duration)
|
|
{
|
|
if (caller == null) return true;
|
|
|
|
var canPermBan = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permban");
|
|
|
|
if (duration <= 0 && canPermBan == false)
|
|
{
|
|
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_perm_restricted"]}");
|
|
return false;
|
|
}
|
|
|
|
if (duration <= Config.OtherSettings.MaxBanDuration || canPermBan) return true;
|
|
|
|
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_max_duration_exceeded", Config.OtherSettings.MaxBanDuration]}");
|
|
return false;
|
|
}
|
|
|
|
[RequiresPermissions("@css/unban")]
|
|
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
if (Database == null) return;
|
|
|
|
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
|
|
|
if (command.GetArg(1).Length <= 1)
|
|
{
|
|
command.ReplyToCommand($"Too short pattern to search.");
|
|
return;
|
|
}
|
|
|
|
var pattern = command.GetArg(1);
|
|
var reason = command.ArgCount >= 2
|
|
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
|
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
|
|
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
|
|
Task.Run(async () => await BanManager.UnbanPlayer(pattern, callerSteamId, reason));
|
|
|
|
Helper.LogCommand(caller, command);
|
|
|
|
command.ReplyToCommand($"Unbanned player with pattern {pattern}.");
|
|
}
|
|
|
|
[RequiresPermissions("@css/kick")]
|
|
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnWarnCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
if (Database == null)
|
|
return;
|
|
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
if (command.ArgCount < 2)
|
|
return;
|
|
|
|
var targets = GetTarget(command);
|
|
if (targets == null) return;
|
|
var playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.PlayerConnected && !player.IsHLTV).ToList();
|
|
|
|
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
WarnManager warnManager = new(Database);
|
|
|
|
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
var reason = command.ArgCount >= 3
|
|
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
|
|
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
|
|
playersToTarget.ForEach(player =>
|
|
{
|
|
if (caller!.CanTarget(player))
|
|
{
|
|
Warn(caller, player, time, reason, callerName, warnManager, command);
|
|
}
|
|
});
|
|
}
|
|
|
|
internal void Warn(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, WarnManager? warnManager = null, CommandInfo? command = null)
|
|
{
|
|
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
if (!caller.CanTarget(player)) return;
|
|
if (!CheckValidBan(caller, time)) return;
|
|
|
|
// Set default caller name if not provided
|
|
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
? caller.PlayerName
|
|
: (_localizer?["sa_console"] ?? "Console");
|
|
|
|
// Freeze player pawn if alive
|
|
if (player.PawnIsAlive)
|
|
{
|
|
player.Pawn.Value?.Freeze();
|
|
AddTimer(5.0f, () => player.Pawn.Value?.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
}
|
|
|
|
// Get player and admin information
|
|
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
|
|
// Asynchronously handle warning logic
|
|
Task.Run(async () =>
|
|
{
|
|
warnManager ??= new WarnManager(Database);
|
|
int? penaltyId = await warnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
|
|
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
|
|
|
// Check for warn thresholds and execute punish command if applicable
|
|
var totalWarns = await warnManager.GetPlayerWarnsCount(player.SteamID.ToString());
|
|
if (Config.WarnThreshold.Count > 0)
|
|
{
|
|
string? punishCommand = null;
|
|
var lastKey = Config.WarnThreshold.Keys.Max();
|
|
|
|
if (totalWarns >= lastKey)
|
|
punishCommand = Config.WarnThreshold[lastKey];
|
|
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
|
|
punishCommand = value;
|
|
|
|
if (!string.IsNullOrEmpty(punishCommand))
|
|
{
|
|
await Server.NextFrameAsync(() =>
|
|
{
|
|
Server.ExecuteCommand(punishCommand.Replace("USERID", playerInfo.UserId.ToString()).Replace("STEAMID64", playerInfo.SteamId?.ToString()));
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// Determine message keys and arguments based on warning time
|
|
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
|
|
? ("sa_player_warn_message_perm", "sa_admin_warn_message_perm",
|
|
new object[] { reason, "CALLER" },
|
|
new object[] { "CALLER", player.PlayerName, reason })
|
|
: ("sa_player_warn_message_time", "sa_admin_warn_message_time",
|
|
[reason, time, "CALLER"],
|
|
["CALLER", player.PlayerName, reason, time]);
|
|
|
|
// Display center message to the playser
|
|
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
|
|
|
|
// Display admin activity message if necessary
|
|
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
{
|
|
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
}
|
|
|
|
// Log the warning command
|
|
if (command == null)
|
|
Helper.LogCommand(caller, $"css_warn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
else
|
|
Helper.LogCommand(caller, command);
|
|
|
|
// Send Discord notification for the warning
|
|
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Warn, _localizer);
|
|
}
|
|
|
|
internal void AddWarn(CCSPlayerController? caller, SteamID steamid, int time, string reason, WarnManager? warnManager = null)
|
|
{
|
|
// Set default caller name if not provided
|
|
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
? caller.PlayerName
|
|
: (_localizer?["sa_console"] ?? "Console");
|
|
|
|
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
|
|
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
|
|
if (player != null && player.IsValid)
|
|
{
|
|
if (!caller.CanTarget(player))
|
|
return;
|
|
|
|
Warn(caller, player, time, reason, callerName);
|
|
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
}
|
|
else
|
|
{
|
|
if (!caller.CanTarget(steamid))
|
|
return;
|
|
|
|
// Asynchronous ban operation if player is not online or not found
|
|
Task.Run(async () =>
|
|
{
|
|
int? penaltyId = await WarnManager.AddWarnBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
|
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
|
|
|
// Check for warn thresholds and execute punish command if applicable
|
|
var totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64.ToString());
|
|
if (Config.WarnThreshold.Count > 0)
|
|
{
|
|
string? punishCommand = null;
|
|
var lastKey = Config.WarnThreshold.Keys.Max();
|
|
|
|
if (totalWarns >= lastKey)
|
|
punishCommand = Config.WarnThreshold[lastKey];
|
|
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
|
|
punishCommand = value;
|
|
|
|
if (!string.IsNullOrEmpty(punishCommand))
|
|
{
|
|
await Server.NextFrameAsync(() =>
|
|
{
|
|
Server.ExecuteCommand(punishCommand.Replace("STEAMID64", steamid.SteamId64.ToString()));
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Warn, _localizer);
|
|
}
|
|
}
|
|
|
|
[RequiresPermissions("@css/kick")]
|
|
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
public void OnUnwarnCommand(CCSPlayerController? caller, CommandInfo command)
|
|
{
|
|
if (Database == null) return;
|
|
|
|
if (command.GetArg(1).Length <= 1)
|
|
{
|
|
command.ReplyToCommand($"Too short pattern to search.");
|
|
return;
|
|
}
|
|
|
|
var pattern = command.GetArg(1);
|
|
|
|
Task.Run(async () => await WarnManager.UnwarnPlayer(pattern));
|
|
|
|
Helper.LogCommand(caller, command);
|
|
command.ReplyToCommand($"Unwarned player with pattern {pattern}.");
|
|
}
|
|
} |