From 229b8d73a3a3e30c6cd65cccc7949b5c661538aa Mon Sep 17 00:00:00 2001 From: Dawid Bepierszcz <41084667+daffyyyy@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:38:46 +0100 Subject: [PATCH] 1.3.4a - Minor changes - Escape kick reason @poggu suggestion - Auto-updater for config - Using UTC time - Added expiring IP bans after x days (`ExpireOldIpBans` in config => value = days, 0 = disabled) - Added exception message to database error - Fixed? ungag/unmute/unsilence commands - Updated css version to `178` - Changed `css_adminhelp` command to use new file `admin_help.txt` as output --- CS2-SimpleAdmin.cs | 12 +- CS2-SimpleAdmin.csproj | 6 +- Commands/basebans.cs | 21 +- Commands/basechat.cs | 8 +- Commands/basecommands.cs | 17 +- Commands/basecomms.cs | 59 ++++- Commands/basevotes.cs | 3 +- Commands/funcommands.cs | 8 +- Commands/playercommands.cs | 8 +- Config.cs | 5 +- Database/Database.cs | 4 +- Events.cs | 49 ++-- Helper.cs | 57 +++-- Managers/AdminSQLManager.cs | 423 ++++++++++++------------------- Managers/BanManager.cs | 334 +++++++++++++----------- Managers/MuteManager.cs | 336 +++++++++++------------- Managers/PlayerPenaltyManager.cs | 220 ++++++++-------- admin_help.txt | 36 +++ lang/ar.json | 1 - lang/en.json | 1 - lang/es.json | 1 - lang/fa.json | 1 - lang/fr.json | 1 - lang/lv.json | 1 - lang/pl.json | 1 - lang/pt-BR.json | 1 - lang/ru.json | 1 - lang/tr.json | 1 - lang/zh-Hans.json | 1 - 29 files changed, 802 insertions(+), 815 deletions(-) create mode 100644 admin_help.txt diff --git a/CS2-SimpleAdmin.cs b/CS2-SimpleAdmin.cs index 44148a7..27a89df 100644 --- a/CS2-SimpleAdmin.cs +++ b/CS2-SimpleAdmin.cs @@ -12,7 +12,7 @@ using System.Collections.Concurrent; namespace CS2_SimpleAdmin; -[MinimumApiVersion(168)] +[MinimumApiVersion(178)] public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig { public static CS2_SimpleAdmin Instance { get; private set; } = new(); @@ -38,7 +38,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig "CS2-SimpleAdmin"; public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)"; public override string ModuleAuthor => "daffyy & Dliix66"; - public override string ModuleVersion => "1.3.3a"; + public override string ModuleVersion => "1.3.4a"; public CS2_SimpleAdminConfig Config { get; set; } = new(); @@ -46,7 +46,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig - + @@ -24,5 +24,9 @@ + + + + diff --git a/Commands/basebans.cs b/Commands/basebans.cs index 994892f..01749c7 100644 --- a/Commands/basebans.cs +++ b/Commands/basebans.cs @@ -60,7 +60,6 @@ namespace CS2_SimpleAdmin if (_database == null) return; callerName ??= caller == null ? "Console" : caller.PlayerName; - banManager ??= new BanManager(_database, Config); if (player.PawnIsAlive) { @@ -85,6 +84,7 @@ namespace CS2_SimpleAdmin Task.Run(async () => { + banManager ??= new BanManager(_database, Config); await banManager.BanPlayer(playerInfo, adminInfo, reason, time); }); @@ -143,6 +143,7 @@ namespace CS2_SimpleAdmin [CommandHelper(minArgs: 1, usage: " [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnAddBanCommand(CCSPlayerController? caller, CommandInfo command) { + if (_database == null) return; string callerName = caller == null ? "Console" : caller.PlayerName; if (command.ArgCount < 2) return; @@ -243,9 +244,7 @@ namespace CS2_SimpleAdmin Task.Run(async () => { - Database database = new Database(dbConnectionString); - - BanManager _banManager = new(database, Config); + BanManager _banManager = new(_database, Config); await _banManager.AddBanBySteamid(steamid, adminInfo, reason, time); }); @@ -257,6 +256,7 @@ namespace CS2_SimpleAdmin [CommandHelper(minArgs: 1, usage: " [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnBanIp(CCSPlayerController? caller, CommandInfo command) { + if (_database == null) return; string callerName = caller == null ? "Console" : caller.PlayerName; if (command.ArgCount < 2) @@ -355,9 +355,7 @@ namespace CS2_SimpleAdmin Task.Run(async () => { - Database database = new Database(dbConnectionString); - - BanManager _banManager = new(database, Config); + BanManager _banManager = new(_database, Config); await _banManager.AddBanByIp(ipAddress, adminInfo, reason, time); }); @@ -369,6 +367,8 @@ namespace CS2_SimpleAdmin [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command) { + if (_database == null) return; + string callerName = caller == null ? "Console" : caller.PlayerName; if (command.GetArg(1).Length <= 1) { @@ -386,11 +386,8 @@ namespace CS2_SimpleAdmin string pattern = command.GetArg(1); - Database database = new Database(dbConnectionString); - - BanManager _banManager = new(database, Config); - - _ = _banManager.UnbanPlayer(pattern); + BanManager _banManager = new BanManager(_database, Config); + Task.Run(async () => await _banManager.UnbanPlayer(pattern)); command.ReplyToCommand($"Unbanned player with pattern {pattern}."); } diff --git a/Commands/basechat.cs b/Commands/basechat.cs index ffa81b7..7e03d6e 100644 --- a/Commands/basechat.cs +++ b/Commands/basechat.cs @@ -92,10 +92,10 @@ namespace CS2_SimpleAdmin playersToTarget.ForEach(player => { - player.PrintToChat(Helper.ReplaceTags($"({caller!.PlayerName}) {utf8String}")); + player.PrintToChat(StringExtensions.ReplaceColorTags($"({caller!.PlayerName}) {utf8String}")); }); - command.ReplyToCommand(Helper.ReplaceTags($" Private message sent!")); + command.ReplyToCommand(StringExtensions.ReplaceColorTags($" Private message sent!")); } [ConsoleCommand("css_csay", "Say to all players (in center).")] @@ -115,7 +115,7 @@ namespace CS2_SimpleAdmin Helper.LogCommand(caller, command); - Helper.PrintToCenterAll(Helper.ReplaceTags(utf8String)); + Helper.PrintToCenterAll(StringExtensions.ReplaceColorTags(utf8String)); } [ConsoleCommand("css_hsay", "Say to all players (in hud).")] @@ -137,7 +137,7 @@ namespace CS2_SimpleAdmin VirtualFunctions.ClientPrintAll( HudDestination.Alert, - Helper.ReplaceTags(utf8String), + StringExtensions.ReplaceColorTags(utf8String), 0, 0, 0, 0); } } diff --git a/Commands/basecommands.cs b/Commands/basecommands.cs index 24f7de9..7449f08 100644 --- a/Commands/basecommands.cs +++ b/Commands/basecommands.cs @@ -55,8 +55,9 @@ namespace CS2_SimpleAdmin [RequiresPermissions("@css/generic")] public void OnAdminHelpCommand(CCSPlayerController? caller, CommandInfo command) { - if (caller == null || !caller.IsValid) return; + //if (caller == null || !caller.IsValid) return; + /* using (new WithTemporaryCulture(caller.GetLanguage())) { var splitMessage = _localizer!["sa_adminhelp"].ToString().Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); @@ -65,6 +66,20 @@ namespace CS2_SimpleAdmin { caller.PrintToChat(Helper.ReplaceTags($" {line}")); } + } */ + + string[] lines = File.ReadAllLines(ModuleDirectory + "/admin_help.txt"); + + foreach (string line in lines) + { + if (string.IsNullOrWhiteSpace(line)) + { + command.ReplyToCommand(" "); + } + else + { + command.ReplyToCommand(StringExtensions.ReplaceColorTags(line)); + } } } diff --git a/Commands/basecomms.cs b/Commands/basecomms.cs index 9481749..b97b104 100644 --- a/Commands/basecomms.cs +++ b/Commands/basecomms.cs @@ -244,7 +244,12 @@ namespace CS2_SimpleAdmin playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Gag, DateTime.Now.AddMinutes(time), time); } } - _ = _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 0); + + Task.Run(async () => + { + await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 0); + }); + command.ReplyToCommand($"Gagged player with steamid {steamid}."); } @@ -277,6 +282,11 @@ namespace CS2_SimpleAdmin PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + Task.Run(async () => + { + await _muteManager.UnmutePlayer(pattern, 0); // Unmute by type 0 (gag) + }); + if (Helper.IsValidSteamID64(pattern)) { List matches = Helper.GetPlayerFromSteamid64(pattern); @@ -313,12 +323,6 @@ namespace CS2_SimpleAdmin } } } - if (found) - { - _ = _muteManager.UnmutePlayer(pattern, 0); // Unmute by type 0 (gag) - command.ReplyToCommand($"Ungaged player with pattern {pattern}."); - return; - } TargetResult? targets = GetTarget(command); if (targets == null) return; @@ -336,7 +340,11 @@ namespace CS2_SimpleAdmin playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Gag); if (player!.SteamID.ToString().Length == 17) - _ = _muteManager.UnmutePlayer(player.SteamID.ToString(), 0); // Unmute by type 0 (gag) + Task.Run(async () => + { + await _muteManager.UnmutePlayer(player.SteamID.ToString(), 0); // Unmute by type 0 (gag) + }); + if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); @@ -567,7 +575,12 @@ namespace CS2_SimpleAdmin } } } - _ = _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1); + + Task.Run(async () => + { + await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1); + }); + command.ReplyToCommand($"Muted player with steamid {steamid}."); } @@ -598,6 +611,11 @@ namespace CS2_SimpleAdmin MuteManager _muteManager = new(_database); PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + Task.Run(async () => + { + await _muteManager.UnmutePlayer(pattern, 1); // Unmute by type 1 (mute) + }); + if (Helper.IsValidSteamID64(pattern)) { List matches = Helper.GetPlayerFromSteamid64(pattern); @@ -630,12 +648,12 @@ namespace CS2_SimpleAdmin if (found) { - _ = _muteManager.UnmutePlayer(pattern, 1); // Unmute by type 1 (mute) command.ReplyToCommand($"Unmuted player with pattern {pattern}."); return; } TargetResult? targets = GetTarget(command); + if (targets == null) return; List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.SteamID.ToString().Length == 17 && !player.IsHLTV).ToList(); if (playersToTarget.Count > 1 && Config.DisableDangerousCommands || playersToTarget.Count == 0) @@ -648,7 +666,10 @@ namespace CS2_SimpleAdmin playersToTarget.ForEach(player => { if (player.SteamID.ToString().Length == 17) - _ = _muteManager.UnmutePlayer(player.SteamID.ToString(), 1); // Unmute by type 1 (mute) + Task.Run(async () => + { + await _muteManager.UnmutePlayer(player.SteamID.ToString(), 1); // Unmute by type 1 (mute) + }); playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Mute); player.VoiceFlags = VoiceFlags.Normal; @@ -890,7 +911,11 @@ namespace CS2_SimpleAdmin } } } - _ = _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2); + Task.Run(async () => + { + await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2); + }); + command.ReplyToCommand($"Silenced player with steamid {steamid}."); } @@ -921,6 +946,11 @@ namespace CS2_SimpleAdmin MuteManager _muteManager = new(_database); PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + Task.Run(async () => + { + await _muteManager.UnmutePlayer(pattern, 2); // Unmute by type 2 (silence) + }); + if (Helper.IsValidSteamID64(pattern)) { List matches = Helper.GetPlayerFromSteamid64(pattern); @@ -959,12 +989,13 @@ namespace CS2_SimpleAdmin if (found) { - _ = _muteManager.UnmutePlayer(pattern, 2); // Unmute by type 2 (silence) + //Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, 2); }); // Unmute by type 2 (silence) command.ReplyToCommand($"Unsilenced player with pattern {pattern}."); return; } TargetResult? targets = GetTarget(command); + if (targets == null) return; List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.SteamID.ToString().Length == 17 && !player.IsHLTV).ToList(); if (playersToTarget.Count > 1 && Config.DisableDangerousCommands || playersToTarget.Count == 0) @@ -977,7 +1008,7 @@ namespace CS2_SimpleAdmin playersToTarget.ForEach(player => { if (player.SteamID.ToString().Length == 17) - _ = _muteManager.UnmutePlayer(player.SteamID.ToString(), 2); // Unmute by type 2 (silence) + Task.Run(async () => { await _muteManager.UnmutePlayer(player.SteamID.ToString(), 2); }); // Unmute by type 2 (silence) if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); diff --git a/Commands/basevotes.cs b/Commands/basevotes.cs index 2cff60d..03965c1 100644 --- a/Commands/basevotes.cs +++ b/Commands/basevotes.cs @@ -52,12 +52,13 @@ namespace CS2_SimpleAdmin } voteMenu.PostSelectAction = PostSelectAction.Close; - MenuManager.OpenChatMenu(_player, voteMenu); Helper.PrintToCenterAll(_localizer!["sa_admin_vote_message", caller == null ? "Console" : caller.PlayerName, question]); StringBuilder sb = new(_localizer!["sa_prefix"]); sb.Append(_localizer["sa_admin_vote_message", caller == null ? "Console" : caller.PlayerName, question]); _player.PrintToChat(sb.ToString()); + + MenuManager.OpenChatMenu(_player, voteMenu); } } diff --git a/Commands/funcommands.cs b/Commands/funcommands.cs index 906dfa2..9f82bf4 100644 --- a/Commands/funcommands.cs +++ b/Commands/funcommands.cs @@ -41,7 +41,7 @@ namespace CS2_SimpleAdmin callerName ??= caller == null ? "Console" : caller.PlayerName; player!.Pawn.Value!.ToggleNoclip(); - Helper.LogCommand(caller, $"css_noclip {player?.PlayerName}"); + Helper.LogCommand(caller, $"css_noclip {player.PlayerName}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -90,9 +90,9 @@ namespace CS2_SimpleAdmin { callerName ??= caller == null ? "Console" : caller.PlayerName; - player!.Pawn.Value!.Freeze(); + player.Pawn.Value!.Freeze(); - Helper.LogCommand(caller, $"css_freeze {player?.PlayerName}"); + Helper.LogCommand(caller, $"css_freeze {player.PlayerName}"); if (time > 0) AddTimer(time, () => player.Pawn.Value!.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); @@ -142,7 +142,7 @@ namespace CS2_SimpleAdmin player!.Pawn.Value!.Unfreeze(); - Helper.LogCommand(caller, $"css_unfreeze {player?.PlayerName}"); + Helper.LogCommand(caller, $"css_unfreeze {player.PlayerName}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { diff --git a/Commands/playercommands.cs b/Commands/playercommands.cs index d7c0eaa..2580dea 100644 --- a/Commands/playercommands.cs +++ b/Commands/playercommands.cs @@ -46,7 +46,7 @@ namespace CS2_SimpleAdmin player.CommitSuicide(false, true); - Helper.LogCommand(caller, $"css_slay {player?.PlayerName}"); + Helper.LogCommand(caller, $"css_slay {player.PlayerName}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -182,7 +182,7 @@ namespace CS2_SimpleAdmin player.RemoveWeapons(); - Helper.LogCommand(caller, $"css_strip {player?.PlayerName}"); + Helper.LogCommand(caller, $"css_strip {player.PlayerName}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -236,7 +236,7 @@ namespace CS2_SimpleAdmin player.SetHp(health); - Helper.LogCommand(caller, $"css_hp {player?.PlayerName} {health}"); + Helper.LogCommand(caller, $"css_hp {player.PlayerName} {health}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -408,7 +408,7 @@ namespace CS2_SimpleAdmin callerName ??= caller == null ? "Console" : caller.PlayerName; player!.Pawn.Value!.Slap(damage); - Helper.LogCommand(caller, $"css_slap {player?.PlayerName} {damage}"); + Helper.LogCommand(caller, $"css_slap {player.PlayerName} {damage}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { diff --git a/Config.cs b/Config.cs index 05ec01f..5aef43f 100644 --- a/Config.cs +++ b/Config.cs @@ -14,7 +14,7 @@ namespace CS2_SimpleAdmin public class CS2_SimpleAdminConfig : BasePluginConfig { - public override int Version { get; set; } = 6; + [JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 7; [JsonPropertyName("DatabaseHost")] public string DatabaseHost { get; set; } = ""; @@ -43,6 +43,9 @@ namespace CS2_SimpleAdmin [JsonPropertyName("BanType")] public int BanType { get; set; } = 1; + [JsonPropertyName("ExpireOldIpBans")] + public int ExpireOldIpBans { get; set; } = 0; + [JsonPropertyName("TeamSwitchType")] public int TeamSwitchType { get; set; } = 1; diff --git a/Database/Database.cs b/Database/Database.cs index 87a3c59..521c8ca 100644 --- a/Database/Database.cs +++ b/Database/Database.cs @@ -20,10 +20,10 @@ namespace CS2_SimpleAdmin await connection.OpenAsync(); return connection; } - catch (Exception) + catch (Exception ex) { if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to connect to database"); + CS2_SimpleAdmin._logger.LogCritical($"Unable to connect to database: {ex.Message}"); throw; } } diff --git a/Events.cs b/Events.cs index 2a6c4ec..773bd3c 100644 --- a/Events.cs +++ b/Events.cs @@ -8,14 +8,14 @@ using Dapper; using Microsoft.Extensions.Logging; using System.Data; using System.Text; +using static Dapper.SqlMapper; namespace CS2_SimpleAdmin; public partial class CS2_SimpleAdmin { - private void registerEvents() + private void RegisterEvents() { - RegisterListener(OnClientPutInServer); RegisterListener(OnMapStart); AddCommandListener("say", OnCommandSay); AddCommandListener("say_team", OnCommandTeamSay); @@ -80,30 +80,27 @@ public partial class CS2_SimpleAdmin return HookResult.Continue; } - public void OnClientPutInServer(int playerSlot) + [GameEventHandler] + public HookResult OnPlayerFullConnect(EventPlayerConnectFull @event, GameEventInfo info) { - CCSPlayerController? player = Utilities.GetPlayerFromSlot(playerSlot); + CCSPlayerController? player = @event.Userid; #if DEBUG Logger.LogCritical("[OnPlayerConnect] Before check"); - #endif - if (player is null || !player.IsValid || player.IsBot || player.IsHLTV) return; + if (player is null || !player.IsValid || player.SteamID.ToString().Length != 17 || string.IsNullOrEmpty(player.IpAddress)) return HookResult.Continue; #if DEBUG Logger.LogCritical("[OnPlayerConnect] After Check"); #endif - string? ipAddress = !string.IsNullOrEmpty(player.IpAddress) ? player.IpAddress.Split(":")[0] : null; + string? ipAddress = player.IpAddress.Split(":")[0]; - if ( - ipAddress != null && bannedPlayers.Contains(ipAddress) || - bannedPlayers.Contains(player.SteamID.ToString()) - ) + if (bannedPlayers.Contains(ipAddress) || bannedPlayers.Contains(player.SteamID.ToString())) { Helper.KickPlayer((ushort)player.UserId!, "Banned"); - return; + return HookResult.Continue; } if (_database == null) - return; + return HookResult.Continue; PlayerInfo playerInfo = new PlayerInfo { @@ -115,12 +112,13 @@ public partial class CS2_SimpleAdmin IpAddress = ipAddress }; - BanManager _banManager = new(_database, Config); - MuteManager _muteManager = new(_database); - PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); Task.Run(async () => { + BanManager _banManager = new(_database, Config); + MuteManager _muteManager = new(_database); + PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + if (await _banManager.IsPlayerBanned(playerInfo)) { if (playerInfo.IpAddress != null && !bannedPlayers.Contains(playerInfo.IpAddress)) @@ -183,7 +181,7 @@ public partial class CS2_SimpleAdmin } }); - return; + return HookResult.Continue; } [GameEventHandler] @@ -198,7 +196,7 @@ public partial class CS2_SimpleAdmin Logger.LogCritical("[OnClientDisconnect] Before"); #endif - if (player.IsBot || player.IsHLTV) return HookResult.Continue; + if (player.IsBot || player.IsHLTV || player.SteamID.ToString().Length != 17) return HookResult.Continue; #if DEBUG Logger.LogCritical("[OnClientDisconnect] After Check"); @@ -224,7 +222,12 @@ public partial class CS2_SimpleAdmin private void OnMapStart(string mapName) { - Random random = new Random(); + string? path = Path.GetDirectoryName(ModuleDirectory); + if (Directory.Exists(path + "/CS2-Tags")) + { + TagsDetected = true; + } + godPlayers.Clear(); silentPlayers.Clear(); @@ -235,7 +238,7 @@ public partial class CS2_SimpleAdmin if (_database == null) return; - AddTimer(random.Next(60, 80), async () => + AddTimer(60.0f, async () => { #if DEBUG Logger.LogCritical("[OnMapStart] Expired check"); @@ -282,12 +285,6 @@ public partial class CS2_SimpleAdmin playerPenaltyManager.RemoveExpiredPenalties(); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - string? path = Path.GetDirectoryName(ModuleDirectory); - if (Directory.Exists(path + "/CS2-Tags")) - { - TagsDetected = true; - } - AddTimer(3.0f, async () => { string? address = $"{ConVar.Find("ip")!.StringValue}:{ConVar.Find("hostport")!.GetPrimitiveValue()}"; diff --git a/Helper.cs b/Helper.cs index 2fdce99..6771f48 100644 --- a/Helper.cs +++ b/Helper.cs @@ -6,18 +6,21 @@ using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Menu; -using CounterStrikeSharp.API.Modules.Utils; using Discord; using Microsoft.Extensions.Logging; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; +using System.Text.Json; using System.Text.RegularExpressions; namespace CS2_SimpleAdmin { internal class Helper { + private static readonly string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? ""; + private static readonly string CfgPath = $"{Server.GameDirectory}/csgo/addons/counterstrikesharp/configs/plugins/{AssemblyName}/{AssemblyName}.json"; + internal static CS2_SimpleAdminConfig? Config { get; set; } public static List GetPlayerFromName(string name) @@ -105,36 +108,27 @@ namespace CS2_SimpleAdmin public static void KickPlayer(ushort userId, string? reason = null) { + if (!string.IsNullOrEmpty(reason)) + { + int escapeChars = reason.IndexOfAny(new char[] { ';', '|' }); + + if (escapeChars != -1) + { + reason = reason[..escapeChars]; + } + } + Server.ExecuteCommand($"kickid {userId} {reason}"); } public static void PrintToCenterAll(string message) { - Utilities.GetPlayers().ForEach(controller => + Utilities.GetPlayers().Where(p => p is not null && p.IsValid && !p.IsBot && !p.IsHLTV).ToList().ForEach(controller => { controller.PrintToCenter(message); }); } - internal static string ReplaceTags(string message) - { - if (message.Contains('{')) - { - string modifiedValue = message; - foreach (FieldInfo field in typeof(ChatColors).GetFields()) - { - string pattern = $"{{{field.Name}}}"; - if (message.Contains(pattern, StringComparison.OrdinalIgnoreCase)) - { - modifiedValue = modifiedValue.Replace(pattern, field.GetValue(null)!.ToString(), StringComparison.OrdinalIgnoreCase); - } - } - return modifiedValue; - } - - return message; - } - internal static void HandleVotes(CCSPlayerController player, ChatMenuOption option) { if (!CS2_SimpleAdmin.voteInProgress) @@ -212,6 +206,23 @@ namespace CS2_SimpleAdmin return message; } + + public static void UpdateConfig(T config) where T : BasePluginConfig, new() + { + // get newest config version + var newCfgVersion = new T().Version; + + // loaded config is up to date + if (config.Version == newCfgVersion) + return; + + // update the version + config.Version = newCfgVersion; + + // serialize the updated config back to json + var updatedJsonContent = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); + File.WriteAllText(CfgPath, updatedJsonContent); + } } public class SchemaString : NativeObject where SchemaClass : NativeObject @@ -225,10 +236,10 @@ namespace CS2_SimpleAdmin for (int i = 0; i < bytes.Length; i++) { - Unsafe.Write((void*)(this.Handle.ToInt64() + i), bytes[i]); + Unsafe.Write((void*)(Handle.ToInt64() + i), bytes[i]); } - Unsafe.Write((void*)(this.Handle.ToInt64() + bytes.Length), 0); + Unsafe.Write((void*)(Handle.ToInt64() + bytes.Length), 0); } private static byte[] GetStringBytes(string str) diff --git a/Managers/AdminSQLManager.cs b/Managers/AdminSQLManager.cs index 8afa9a4..228c625 100644 --- a/Managers/AdminSQLManager.cs +++ b/Managers/AdminSQLManager.cs @@ -3,82 +3,80 @@ using Dapper; using Microsoft.Extensions.Logging; using System.Collections.Concurrent; -namespace CS2_SimpleAdmin +namespace CS2_SimpleAdmin; +public class AdminSQLManager { - public class AdminSQLManager + private readonly Database _database; + + // Unused for now + //public static readonly ConcurrentDictionary> _adminCache = new ConcurrentDictionary>(); + public static readonly ConcurrentDictionary _adminCache = new ConcurrentDictionary(); + + //public static readonly ConcurrentDictionary _adminCacheTimestamps = new ConcurrentDictionary(); + + public AdminSQLManager(Database database) { - private readonly Database _database; + _database = database; + } - // Unused for now - //public static readonly ConcurrentDictionary> _adminCache = new ConcurrentDictionary>(); - public static readonly ConcurrentDictionary _adminCache = new ConcurrentDictionary(); + public async Task, int)>> GetAdminFlags(string steamId) + { + DateTime now = DateTime.UtcNow; - //public static readonly ConcurrentDictionary _adminCacheTimestamps = new ConcurrentDictionary(); + await using var connection = await _database.GetConnectionAsync(); - public AdminSQLManager(Database database) + string sql = "SELECT flags, immunity, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR server_id = @serverid)"; + List? activeFlags = (await connection.QueryAsync(sql, new { PlayerSteamID = steamId, CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList(); + + if (activeFlags == null) { - _database = database; + return new List<(List, int)>(); } - /* - public async Task> GetAdminFlags(string steamId) + List<(List, int)> filteredFlagsWithImmunity = new List<(List, int)>(); + + foreach (dynamic flags in activeFlags) { - if (_adminCache.ContainsKey(steamId)) + if (flags is not IDictionary flagsDict) { - return _adminCache[steamId].Select(flag => (dynamic)flag).ToList(); + continue; } - else + + if (!flagsDict.TryGetValue("flags", out var flagsValueObj) || !flagsDict.TryGetValue("immunity", out var immunityValueObj)) { - await using var connection = _database.GetConnection(); - await connection.OpenAsync(); - - DateTime now = DateTime.Now; - - string sql = "SELECT flags, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime)"; - List activeFlags = (await connection.QueryAsync(sql, new { PlayerSteamID = steamId, CurrentTime = now })).ToList(); - - _adminCache[steamId] = new List(); - foreach (var flags in activeFlags) - { - if (flags == null) continue; - string flagsValue = flags.flags.ToString(); - _adminCache[steamId].Add(flagsValue); - } + continue; } - return _adminCache[steamId].Select(flag => (dynamic)flag).ToList(); + + if (!(flagsValueObj is string flagsValue) || !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) + { + continue; + } + + //Console.WriteLine($"Flags: {flagsValue}, Immunity: {immunityValue}"); + + filteredFlagsWithImmunity.Add((flagsValue.Split(',').ToList(), immunityValue)); } - */ - public async Task, int)>> GetAdminFlags(string steamId) + return filteredFlagsWithImmunity; + } + + public async Task, int, DateTime?)>> GetAllPlayersFlags() + { + DateTime now = DateTime.UtcNow; + + try { - DateTime now = DateTime.Now; - await using var connection = await _database.GetConnectionAsync(); - string sql = "SELECT flags, immunity, ends FROM sa_admins WHERE player_steamid = @PlayerSteamID AND (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR server_id = @serverid)"; - List? activeFlags = (await connection.QueryAsync(sql, new { PlayerSteamID = steamId, CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList(); + string sql = "SELECT player_steamid, flags, immunity, ends FROM sa_admins WHERE (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR server_id = @serverid)"; + List? activeFlags = (await connection.QueryAsync(sql, new { CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList(); if (activeFlags == null) { - return new List<(List, int)>(); + return new List<(string, List, int, DateTime?)>(); } - List<(List, int)> filteredFlagsWithImmunity = new List<(List, int)>(); - - /* - List filteredFlags = new List(); - - foreach (var flags in activeFlags) - { - if (flags == null) continue; - - string flag = flags.flags.ToString(); - if (flag != null) - { - filteredFlags.Add(flag); - } - } - */ + List<(string, List, int, DateTime?)> filteredFlagsWithImmunity = new List<(string, List, int, DateTime?)>(); foreach (dynamic flags in activeFlags) { @@ -87,226 +85,141 @@ namespace CS2_SimpleAdmin continue; } - if (!flagsDict.TryGetValue("flags", out var flagsValueObj) || !flagsDict.TryGetValue("immunity", out var immunityValueObj)) + if (!flagsDict.TryGetValue("player_steamid", out var steamIdObj) || + !flagsDict.TryGetValue("flags", out var flagsValueObj) || + !flagsDict.TryGetValue("immunity", out var immunityValueObj) || + !flagsDict.TryGetValue("ends", out var endsObj)) { + //Console.WriteLine("One or more required keys are missing."); continue; } - if (!(flagsValueObj is string flagsValue) || !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) + DateTime? ends = null; + + if (endsObj != null) // Check if "ends" is not null { + if (!DateTime.TryParse(endsObj.ToString(), out var parsedEnds)) + { + //Console.WriteLine("Failed to parse 'ends' value."); + continue; + } + + ends = parsedEnds; + } + + if (!(steamIdObj is string steamId) || + !(flagsValueObj is string flagsValue) || + !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) + { + //Console.WriteLine("Failed to parse one or more values."); continue; } - //Console.WriteLine($"Flags: {flagsValue}, Immunity: {immunityValue}"); - - filteredFlagsWithImmunity.Add((flagsValue.Split(',').ToList(), immunityValue)); + filteredFlagsWithImmunity.Add((steamId, flagsValue.Split(',').ToList(), immunityValue, ends)); } - /* Unused for now - bool shouldCache = activeFlags.Any(flags => - { - if (flags?.ends == null) - { - return true; - } - - if (flags.ends is DateTime endsTime) - { - return (endsTime - now).TotalHours > 1; - } - - return false; - }); - - if (shouldCache) - { - List flagsToCache = new List(); - - foreach (var flags in activeFlags) - { - if (flags.ends == null || (DateTime.Now - (DateTime)flags.ends).TotalHours > 6) - { - if (flags == null) continue; - flagsToCache.Add(flags.flags.ToString()); - } - } - - _adminCache.AddOrUpdate(steamId, new ConcurrentBag(flagsToCache), (_, existingBag) => - { - foreach (var flag in flagsToCache) - { - existingBag.Add(flag); - } - return existingBag; - }); - return flagsToCache.Cast().ToList(); - } - */ return filteredFlagsWithImmunity; - //return filteredFlags.Cast().ToList(); } - - public async Task, int, DateTime?)>> GetAllPlayersFlags() + catch (Exception) { - DateTime now = DateTime.Now; + return new List<(string, List, int, DateTime?)>(); + } + } - try + public async Task GiveAllFlags() + { + List<(string, List, int, DateTime?)> allPlayers = await GetAllPlayersFlags(); + + foreach (var record in allPlayers) + { + string steamIdStr = record.Item1; + List flags = record.Item2; + int immunity = record.Item3; + + DateTime? ends = record.Item4; + + if (!string.IsNullOrEmpty(steamIdStr) && SteamID.TryParse(steamIdStr, out var steamId) && steamId != null) { - await using var connection = await _database.GetConnectionAsync(); - - string sql = "SELECT player_steamid, flags, immunity, ends FROM sa_admins WHERE (ends IS NULL OR ends > @CurrentTime) AND (server_id IS NULL OR server_id = @serverid)"; - List? activeFlags = (await connection.QueryAsync(sql, new { CurrentTime = now, serverid = CS2_SimpleAdmin.ServerId }))?.ToList(); - - if (activeFlags == null) + if (!_adminCache.ContainsKey(steamId)) { - return new List<(string, List, int, DateTime?)>(); + _adminCache.TryAdd(steamId, ends); + //_adminCacheTimestamps.Add(steamId, ends); } - List<(string, List, int, DateTime?)> filteredFlagsWithImmunity = new List<(string, List, int, DateTime?)>(); - - foreach (dynamic flags in activeFlags) - { - if (flags is not IDictionary flagsDict) - { - continue; - } - - if (!flagsDict.TryGetValue("player_steamid", out var steamIdObj) || - !flagsDict.TryGetValue("flags", out var flagsValueObj) || - !flagsDict.TryGetValue("immunity", out var immunityValueObj) || - !flagsDict.TryGetValue("ends", out var endsObj)) - { - //Console.WriteLine("One or more required keys are missing."); - continue; - } - - DateTime? ends = null; - - if (endsObj != null) // Check if "ends" is not null - { - if (!DateTime.TryParse(endsObj.ToString(), out var parsedEnds)) - { - //Console.WriteLine("Failed to parse 'ends' value."); - continue; - } - - ends = parsedEnds; - } - - if (!(steamIdObj is string steamId) || - !(flagsValueObj is string flagsValue) || - !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) - { - //Console.WriteLine("Failed to parse one or more values."); - continue; - } - - filteredFlagsWithImmunity.Add((steamId, flagsValue.Split(',').ToList(), immunityValue, ends)); - } - - return filteredFlagsWithImmunity; - } - catch (Exception) - { - return new List<(string, List, int, DateTime?)>(); - } - } - - public async Task GiveAllFlags() - { - List<(string, List, int, DateTime?)> allPlayers = await GetAllPlayersFlags(); - - foreach (var record in allPlayers) - { - string steamIdStr = record.Item1; - List flags = record.Item2; - int immunity = record.Item3; - - DateTime? ends = record.Item4; - - if (!string.IsNullOrEmpty(steamIdStr) && SteamID.TryParse(steamIdStr, out var steamId) && steamId != null) - { - if (!_adminCache.ContainsKey(steamId)) - { - _adminCache.TryAdd(steamId, ends); - //_adminCacheTimestamps.Add(steamId, ends); - } - - Helper.GivePlayerFlags(steamId, flags, (uint)immunity); - // Often need to call 2 times - Helper.GivePlayerFlags(steamId, flags, (uint)immunity); - } - } - } - - public async Task DeleteAdminBySteamId(string playerSteamId, bool globalDelete = false) - { - if (string.IsNullOrEmpty(playerSteamId)) return; - - //_adminCache.TryRemove(playerSteamId, out _); - - await using var connection = await _database.GetConnectionAsync(); - - string sql = ""; - - if (globalDelete) - { - sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID"; - } - else - { - sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID AND server_id = @ServerId"; - } - - await connection.ExecuteAsync(sql, new { PlayerSteamID = playerSteamId, ServerId = CS2_SimpleAdmin.ServerId }); - } - - public async Task AddAdminBySteamId(string playerSteamId, string playerName, string flags, int immunity = 0, int time = 0, bool globalAdmin = false) - { - if (string.IsNullOrEmpty(playerSteamId)) return; - - flags = flags.Replace(" ", ""); - - DateTime now = DateTime.Now; - DateTime? futureTime; - if (time != 0) - futureTime = now.AddMinutes(time); - else - futureTime = null; - - await using var connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_admins` (`player_steamid`, `player_name`, `flags`, `immunity`, `ends`, `created`, `server_id`) " + - "VALUES (@playerSteamid, @playerName, @flags, @immunity, @ends, @created, @serverid)"; - - int? serverId = globalAdmin ? null : CS2_SimpleAdmin.ServerId; - - await connection.ExecuteAsync(sql, new - { - playerSteamId, - playerName, - flags, - immunity, - ends = futureTime, - created = now, - serverid = serverId - }); - } - - public async Task DeleteOldAdmins() - { - try - { - await using var connection = await _database.GetConnectionAsync(); - - string sql = "DELETE FROM sa_admins WHERE ends IS NOT NULL AND ends <= @CurrentTime"; - await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.Now }); - } - catch (Exception) - { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired admins"); + Helper.GivePlayerFlags(steamId, flags, (uint)immunity); + // Often need to call 2 times + Helper.GivePlayerFlags(steamId, flags, (uint)immunity); } } } -} \ No newline at end of file + + public async Task DeleteAdminBySteamId(string playerSteamId, bool globalDelete = false) + { + if (string.IsNullOrEmpty(playerSteamId)) return; + + //_adminCache.TryRemove(playerSteamId, out _); + + await using var connection = await _database.GetConnectionAsync(); + + string sql = ""; + + if (globalDelete) + { + sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID"; + } + else + { + sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID AND server_id = @ServerId"; + } + + await connection.ExecuteAsync(sql, new { PlayerSteamID = playerSteamId, ServerId = CS2_SimpleAdmin.ServerId }); + } + + public async Task AddAdminBySteamId(string playerSteamId, string playerName, string flags, int immunity = 0, int time = 0, bool globalAdmin = false) + { + if (string.IsNullOrEmpty(playerSteamId)) return; + + flags = flags.Replace(" ", ""); + + DateTime now = DateTime.UtcNow; + DateTime? futureTime; + if (time != 0) + futureTime = now.AddMinutes(time); + else + futureTime = null; + + await using var connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_admins` (`player_steamid`, `player_name`, `flags`, `immunity`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @playerName, @flags, @immunity, @ends, @created, @serverid)"; + + int? serverId = globalAdmin ? null : CS2_SimpleAdmin.ServerId; + + await connection.ExecuteAsync(sql, new + { + playerSteamId, + playerName, + flags, + immunity, + ends = futureTime, + created = now, + serverid = serverId + }); + } + + public async Task DeleteOldAdmins() + { + try + { + await using var connection = await _database.GetConnectionAsync(); + + string sql = "DELETE FROM sa_admins WHERE ends IS NOT NULL AND ends <= @CurrentTime"; + await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.Now }); + } + catch (Exception) + { + if (CS2_SimpleAdmin._logger != null) + CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired admins"); + } + } +} diff --git a/Managers/BanManager.cs b/Managers/BanManager.cs index a460ac4..8c823b7 100644 --- a/Managers/BanManager.cs +++ b/Managers/BanManager.cs @@ -1,113 +1,112 @@ using Dapper; using Microsoft.Extensions.Logging; -namespace CS2_SimpleAdmin +namespace CS2_SimpleAdmin; +internal class BanManager { - internal class BanManager + private readonly Database _database; + private readonly CS2_SimpleAdminConfig _config; + + public BanManager(Database database, CS2_SimpleAdminConfig config) { - private readonly Database _database; - private readonly CS2_SimpleAdminConfig _config; + _database = database; + _config = config; + } - public BanManager(Database database, CS2_SimpleAdminConfig config) + public async Task BanPlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0) + { + DateTime now = DateTime.UtcNow; + DateTime futureTime = now.AddMinutes(time); + + await using var connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new { - _database = database; - _config = config; + playerSteamid = player.SteamId, + playerName = player.Name, + playerIp = _config.BanType == 1 ? player.IpAddress : null, + adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, + adminName = issuer.Name == null ? "Console" : issuer.Name, + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + + public async Task AddBanBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0) + { + if (string.IsNullOrEmpty(playerSteamId)) return; + + DateTime now = DateTime.UtcNow; + DateTime futureTime = now.AddMinutes(time); + + await using var connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = playerSteamId, + adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, + adminName = issuer.Name == null ? "Console" : issuer.Name, + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + + public async Task AddBanByIp(string playerIp, PlayerInfo issuer, string reason, int time = 0) + { + if (string.IsNullOrEmpty(playerIp)) return; + + DateTime now = DateTime.UtcNow; + DateTime futureTime = now.AddMinutes(time); + + await using var connection = await _database.GetConnectionAsync(); + + var sql = "INSERT INTO `sa_bans` (`player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + + "VALUES (@playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerIp, + adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, + adminName = issuer.Name == null ? "Console" : issuer.Name, + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + + public async Task IsPlayerBanned(PlayerInfo player) + { + if (player.SteamId == null && player.IpAddress == null) + { + return false; } - public async Task BanPlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0) - { - DateTime now = DateTime.Now; - DateTime futureTime = now.AddMinutes(time); - - await using var connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_steamid`, `player_name`, `player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerSteamid, @playerName, @playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new - { - playerSteamid = player.SteamId, - playerName = player.Name, - playerIp = _config.BanType == 1 ? player.IpAddress : null, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); - } - - public async Task AddBanBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0) - { - if (string.IsNullOrEmpty(playerSteamId)) return; - - DateTime now = DateTime.Now; - DateTime futureTime = now.AddMinutes(time); - - await using var connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new - { - playerSteamid = playerSteamId, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); - } - - public async Task AddBanByIp(string playerIp, PlayerInfo issuer, string reason, int time = 0) - { - if (string.IsNullOrEmpty(playerIp)) return; - - DateTime now = DateTime.Now; - DateTime futureTime = now.AddMinutes(time); - - await using var connection = await _database.GetConnectionAsync(); - - var sql = "INSERT INTO `sa_bans` (`player_ip`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `server_id`) " + - "VALUES (@playerIp, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @serverid)"; - - await connection.ExecuteAsync(sql, new - { - playerIp, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - serverid = CS2_SimpleAdmin.ServerId - }); - } - - public async Task IsPlayerBanned(PlayerInfo player) - { - if (player.SteamId == null && player.IpAddress == null) - { - return false; - } - #if DEBUG - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical($"IsPlayerBanned for {player.Name}"); + if (CS2_SimpleAdmin._logger != null) + CS2_SimpleAdmin._logger.LogCritical($"IsPlayerBanned for {player.Name}"); #endif - int banCount = 0; + int banCount = 0; - DateTime currentTime = DateTime.Now; + DateTime currentTime = DateTime.Now; - try - { - string sql = @" + try + { + string sql = @" UPDATE sa_bans SET player_ip = CASE WHEN player_ip IS NULL THEN @PlayerIP ELSE player_ip END, player_name = CASE WHEN player_name IS NULL THEN @PlayerName ELSE player_name END @@ -120,72 +119,107 @@ namespace CS2_SimpleAdmin AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime);"; - await using var connection = await _database.GetConnectionAsync(); + await using var connection = await _database.GetConnectionAsync(); - var parameters = new - { - PlayerSteamID = player.SteamId, - PlayerIP = !string.IsNullOrEmpty(player.IpAddress) ? player.IpAddress : (object)DBNull.Value, - PlayerName = !string.IsNullOrEmpty(player.Name) ? player.Name : string.Empty, - CurrentTime = currentTime - }; - - banCount = await connection.ExecuteScalarAsync(sql, parameters); - } - catch (Exception) + var parameters = new { - return false; - } + PlayerSteamID = player.SteamId, + PlayerIP = _config.BanType == 0 || string.IsNullOrEmpty(player.IpAddress) ? null : player.IpAddress, + PlayerName = !string.IsNullOrEmpty(player.Name) ? player.Name : string.Empty, + CurrentTime = currentTime + }; - return banCount > 0; + banCount = await connection.ExecuteScalarAsync(sql, parameters); + } + catch (Exception) + { + return false; } - public async Task GetPlayerBans(PlayerInfo player) + return banCount > 0; + } + + public async Task GetPlayerBans(PlayerInfo player) + { + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; + int banCount; + + await using var connection = await _database.GetConnectionAsync(); + + if (!string.IsNullOrEmpty(player.IpAddress)) { - string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; - int banCount; + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = player.IpAddress }); + } + else + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = DBNull.Value }); + } + + return banCount; + } + + public async Task UnbanPlayer(string playerPattern) + { + if (playerPattern == null || playerPattern.Length <= 1) + { + return; + } + + await using var connection = await _database.GetConnectionAsync(); + + string sqlUnban = "UPDATE sa_bans SET status = 'UNBANNED' WHERE player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern AND status = 'ACTIVE'"; + await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern }); + } + + public async Task ExpireOldBans() + { + try + { + DateTime currentTime = DateTime.UtcNow; await using var connection = await _database.GetConnectionAsync(); - if (!string.IsNullOrEmpty(player.IpAddress)) - { - banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = player.IpAddress }); - } - else - { - banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = player.SteamId, PlayerIP = DBNull.Value }); - } - - return banCount; - } - - public async Task UnbanPlayer(string playerPattern) - { - if (playerPattern == null || playerPattern.Length <= 1) - { - return; - } - + /* + string sql = ""; await using var connection = await _database.GetConnectionAsync(); - string sqlUnban = "UPDATE sa_bans SET status = 'UNBANNED' WHERE player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern AND status = 'ACTIVE'"; - await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern }); + sql = "UPDATE sa_bans SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; + await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.UtcNow }); + */ + + string sql = @" + UPDATE sa_bans + SET + status = 'EXPIRED' + WHERE + status = 'ACTIVE' + AND + `duration` > 0 + AND + ends <= @currentTime"; + + await connection.ExecuteAsync(sql, new { currentTime }); + + if (_config.ExpireOldIpBans > 0) + { + DateTime ipBansTime = currentTime.AddDays(-_config.ExpireOldIpBans); + + sql = @" + UPDATE sa_bans + SET + player_ip = NULL + WHERE + status = 'ACTIVE' + AND + ends <= @ipBansTime"; + + await connection.ExecuteAsync(sql, new { ipBansTime }); + } + } - - public async Task ExpireOldBans() + catch (Exception) { - try - { - await using var connection = await _database.GetConnectionAsync(); - - string sql = "UPDATE sa_bans SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; - await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.Now }); - } - catch (Exception) - { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired bans"); - } + CS2_SimpleAdmin._logger?.LogCritical("Unable to remove expired bans"); } } -} \ No newline at end of file +} diff --git a/Managers/MuteManager.cs b/Managers/MuteManager.cs index b384cf4..35569db 100644 --- a/Managers/MuteManager.cs +++ b/Managers/MuteManager.cs @@ -1,208 +1,164 @@ -using CounterStrikeSharp.API.Core; -using Dapper; +using Dapper; using Microsoft.Extensions.Logging; -namespace CS2_SimpleAdmin +namespace CS2_SimpleAdmin; +internal class MuteManager { - internal class MuteManager + private readonly Database _database; + + public MuteManager(Database database) { - private readonly Database _database; + _database = database; + } - public MuteManager(Database database) + public async Task MutePlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0, int type = 0) + { + if (player == null || player.SteamId == null) return; + + await using var connection = await _database.GetConnectionAsync(); + + DateTime now = DateTime.UtcNow; + DateTime futureTime = now.AddMinutes(time); + + string muteType = "GAG"; + if (type == 1) + muteType = "MUTE"; + else if (type == 2) + muteType = "SILENCE"; + + var sql = "INSERT INTO `sa_mutes` (`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " + + "VALUES (@playerSteamid, @playerName, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @type, @serverid)"; + + await connection.ExecuteAsync(sql, new { - _database = database; + playerSteamid = player.SteamId, + playerName = player.Name, + adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, + adminName = issuer.SteamId == null ? "Console" : issuer.Name, + banReason = reason, + duration = time, + ends = futureTime, + created = now, + type = muteType, + serverid = CS2_SimpleAdmin.ServerId + }); + } + + public async Task AddMuteBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0, int type = 0) + { + if (string.IsNullOrEmpty(playerSteamId)) return; + + await using var connection = await _database.GetConnectionAsync(); + + DateTime now = DateTime.UtcNow; + DateTime futureTime = now.AddMinutes(time); + + string muteType = "GAG"; + if (type == 1) + muteType = "MUTE"; + else if (type == 2) + muteType = "SILENCE"; + + var sql = "INSERT INTO `sa_mutes` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " + + "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @type, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = playerSteamId, + adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, + adminName = issuer.Name == null ? "Console" : issuer.Name, + banReason = reason, + duration = time, + ends = futureTime, + created = now, + type = muteType, + serverid = CS2_SimpleAdmin.ServerId + }); + } + + public async Task> IsPlayerMuted(string steamId) + { + if (string.IsNullOrEmpty(steamId)) + { + return new List(); } - public async Task MutePlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0, int type = 0) - { - if (player == null || player.SteamId == null) return; - - await using var connection = await _database.GetConnectionAsync(); - - DateTime now = DateTime.Now; - DateTime futureTime = now.AddMinutes(time); - - string muteType = "GAG"; - if (type == 1) - muteType = "MUTE"; - else if (type == 2) - muteType = "SILENCE"; - - var sql = "INSERT INTO `sa_mutes` (`player_steamid`, `player_name`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " + - "VALUES (@playerSteamid, @playerName, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @type, @serverid)"; - - await connection.ExecuteAsync(sql, new - { - playerSteamid = player.SteamId, - playerName = player.Name, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.SteamId == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - type = muteType, - serverid = CS2_SimpleAdmin.ServerId - }); - } - - public async Task AddMuteBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0, int type = 0) - { - if (string.IsNullOrEmpty(playerSteamId)) return; - - await using var connection = await _database.GetConnectionAsync(); - - DateTime now = DateTime.Now; - DateTime futureTime = now.AddMinutes(time); - - string muteType = "GAG"; - if (type == 1) - muteType = "MUTE"; - else if (type == 2) - muteType = "SILENCE"; - - var sql = "INSERT INTO `sa_mutes` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " + - "VALUES (@playerSteamid, @adminSteamid, @adminName, @banReason, @duration, @ends, @created, @type, @serverid)"; - - await connection.ExecuteAsync(sql, new - { - playerSteamid = playerSteamId, - adminSteamid = issuer.SteamId == null ? "Console" : issuer.SteamId, - adminName = issuer.Name == null ? "Console" : issuer.Name, - banReason = reason, - duration = time, - ends = futureTime, - created = now, - type = muteType, - serverid = CS2_SimpleAdmin.ServerId - }); - } - - public async Task> IsPlayerMuted(string steamId) - { - if (string.IsNullOrEmpty(steamId)) - { - return new List(); - } - #if DEBUG - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical($"IsPlayerMuted for {steamId}"); + if (CS2_SimpleAdmin._logger != null) + CS2_SimpleAdmin._logger.LogCritical($"IsPlayerMuted for {steamId}"); #endif - try - { - await using var connection = await _database.GetConnectionAsync(); - DateTime currentTime = DateTime.Now; - string sql = "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime)"; - - var parameters = new { PlayerSteamID = steamId, CurrentTime = currentTime }; - var activeMutes = (await connection.QueryAsync(sql, parameters)).ToList(); - return activeMutes; - } - catch (Exception) - { - return new List(); - } - } - - public async Task GetPlayerMutes(string steamId) + try { await using var connection = await _database.GetConnectionAsync(); + DateTime currentTime = DateTime.Now; + string sql = "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime)"; - int muteCount; - string sql = "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; - - muteCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = steamId }); - - return muteCount; + var parameters = new { PlayerSteamID = steamId, CurrentTime = currentTime }; + var activeMutes = (await connection.QueryAsync(sql, parameters)).ToList(); + return activeMutes; } - - public async Task UnmutePlayer(string playerPattern, int type = 0) + catch (Exception) { - if (playerPattern == null || playerPattern.Length <= 1) - { - return; - } - - await using var connection = await _database.GetConnectionAsync(); - - if (type == 2) - { - string _unbanSql = "UPDATE sa_mutes SET status = 'UNMUTED' WHERE (player_steamid = @pattern OR player_name = @pattern) AND status = 'ACTIVE'"; - await connection.ExecuteAsync(_unbanSql, new { pattern = playerPattern }); - - return; - } - - string muteType = "GAG"; - if (type == 1) - { - muteType = "MUTE"; - } - else if (type == 2) - muteType = "SILENCE"; - - string sqlUnban = "UPDATE sa_mutes SET status = 'UNMUTED' WHERE (player_steamid = @pattern OR player_name = @pattern) AND type = @muteType AND status = 'ACTIVE'"; - await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern, muteType }); - } - - public async Task ExpireOldMutes() - { - try - { - await using var connection = await _database.GetConnectionAsync(); - - string sql = "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; - await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.Now }); - } - catch (Exception) - { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired mutes"); - } - } - - public async Task CheckMute(PlayerInfo player) - { - if (player.UserId == null || player.SteamId == null) return; - - string steamId = player.SteamId; - List activeMutes = await IsPlayerMuted(steamId); - - if (activeMutes.Count > 0) - { - foreach (var mute in activeMutes) - { - string muteType = mute.type; - TimeSpan duration = mute.ends - mute.created; - int durationInSeconds = (int)duration.TotalSeconds; - - if (muteType == "GAG") - { - if (CS2_SimpleAdmin.TagsDetected) - NativeAPI.IssueServerCommand($"css_tag_mute {player!.SteamId}"); - - /* - CCSPlayerController currentPlayer = player; - - if (mute.duration == 0 || durationInSeconds >= 1800) continue; - - await Task.Delay(TimeSpan.FromSeconds(durationInSeconds)); - - if (currentPlayer != null && currentPlayer.IsValid) - { - NativeAPI.IssueServerCommand($"css_tag_unmute {currentPlayer.Index.ToString()}"); - await UnmutePlayer(currentPlayer.AuthorizedSteamID.SteamId64.ToString(), 0); - } - */ - } - else - { - // Mic mute - } - } - } + return new List(); } } -} \ No newline at end of file + + public async Task GetPlayerMutes(string steamId) + { + await using var connection = await _database.GetConnectionAsync(); + + int muteCount; + string sql = "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; + + muteCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = steamId }); + + return muteCount; + } + + public async Task UnmutePlayer(string playerPattern, int type = 0) + { + if (playerPattern == null || playerPattern.Length <= 1) + { + return; + } + + await using var connection = await _database.GetConnectionAsync(); + + if (type == 2) + { + string _unbanSql = "UPDATE sa_mutes SET status = 'UNMUTED' WHERE (player_steamid = @pattern OR player_name = @pattern) AND status = 'ACTIVE'"; + await connection.ExecuteAsync(_unbanSql, new { pattern = playerPattern }); + + return; + } + + string muteType = "GAG"; + if (type == 1) + { + muteType = "MUTE"; + } + else if (type == 2) + muteType = "SILENCE"; + + string sqlUnban = "UPDATE sa_mutes SET status = 'UNMUTED' WHERE (player_steamid = @pattern OR player_name = @pattern) AND type = @muteType AND status = 'ACTIVE'"; + await connection.ExecuteAsync(sqlUnban, new { pattern = playerPattern, muteType }); + } + + public async Task ExpireOldMutes() + { + try + { + await using var connection = await _database.GetConnectionAsync(); + + string sql = "UPDATE sa_mutes SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; + await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.Now }); + } + catch (Exception) + { + if (CS2_SimpleAdmin._logger != null) + CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired mutes"); + } + } + +} diff --git a/Managers/PlayerPenaltyManager.cs b/Managers/PlayerPenaltyManager.cs index d8cae04..9a925f9 100644 --- a/Managers/PlayerPenaltyManager.cs +++ b/Managers/PlayerPenaltyManager.cs @@ -1,139 +1,137 @@ using System.Collections.Concurrent; -namespace CS2_SimpleAdmin +namespace CS2_SimpleAdmin; +public enum PenaltyType { - public enum PenaltyType - { - Mute, - Gag, - Silence - } + Mute, + Gag, + Silence +} - public class PlayerPenaltyManager - { - private static ConcurrentDictionary>> penalties = - new ConcurrentDictionary>>(); +public class PlayerPenaltyManager +{ + private static ConcurrentDictionary>> penalties = + new ConcurrentDictionary>>(); - // Add a penalty for a player - public void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationSeconds) + // Add a penalty for a player + public void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationSeconds) + { + if (!penalties.ContainsKey(slot)) { - if (!penalties.ContainsKey(slot)) - { - penalties[slot] = new Dictionary>(); - } - - if (!penalties[slot].ContainsKey(penaltyType)) - { - penalties[slot][penaltyType] = new List<(DateTime, int)>(); - } - - penalties[slot][penaltyType].Add((endDateTime, durationSeconds)); + penalties[slot] = new Dictionary>(); } - public bool IsPenalized(int slot, PenaltyType penaltyType) + if (!penalties[slot].ContainsKey(penaltyType)) { - //Console.WriteLine($"Checking penalties for player with slot {slot} and penalty type {penaltyType}"); + penalties[slot][penaltyType] = new List<(DateTime, int)>(); + } - if (penalties.TryGetValue(slot, out var penaltyDict) && penaltyDict.TryGetValue(penaltyType, out var penaltiesList)) + penalties[slot][penaltyType].Add((endDateTime, durationSeconds)); + } + + public bool IsPenalized(int slot, PenaltyType penaltyType) + { + //Console.WriteLine($"Checking penalties for player with slot {slot} and penalty type {penaltyType}"); + + if (penalties.TryGetValue(slot, out var penaltyDict) && penaltyDict.TryGetValue(penaltyType, out var penaltiesList)) + { + //Console.WriteLine($"Found penalties for player with slot {slot} and penalty type {penaltyType}"); + + DateTime now = DateTime.Now; + + // Check if any active penalties exist + foreach (var penalty in penaltiesList.ToList()) { - //Console.WriteLine($"Found penalties for player with slot {slot} and penalty type {penaltyType}"); - - DateTime now = DateTime.Now; - - // Check if any active penalties exist - foreach (var penalty in penaltiesList.ToList()) + // Check if the penalty is still active + if (penalty.Duration > 0 && now >= penalty.EndDateTime.AddSeconds(penalty.Duration)) { - // Check if the penalty is still active - if (penalty.Duration > 0 && now >= penalty.EndDateTime.AddSeconds(penalty.Duration)) + //Console.WriteLine($"Removing expired penalty for player with slot {slot} and penalty type {penaltyType}"); + penaltiesList.Remove(penalty); // Remove expired penalty + if (penaltiesList.Count == 0) { - //Console.WriteLine($"Removing expired penalty for player with slot {slot} and penalty type {penaltyType}"); - penaltiesList.Remove(penalty); // Remove expired penalty - if (penaltiesList.Count == 0) - { - //Console.WriteLine($"No more penalties of type {penaltyType} for player with slot {slot}. Removing penalty type."); - penaltyDict.Remove(penaltyType); // Remove penalty type if no more penalties exist - } - } - else if (penalty.Duration == 0 || now < penalty.EndDateTime) - { - //Console.WriteLine($"Player with slot {slot} is penalized for type {penaltyType}"); - // Return true if there's an active penalty - return true; + //Console.WriteLine($"No more penalties of type {penaltyType} for player with slot {slot}. Removing penalty type."); + penaltyDict.Remove(penaltyType); // Remove penalty type if no more penalties exist } } - - // Return false if no active penalties are found - //Console.WriteLine($"Player with slot {slot} is not penalized for type {penaltyType}"); - return false; + else if (penalty.Duration == 0 || now < penalty.EndDateTime) + { + //Console.WriteLine($"Player with slot {slot} is penalized for type {penaltyType}"); + // Return true if there's an active penalty + return true; + } } - // Return false if no penalties of the specified type were found for the player - //Console.WriteLine($"No penalties found for player with slot {slot} and penalty type {penaltyType}"); + // Return false if no active penalties are found + //Console.WriteLine($"Player with slot {slot} is not penalized for type {penaltyType}"); return false; } - // Get the end datetime and duration of penalties for a player and penalty type - public List<(DateTime EndDateTime, int Duration)> GetPlayerPenalties(int slot, PenaltyType penaltyType) + // Return false if no penalties of the specified type were found for the player + //Console.WriteLine($"No penalties found for player with slot {slot} and penalty type {penaltyType}"); + return false; + } + + // Get the end datetime and duration of penalties for a player and penalty type + public List<(DateTime EndDateTime, int Duration)> GetPlayerPenalties(int slot, PenaltyType penaltyType) + { + if (penalties.TryGetValue(slot, out Dictionary>? penaltyDict) && + penaltyDict.TryGetValue(penaltyType, out List<(DateTime EndDateTime, int Duration)>? penaltiesList) && penaltiesList != null) { - if (penalties.TryGetValue(slot, out Dictionary>? penaltyDict) && - penaltyDict.TryGetValue(penaltyType, out List<(DateTime EndDateTime, int Duration)>? penaltiesList) && penaltiesList != null) + return penaltiesList; + } + return new List<(DateTime EndDateTime, int Duration)>(); + } + + public bool IsSlotInPenalties(int slot) + { + return penalties.ContainsKey(slot); + } + + // Remove all penalties for a player slot + public void RemoveAllPenalties(int slot) + { + if (penalties.ContainsKey(slot)) + { + penalties.TryRemove(slot, out _); + } + } + + // Remove all penalties + public void RemoveAllPenalties() + { + penalties.Clear(); + } + + // Remove all penalties of a selected type from a specific player + public void RemovePenaltiesByType(int slot, PenaltyType penaltyType) + { + if (penalties.TryGetValue(slot, out Dictionary>? penaltyDict) && + penaltyDict.ContainsKey(penaltyType)) + { + penaltyDict.Remove(penaltyType); + } + } + + // Remove all expired penalties for all players and penalty types + public void RemoveExpiredPenalties() + { + DateTime now = DateTime.Now; + foreach (var kvp in penalties.ToList()) // Use ToList to avoid modification while iterating + { + var playerSlot = kvp.Key; + var penaltyDict = kvp.Value; + + // Remove expired penalties for the player + foreach (var penaltiesList in penaltyDict.Values) { - return penaltiesList; + penaltiesList.RemoveAll(p => p.Duration > 0 && now >= p.EndDateTime.AddSeconds(p.Duration)); } - return new List<(DateTime EndDateTime, int Duration)>(); - } - public bool IsSlotInPenalties(int slot) - { - return penalties.ContainsKey(slot); - } - - // Remove all penalties for a player slot - public void RemoveAllPenalties(int slot) - { - if (penalties.ContainsKey(slot)) + // Remove player slot if no penalties left + if (penaltyDict.Count == 0) { - penalties.TryRemove(slot, out _); - } - } - - // Remove all penalties - public void RemoveAllPenalties() - { - penalties.Clear(); - } - - // Remove all penalties of a selected type from a specific player - public void RemovePenaltiesByType(int slot, PenaltyType penaltyType) - { - if (penalties.TryGetValue(slot, out Dictionary>? penaltyDict) && - penaltyDict.ContainsKey(penaltyType)) - { - penaltyDict.Remove(penaltyType); - } - } - - // Remove all expired penalties for all players and penalty types - public void RemoveExpiredPenalties() - { - DateTime now = DateTime.Now; - foreach (var kvp in penalties.ToList()) // Use ToList to avoid modification while iterating - { - var playerSlot = kvp.Key; - var penaltyDict = kvp.Value; - - // Remove expired penalties for the player - foreach (var penaltiesList in penaltyDict.Values) - { - penaltiesList.RemoveAll(p => p.Duration > 0 && now >= p.EndDateTime.AddSeconds(p.Duration)); - } - - // Remove player slot if no penalties left - if (penaltyDict.Count == 0) - { - penalties.TryRemove(playerSlot, out _); - } + penalties.TryRemove(playerSlot, out _); } } } -} \ No newline at end of file +} diff --git a/admin_help.txt b/admin_help.txt new file mode 100644 index 0000000..44b1b57 --- /dev/null +++ b/admin_help.txt @@ -0,0 +1,36 @@ +{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT} +- css_who <#userid or name> - Display informations about player +- css_players - Display player list +- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player +- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64 +- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address +- css_unban - Unban player +- css_kick <#userid or name> [reason] - Kick player +- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player +- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64 +- css_unmute - Ungag player +- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player +- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64 +- css_give <#userid or name> - Give player a weapon +- css_strip <#userid or name> - Takes all of the player weapons +- css_hp <#userid or name> [health] - Set player health +- css_god <#userid or name> - Toggle player godmode +- css_slay <#userid or name> - Kill player +- css_slap <#userid or name> [damage] - Slap player +- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote +- css_map - Change map +- css_wsmap - Change workshop map +- css_asay - Say message to all admins +- css_say - Say message as admin in chat +- css_psay <#userid or name> - Sends private message to player +- css_csay - Say message as admin in center +- css_hsay - Say message as admin in hud +- css_noclip <#userid or name> - Toggle noclip for player +- css_freeze <#userid or name> [duration] - Freeze player +- css_unfreeze <#userid or name> - Unfreeze player +- css_respawn <#userid or name> - Respawn player +- css_cvar - Change cvar value +- css_rcon - Run command as server + +{Green}This is a sample admin_help.txt file +{LightRed}Write all useful information for admins here diff --git a/lang/ar.json b/lang/ar.json index 5bf821a..1da47e5 100644 --- a/lang/ar.json +++ b/lang/ar.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[مساعدة القائمة] {default}،", - "sa_adminhelp": "{lightred}[ مساعدة برنامج SimpleAdmin CS2 ]{DEFAULT}\n- css_who <#userid أو اسم المستخدم> - عرض معلومات عن اللاعب\n- css_players - عرض قائمة اللاعبين\n- css_ban <#userid أو اسم المستخدم> [وقت الحظر بالدقائق/0 دائم] [سبب الحظر] - حظر اللاعب\n- css_addban [وقت الحظر بالدقائق/0 دائم] [سبب الحظر] - حظر اللاعب عن طريق steamid64\n- css_banip [وقت الحظر بالدقائق/0 دائم] [سبب الحظر] - حظر اللاعب عن طريق عنوان ip\n- css_unban - إلغاء حظر اللاعب\n- css_kick <#userid أو اسم المستخدم> [سبب الطرد] - طرد اللاعب\n- css_gag <#userid أو اسم المستخدم> [وقت الحجب بالدقائق/0 دائم] [سبب الحجب] - حجب اللاعب\n- css_addgag [وقت الحجب بالدقائق/0 دائم] [سبب الحجب] - حجب اللاعب عن طريق steamid64\n- css_unmute - إلغاء حجب الصوت لللاعب\n- css_mute <#userid أو اسم المستخدم> [وقت الحجب بالدقائق/0 دائم] [سبب الحجب] - حجب صوت اللاعب\n- css_addmute [وقت الحجب بالدقائق/0 دائم] [سبب الحجب] - حجب صوت اللاعب عن طريق steamid64\n- css_give <#userid أو اسم المستخدم> <سلاح> - توفير سلاح لللاعب\n- css_strip <#userid أو اسم المستخدم> - استرداد كافة الأسلحة من اللاعب\n- css_hp <#userid أو اسم المستخدم> [الصحة] - تغيير معدل الصحة لللاعب\n- css_god <#userid أو اسم المستخدم> - تبديل وضع اللاعب في اللامراعية\n- css_slay <#userid أو اسم المستخدم> - قتل اللاعب\n- css_slap <#userid أو اسم المستخدم> [مدى الضرر] - ضرب اللاعب\n- css_vote <'سؤال?'> ['إجابة 1'] ['إجابة 2'] ... - بدء تصويت\n- css_map <اسم الخريطة> - تغيير الخريطة\n- css_wsmap <اسم أو معرف> - تغيير الخريطة من مكتبة العمل\n- css_asay <رسالة> - قول رسالة لكافة المشرفين\n- css_say <رسالة> - قول رسالة كمشرف في الدردشة\n- css_psay <#userid أو اسم المستخدم> <رسالة> - إرسال رسالة خاصة إلى اللاعب\n- css_csay <رسالة> - قول رسالة كمشرف في الوسط\n- css_hsay <رسالة> - قول رسالة كمشرف في الشاشة الرئيسية\n- css_noclip <#userid أو اسم المستخدم> - تبديل وضع لا للتعليق لللاعب\n- css_freeze <#userid أو اسم المستخدم> [مدة] - تجميد اللاعب\n- css_unfreeze <#userid أو اسم المستخدم> - إلغاء تجميد اللاعب\n- css_respawn <#userid أو اسم المستخدم> - إعادة توليد اللاعب\n- css_cvar <قيمة> - تغيير قيمة cvar\n- css_rcon <أمر> - تنفيذ أمر كخادم\n", "sa_player_ban_message_time": "لقد حظرتك لمدة {lightred}{0}{default} لدقائق {lightred}{1}{default} بواسطة {lightred}{2}{default}!", "sa_player_ban_message_perm": "لقد حظرتك دائما لمدة {lightred}{0}{default} بواسطة {lightred}{1}{default}!", "sa_player_kick_message": "لقد طردتك لمدة {lightred}{0}{default} بواسطة {lightred}{1}{default}!", diff --git a/lang/en.json b/lang/en.json index 4954a0c..235eee4 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid or name> - Display informations about player\n- css_players - Display player list\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_strip <#userid or name> - Takes all of the player weapons\n- css_hp <#userid or name> [health] - Set player health\n- css_god <#userid or name> - Toggle player godmode\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", "sa_player_ban_message_time": "You have been banned for {lightred}{0}{default} for {lightred}{1}{default} minutes by {lightred}{2}{default}!", "sa_player_ban_message_perm": "You have been banned permanently for {lightred}{0}{default} by {lightred}{1}{default}!", "sa_player_kick_message": "You have been kicked for {lightred}{0}{default} by {lightred}{1}{default}!", diff --git a/lang/es.json b/lang/es.json index 7660f47..34343cc 100644 --- a/lang/es.json +++ b/lang/es.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin AYUDA ]{DEFAULT}\n- css_who <#userid o nombre> - Mostrar información sobre el jugador\n- css_players - Mostrar lista de jugadores\n- css_ban <#userid o nombre> [tiempo en minutos/0 perm] [razón] - Banear jugador\n- css_addban [tiempo en minutos/0 perm] [razón] - Banear jugador por steamid64\n- css_banip [tiempo en minutos/0 perm] [razón] - Banear jugador por dirección IP\n- css_unban - Desbanear jugador\n- css_kick <#userid o nombre> [razón] - Expulsar jugador\n- css_gag <#userid o nombre> [tiempo en minutos/0 perm] [razón] - Silenciar jugador\n- css_addgag [tiempo en minutos/0 perm] [razón] - Silenciar jugador por steamid64\n- css_unmute - Quitar silencio a jugador\n- css_mute <#userid o nombre> [tiempo en minutos/0 perm] [razón] - Silenciar jugador\n- css_addmute [tiempo en minutos/0 perm] [razón] - Silenciar jugador por steamid64\n- css_give <#userid o nombre> - Darle a jugador un arma\n- css_strip <#userid o nombre> - Quitarle todas las armas al jugador\n- css_hp <#userid o nombre> [salud] - Establecer la salud del jugador\n- css_god <#userid o nombre> - Alternar el modo dios del jugador\n- css_slay <#userid o nombre> - Matar jugador\n- css_slap <#userid o nombre> [daño] - Abofetear jugador\n- css_vote <'Pregunta?'> ['Respuesta1'] ['Respuesta2'] ... - Crear votación\n- css_map - Cambiar mapa\n- css_wsmap - Cambiar mapa de taller\n- css_asay - Decir mensaje a todos los administradores\n- css_say - Decir mensaje como administrador en el chat\n- css_psay <#userid o nombre> - Enviar mensaje privado al jugador\n- css_csay - Decir mensaje como administrador en el centro\n- css_hsay - Decir mensaje como administrador en la pantalla\n- css_noclip <#userid o nombre> - Alternar noclip para el jugador\n- css_freeze <#userid o nombre> [duración] - Congelar jugador\n- css_unfreeze <#userid o nombre> - Descongelar jugador\n- css_respawn <#userid o nombre> - Respawnear jugador\n- css_cvar - Cambiar valor de cvar\n- css_rcon - Ejecutar comando como servidor", "sa_player_ban_message_time": "Has sido baneado por {lightred}{0}{default} durante {lightred}{1}{default} minutos por {lightred}{2}{default}.", "sa_player_ban_message_perm": "Has sido baneado permanentemente por {lightred}{0}{default} por {lightred}{1}{default}.", "sa_player_kick_message": "Has sido expulsado por {lightred}{0}{default} por {lightred}{1}{default}.", diff --git a/lang/fa.json b/lang/fa.json index a02519e..67c11a6 100644 --- a/lang/fa.json +++ b/lang/fa.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid ya Esm> - Etela'ate marbot be bazikon ra namayesh midahad\n- css_players - Liste bazikonan ra namayesh midahad\n- css_ban <#userid ya Esm> [Zaman Be Daghighe/0 perm] [Dalil] - Ban player\n- css_addban [Zaman Be Daghighe/0 perm] [Dalil] - Ban player via steamid64\n- css_banip [Zaman Be Daghighe/0 perm] [Dalil] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid ya Esm> [Dalil] - Kick player\n- css_gag <#userid ya Esm> [Zaman Be Daghighe/0 perm] [Dalil] - Gag player\n- css_addgag [Zaman Be Daghighe/0 perm] [Dalil] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid ya Esm> [Zaman Be Daghighe/0 perm] [Dalil] - Mute player\n- css_addmute [Zaman Be Daghighe/0 perm] [Dalil] - Mute player via steamid64\n- css_give <#userid ya Esm> - Be bazikon aslahe midahad\n- css_strip <#userid ya Esm> - Tamami aslahe haye bazikon ra migirad\n- css_hp <#userid ya Esm> [health] - Jone player ra tanzim mikonad\n- css_god <#userid ya Esm> - God mode bazikon ra roshan ya khamosh mikonad\n- css_slay <#userid ya Esm> - Bazikon ra mikoshad\n- css_slap <#userid ya Esm> [damage] - Slap player\n- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote\n- css_map - Map ra taghir midahad\n- css_wsmap - Map ra be workshop taghir midahad\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid ya Esm> - Payame shakhsi be bazikon ersal mikonad\n- css_csay - Say message as admin in center\n- css_hsay - Dakhele Safhe az tarafe admin peygham ersal mikonad\n- css_noclip <#userid ya Esm> - Noclip ya baraye bazikon khamosh ya roshan konid\n- css_freeze <#userid ya Esm> [Zaman] - Freeze player\n- css_unfreeze <#userid ya Esm> - Unfreeze player\n- css_respawn <#userid ya Esm> - Bazikon ra Respawn mikonad\n- css_cvar - Change cvar value\n- css_rcon - Dastor ra az tarighe server ejra mikonad", "sa_player_ban_message_time": "Shoma Ban shodid be dalile {lightred}{0}{default} Be modate {lightred}{1}{default} Daghighe Tavasote {lightred}{2}{default}!", "sa_player_ban_message_perm": "Shoma baraye hamishe Ban shodid be dalile {lightred}{0}{default} Tvasaote {lightred}{1}{default}!", "sa_player_kick_message": "Shoma kick shodid be dalile {lightred}{0}{default} Tavasote {lightred}{1}{default}!", diff --git a/lang/fr.json b/lang/fr.json index 04420f0..a04e1fe 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ AIDE CS2-SimpleAdmin ]{DEFAULT}\n- css_who <#userid ou nom> - Voir les infos d'un joueur\n- css_players - Affiche la liste des joueurs\n- css_ban <#userid ou nom> [temps en minutes/0 perm] [raison] - Bannir le joueur\n- css_addban [temps en minutes/0 perm] [raison] - Bannir le joueur via steamid64\n- css_banip [temps en minutes/0 perm] [raison] - Bannir le joueur via Addresse IP\n- css_unban - Débannir le joueur\n- css_kick <#userid ou nom> [raison] - Kicker le joueur\n- css_gag <#userid ou nom> [temps en minutes/0 perm] [raison] - Gagger le joueur\n- css_addgag [temps en minutes/0 perm] [raison] - Gagger le joueur via steamid64\n- css_unmute - Dé-Gagger le joueur\n- css_mute <#userid ou nom> [temps en minutes/0 perm] [raison] - Rendre muet le joueur\n- css_addmute [temps en minutes/0 perm] [raison] - Rendre muet le joueur via steamid64\n- css_give <#userid ou nom> - Donner une arme au joueur\n- css_strip <#userid ou nom> - Prendre les armes du joueur\n- css_hp <#userid ou nom> [vie] - Changer la vie du joueur\n- css_god <#userid ou nom> - Rendre invincible\n- css_slay <#userid ou nom> - Tuer le joueur\n- css_slap <#userid ou nom> [damage] - Mettre une fessée au joueur\n- css_vote <'Question?'> ['Réponse1'] ['Réponse2'] ... - Créer un vote\n- css_map - Changer de carte\n- css_wsmap - Changer de carte du workshop\n- css_asay - Parler a tous les admins\n- css_say - Parler en tant qu'admin dans le chat\n- css_psay <#userid ou nom> - Envoyer un message privé au joueur\n- css_csay - Parler comme admin au centre de l'écran\n- css_hsay - Parler en tant qu'admin sur le HUD\n- css_noclip <#userid ou nom> - Activer le NoClip\n- css_freeze <#userid ou nom> [durée] - Bloquer le joueur\n- css_unfreeze <#userid ou nom> - Débloquer le joueur\n- css_respawn <#userid ou nom> - Faire revivre le joueur\n- css_cvar - Changer la valeur d'une CVAR\n- css_rcon - Executer une commande serveur", "sa_player_ban_message_time": "Tu as été banni pour {lightred}{0}{default} pendant {lightred}{1}{default} minutes par {lightred}{2}{default} !", "sa_player_ban_message_perm": "Tu a été banni de manière permanente pour {lightred}{0}{default} par {lightred}{1}{default} !", "sa_player_kick_message": "Tu as été expulsé pour {lightred}{0}{default} par {lightred}{1}{default} !", diff --git a/lang/lv.json b/lang/lv.json index c05ee37..0a6e72a 100644 --- a/lang/lv.json +++ b/lang/lv.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid or name> - Display informations about player\n- css_players - Display player list\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_strip <#userid or name> - Takes all of the player weapons\n- css_hp <#userid or name> [health] - Set player health\n- css_god <#userid or name> - Toggle player godmode\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", "sa_player_ban_message_time": "Tu tiki banots ar iemeslu {lightred}{0}{default} uz {lightred}{1}{default} minūti/ēm. Pieeju liedza Admins: {lightred}{2}{default}!", "sa_player_ban_message_perm": "Tu tiki banots uz mūžu ar iemeslu {lightred}{0}{default} Pieeju liedza Admins: {lightred}{1}{default}!", "sa_player_kick_message": "Tu tiki izmests ar iemeslu {lightred}{0}{default} Tevi izmeta Admins: {lightred}{1}{default}!", diff --git a/lang/pl.json b/lang/pl.json index 289453a..aa109d4 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid or name> - Display informations about player\n- css_players - Display player list\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_strip <#userid or name> - Takes all of the player weapons\n- css_hp <#userid or name> [health] - Set player health\n- css_god <#userid or name> - Toggle player godmode\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", "sa_player_ban_message_time": "Zostałeś zbanowany za {lightred}{0}{default} na {lightred}{1}{default} minut przez {lightred}{2}{default}!", "sa_player_ban_message_perm": "Zostałeś zbanowany na zawsze za {lightred}{0}{default} przez {lightred}{1}{default}!", "sa_player_kick_message": "Zostałeś wyrzucony za {lightred}{0}{default} przez {lightred}{1}{default}!", diff --git a/lang/pt-BR.json b/lang/pt-BR.json index 722fe3a..329c5e1 100644 --- a/lang/pt-BR.json +++ b/lang/pt-BR.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid or name> - Mostrar inpormações sobre o player\n- css_players - Mostrar a lista de players\n- css_ban <#userid or name> [time in minutos/0 perm] [reason] - Ban player\n- css_addban [time in minutos/0 perm] [reason] - Banir o player através do steamid64\n- css_banip [time in minutos/0 perm] [reason] - Banir o player através do endereço IP\n- css_unban - Desbanir o player\n- css_kick <#userid or name> [reason] - Kikar player\n- css_gag <#userid or name> [time in minutos/0 perm] [reason] - Mutar pelo chat o player\n- css_addgag [time in minutos/0 perm] [reason] - Mutar pelo chat o player pelo steamid64\n- css_unmute - Desmutar pelo chat o player\n- css_mute <#userid or name> [time in minutos/0 perm] [reason] - Mutar na voice o player\n- css_addmute [time in minutos/0 perm] [reason] - Mutar na voice o player pelo steamid64\n- css_give <#userid or name> - Dar arma a um player\n- css_strip <#userid or name> - Tirar arma de um player\n- css_hp <#userid or name> [health] - Setar vida de um player\n- css_god <#userid or name> - Alternar god no player\n- css_slay <#userid or name> - Matar player\n- css_slap <#userid or name> [damage] - Dâ uns tapa no player\n-<'Question?'> [ 'Answer1' ] ['Answer2'] ... - Criar votação (pool)\n- css_map - Mudar mapa\n- css_wsmap - Mudar mapa da workshop\n- css_asay - Mandar mensagem para todos os Admins\n- css_say - Manda uma mensagem em modo adm no chat\n- css_psay <#userid or name> - Manda uma mensagem privada para um player\n- css_csay - Manda uma mensagem em modo admin de centro\n- css_hsay - Manda uma mensagem em modo admin no HUD\n- css_noclip <#userid or name> - Alternar Noclip em player\n- css_freeze <#userid or name> [duration] - Congela um player\n- css_unfreeze <#userid or name> - Descongela um player\n- css_respawn <#userid or name> - Respawna um player\n- css_cvar - Muda valor de cvar\n- css_rcon - Executar comando como servidor", "sa_player_ban_message_time": "Você foi banido por {lightred}{0}{default} por {lightred}{1}{default} minutos por {lightred}{2}{default}!", "sa_player_ban_message_perm": "Você foi banido permanentemente por {lightred}{0}{default} por {lightred}{1}{default}!", "sa_player_kick_message": "Você foi kikado por {lightred}{0}{default} por {lightred}{1}{default}!", diff --git a/lang/ru.json b/lang/ru.json index 3840997..24405f0 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin HELP ]{DEFAULT}\n- css_who <#userid or name> - Display informations about player\n- css_players - Display player list\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Ban player\n- css_addban [time in minutes/0 perm] [reason] - Ban player via steamid64\n- css_banip [time in minutes/0 perm] [reason] - Ban player via IP address\n- css_unban - Unban player\n- css_kick <#userid or name> [reason] - Kick player\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Gag player\n- css_addgag [time in minutes/0 perm] [reason] - Gag player via steamid64\n- css_unmute - Ungag player\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Mute player\n- css_addmute [time in minutes/0 perm] [reason] - Mute player via steamid64\n- css_give <#userid or name> - Give player a weapon\n- css_strip <#userid or name> - Takes all of the player weapons\n- css_hp <#userid or name> [health] - Set player health\n- css_god <#userid or name> - Toggle player godmode\n- css_slay <#userid or name> - Kill player\n- css_slap <#userid or name> [damage] - Slap player\n- css_vote <'Question?'> ['Answer1'] ['Answer2'] ... - Create vote\n- css_map - Change map\n- css_wsmap - Change workshop map\n- css_asay - Say message to all admins\n- css_say - Say message as admin in chat\n- css_psay <#userid or name> - Sends private message to player\n- css_csay - Say message as admin in center\n- css_hsay - Say message as admin in hud\n- css_noclip <#userid or name> - Toggle noclip for player\n- css_freeze <#userid or name> [duration] - Freeze player\n- css_unfreeze <#userid or name> - Unfreeze player\n- css_respawn <#userid or name> - Respawn player\n- css_cvar - Change cvar value\n- css_rcon - Run command as server", "sa_player_ban_message_time": "Вы были забанены за {lightred}{0}{default} на {lightred}{1}{default} минут администратором {lightred}{2}{default}!", "sa_player_ban_message_perm": "Вы были забанены навсегда за {lightred}{0}{default} администратором {lightred}{1}{default}!", "sa_player_kick_message": "Вас выгнал за {lightred}{0}{default} администратор {lightred}{1}{default}!", diff --git a/lang/tr.json b/lang/tr.json index 75c3402..ec21e1e 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[ CS2-SimpleAdmin Yardım ]{DEFAULT}\n- css_who <#userid or name> - Oyuncu hakkındaki bilgileri görüntüleme\n- css_players - Oyuncu listesini görüntüle\n- css_ban <#userid or name> [time in minutes/0 perm] [reason] - Oyuncu yasaklama\n- css_addban [time in minutes/0 perm] [reason] - SteamID64 ile oyuncu yasaklama\n- css_banip [time in minutes/0 perm] [reason] - IP Adresi ile oyuncu yasaklama\n- css_unban - Oyuncunun yasaklamasını kaldırma\n- css_kick <#userid or name> [reason] - Oyuncuyu sunucudan atma\n- css_gag <#userid or name> [time in minutes/0 perm] [reason] - Oyuncuya sohbet yasağı\n- css_addgag [time in minutes/0 perm] [reason] - SteamID64 ile oyuncuya sohbet yasağı\n- css_unmute - Oyuncunun sohbet yasağını kaldırma\n- css_mute <#userid or name> [time in minutes/0 perm] [reason] - Oyuncuyu susturma\n- css_addmute [time in minutes/0 perm] [reason] - SteamID64 ile oyuncuyu susturma\n- css_give <#userid or name> - Oyuncuya silah verme\n- css_strip <#userid or name> - Oyuncunun tüm silahlarını alma\n- css_hp <#userid or name> [health] - Oyuncu sağlığını değiştirme\n- css_god <#userid or name> - Oyuncunun ölümsüzlük modunu açıp/kapama\n- css_slay <#userid or name> - Oyuncuyu öldürme\n- css_slap <#userid or name> [damage] - Oyuncuyu tokatlama\n- css_vote <'Soru?'> ['Yanıt1'] ['Yanıt2'] ... - Oylama oluşturma\n- css_map - Haritayı değiştirme\n- css_wsmap - Atölye haritasını değiştirme\n- css_asay - Yöneticilere özel mesaj gönderme\n- css_say - Sohbete yönetici olarak mesaj gönderme\n- css_psay <#userid or name> - Oyuncuya özel mesaj gönderme\n- css_csay - Ekranın ortasında yönetici olarak mesaj gönderme\n- css_hsay - HUD ile yönetici olarak mesaj gönderme\n- css_noclip <#userid or name> - Oyuncu için hayalet modunu aç/kapat\n- css_freeze <#userid or name> [duration] - Oyuncuyu dondur\n- css_unfreeze <#userid or name> - Oyuncunun dondurulmasını kaldır\n- css_respawn <#userid or name> - Oyuncuyu yeniden canlandır\n- css_cvar - Cvar değerini değiştir\n- css_rcon - Komutu sunucu olarak çalıştır", "sa_player_ban_message_time": "{lightred}{0}{default} sebebiyle {lightred}{1}{default} dakika süreyle {lightred}{2}{default} tarafından yasaklandınız!", "sa_player_ban_message_perm": "{lightred}{0}{default} sebebiyle {lightred}{1}{default} tarafından kalıcı olarak yasaklandınız!", "sa_player_kick_message": "{lightred}{0}{default} sebebiyle {lightred}{1}{default} tarafından sunucudan atıldınız!", diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index 8ade1e4..4548486 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -1,6 +1,5 @@ { "sa_prefix": "{lightred}[SA] {default}", - "sa_adminhelp": "{GREEN}[CS2-SimpleAdmin帮助]{DEFAULT}\n- css_who <#用户ID或名称> - 显示玩家信息\n- css_players - 显示玩家列表\n- css_ban <#用户ID或名称> [时间(分钟)/0永久] [原因] - 封禁玩家\n- css_addban [时间(分钟)/0永久] [原因] - 通过SteamID64封禁玩家\n- css_banip [时间(分钟)/0永久] [原因] - 通过IP地址封禁玩家\n- css_unban - 解封玩家\n- css_kick <#用户ID或名称> [原因] - 踢出玩家\n- css_gag <#用户ID或名称> [时间(分钟)/0永久] [原因] - 禁言玩家\n- css_addgag [时间(分钟)/0永久] [原因] - 通过SteamID64禁言玩家\n- css_unmute - 解除玩家禁言\n- css_mute <#用户ID或名称> [时间(分钟)/0永久] [原因] - 禁言玩家\n- css_addmute [时间(分钟)/0永久] [原因] - 通过SteamID64禁言玩家\n- css_give <#用户ID或名称> <武器> - 给予玩家武器\n- css_strip <#用户ID或名称> <武器> - 夺取玩家所有武器\n- css_hp <#用户ID或名称> [生命值] - 设置玩家生命值\n- css_god <#用户ID或名称> - 切换玩家上帝模式\n- css_slay <#用户ID或名称> - 杀死玩家\n- css_slap <#用户ID或名称> [伤害] - 打击玩家\n- css_vote <'问题?'> ['答案1'] ['答案2'] ... - 创建投票\n- css_map <地图名称> - 切换地图\n- css_wsmap <名称或ID> - 切换创意工坊地图\n- css_asay <消息> - 向所有管理员发送消息\n- css_say <消息> - 作为管理员在聊天中发送消息\n- css_psay <#用户ID或名称> <消息> - 向玩家发送私密消息\n- css_csay <消息> - 作为管理员在中央发送消息\n- css_hsay <消息> - 作为管理员在HUD发送消息\n- css_noclip <#用户ID或名称> - 切换玩家无碰撞模式\n- css_freeze <#用户ID或名称> [持续时间] - 冻结玩家\n- css_unfreeze <#用户ID或名称> - 解冻玩家\n- css_respawn <#用户ID或名称> - 重生玩家\n- css_cvar - 更改cvar值\n- css_rcon - 作为服务器运行命令", "sa_player_ban_message_time": "你被{lightred}{0}{default}封禁了{lightred}{1}{default}分钟,原因是{lightred}{2}{default}!", "sa_player_ban_message_perm": "你被{lightred}{0}{default}永久封禁了,原因是{lightred}{1}{default}!", "sa_player_kick_message": "你被{lightred}{0}{default}踢出了游戏,原因是{lightred}{1}{default}!",