diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c93c496..6a20dea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,7 +26,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore run: dotnet restore - name: Build @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore run: dotnet restore - name: Build diff --git a/CS2-SimpleAdmin.cs b/CS2-SimpleAdmin.cs index a25f03d..1e29e4c 100644 --- a/CS2-SimpleAdmin.cs +++ b/CS2-SimpleAdmin.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; -using Dapper; using Discord.Webhook; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; @@ -12,16 +11,16 @@ using System.Collections.Concurrent; namespace CS2_SimpleAdmin; -[MinimumApiVersion(191)] +[MinimumApiVersion(201)] public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig { public static CS2_SimpleAdmin Instance { get; private set; } = new(); public static IStringLocalizer? _localizer; - public static Dictionary voteAnswers = new Dictionary(); - public static ConcurrentBag godPlayers = new ConcurrentBag(); - public static ConcurrentBag silentPlayers = new ConcurrentBag(); - public static ConcurrentBag bannedPlayers = new ConcurrentBag(); + public static Dictionary voteAnswers = []; + public static ConcurrentBag godPlayers = []; + public static ConcurrentBag silentPlayers = []; + public static ConcurrentBag bannedPlayers = []; public static bool TagsDetected = false; public static bool voteInProgress = false; public static int? ServerId = null; @@ -38,7 +37,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.6c"; + public override string ModuleVersion => "1.3.9a"; public CS2_SimpleAdminConfig Config { get; set; } = new(); @@ -54,7 +53,6 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig _database.DatabaseMigration()); + + /* Task.Run(async () => { try @@ -90,8 +103,9 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig bag, int playerSlot) { - List tempList = new List(); + List tempList = []; while (!bag.IsEmpty) { if (bag.TryTake(out int item) && item != playerSlot) diff --git a/CS2-SimpleAdmin.csproj b/CS2-SimpleAdmin.csproj index dc0a740..0f6119c 100644 --- a/CS2-SimpleAdmin.csproj +++ b/CS2-SimpleAdmin.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 CS2_SimpleAdmin enable enable @@ -10,10 +10,10 @@ - + - - + + @@ -22,7 +22,7 @@ - + diff --git a/Commands/basebans.cs b/Commands/basebans.cs index 094e711..c4cf433 100644 --- a/Commands/basebans.cs +++ b/Commands/basebans.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; -using CounterStrikeSharp.API.Modules.Entities; using System.Text; namespace CS2_SimpleAdmin @@ -20,7 +19,7 @@ namespace CS2_SimpleAdmin if (command.ArgCount < 2) return; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; TargetResult? targets = GetTarget(command); if (targets == null) return; @@ -31,8 +30,7 @@ namespace CS2_SimpleAdmin return; } - Database database = new Database(dbConnectionString); - + Database database = new(dbConnectionString); BanManager _banManager = new(database, Config); int.TryParse(command.GetArg(2), out int time); @@ -44,14 +42,14 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - Ban(caller, player, time, reason, callerName, _banManager); + Ban(caller, player, time, reason, callerName, _banManager, command); } }); } - internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null) + internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null) { - if (_database == null) return; + if (_database == null || player is null || !player.IsValid) return; callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -60,24 +58,20 @@ namespace CS2_SimpleAdmin player.Pawn.Value!.Freeze(); } - PlayerInfo playerInfo = new PlayerInfo + PlayerInfo playerInfo = new() { SteamId = player.SteamID.ToString(), Name = player.PlayerName, IpAddress = player.IpAddress?.Split(":")[0] }; - PlayerInfo adminInfo = new PlayerInfo + PlayerInfo adminInfo = new() { SteamId = caller?.SteamID.ToString(), Name = caller?.PlayerName, IpAddress = caller?.IpAddress?.Split(":")[0] }; - string commandName = $"css_ban {player.SteamID} {time} {reason}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); - Task.Run(async () => { banManager ??= new BanManager(_database, Config); @@ -85,7 +79,8 @@ namespace CS2_SimpleAdmin }); if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); if (playerInfo.IpAddress != null && !bannedPlayers.Contains(playerInfo.IpAddress)) bannedPlayers.Add(playerInfo.IpAddress); @@ -133,6 +128,13 @@ namespace CS2_SimpleAdmin } } } + + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Ban, _discordWebhookClientPenalty, _localizer); } [ConsoleCommand("css_addban")] @@ -154,16 +156,9 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; - - Database database = new Database(dbConnectionString); + string reason = _localizer?["sa_unknown"] ?? "Unknown"; + Database database = new(dbConnectionString); BanManager _banManager = new(database, Config); int.TryParse(command.GetArg(2), out int time); @@ -178,8 +173,6 @@ namespace CS2_SimpleAdmin IpAddress = caller?.IpAddress?.Split(":")[0] }; - Helper.LogCommand(caller, command); - List matches = Helper.GetPlayerFromSteamid64(steamid); if (matches.Count == 1) { @@ -238,6 +231,8 @@ namespace CS2_SimpleAdmin } } } + + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Ban, _discordWebhookClientPenalty, _localizer); } Task.Run(async () => @@ -246,7 +241,14 @@ namespace CS2_SimpleAdmin await _banManager.AddBanBySteamid(steamid, adminInfo, reason, time); }); - command.ReplyToCommand($"Banned player with steamid {steamid}."); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } + //Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Ban, _discordWebhookClientPenalty, _localizer); + + command?.ReplyToCommand($"Banned player with steamid {steamid}."); } [ConsoleCommand("css_banip")] @@ -269,13 +271,9 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; PlayerInfo adminInfo = new PlayerInfo { @@ -284,8 +282,6 @@ namespace CS2_SimpleAdmin IpAddress = caller?.IpAddress?.Split(":")[0] }; - Helper.LogCommand(caller, command); - int.TryParse(command.GetArg(2), out int time); if (command.ArgCount >= 3 && command.GetArg(3).Length > 0) @@ -348,8 +344,14 @@ namespace CS2_SimpleAdmin } if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value, "Banned"), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + { + AddTimer(Config.KickTime, () => + { + Helper.KickPlayer(player.UserId.Value, "Banned"); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + } } + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Ban, _discordWebhookClientPenalty, _localizer); } Task.Run(async () => @@ -358,35 +360,39 @@ namespace CS2_SimpleAdmin await _banManager.AddBanByIp(ipAddress, adminInfo, reason, time); }); - command.ReplyToCommand($"Banned player with IP address {ipAddress}."); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } + + command?.ReplyToCommand($"Banned player with IP address {ipAddress}."); } [ConsoleCommand("css_unban")] [RequiresPermissions("@css/unban")] - [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + [CommandHelper(minArgs: 1, usage: " [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command) { if (_database == null) return; - string callerName = caller == null ? "Console" : caller.PlayerName; + string callerName = caller?.PlayerName ?? "Console"; + string callerSteamId = caller?.SteamID.ToString() ?? "Console"; + if (command.GetArg(1).Length <= 1) { command.ReplyToCommand($"Too short pattern to search."); return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - - Helper.LogCommand(caller, command); - string pattern = command.GetArg(1); + string reason = command.GetArg(2); - BanManager _banManager = new BanManager(_database, Config); - Task.Run(async () => await _banManager.UnbanPlayer(pattern)); + BanManager _banManager = new(_database, Config); + Task.Run(async () => await _banManager.UnbanPlayer(pattern, callerSteamId, reason)); + + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); command.ReplyToCommand($"Unbanned player with pattern {pattern}."); } diff --git a/Commands/basechat.cs b/Commands/basechat.cs index 6cee028..b347df9 100644 --- a/Commands/basechat.cs +++ b/Commands/basechat.cs @@ -4,7 +4,6 @@ using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using System.Text; @@ -21,12 +20,7 @@ namespace CS2_SimpleAdmin if (caller == null || !caller.IsValid || command.GetCommandString[command.GetCommandString.IndexOf(' ')..].Length == 0) return; string callerName = caller == null ? "Console" : caller.PlayerName; - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); byte[] utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]); @@ -54,12 +48,7 @@ namespace CS2_SimpleAdmin byte[] utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]); string utf8String = Encoding.UTF8.GetString(utf8BytesString); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); foreach (CCSPlayerController _player in Helper.GetValidPlayers()) @@ -84,7 +73,7 @@ namespace CS2_SimpleAdmin if (targets == null) return; List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.SteamID.ToString().Length == 17 && !player.IsHLTV).ToList(); - Helper.LogCommand(caller, command); + //Helper.LogCommand(caller, command); int range = command.GetArg(0).Length + command.GetArg(1).Length + 2; string message = command.GetCommandString[range..]; @@ -109,12 +98,7 @@ namespace CS2_SimpleAdmin byte[] utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]); string utf8String = Encoding.UTF8.GetString(utf8BytesString); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); Helper.PrintToCenterAll(StringExtensions.ReplaceColorTags(utf8String)); @@ -129,12 +113,7 @@ namespace CS2_SimpleAdmin byte[] utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]); string utf8String = Encoding.UTF8.GetString(utf8BytesString); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); VirtualFunctions.ClientPrintAll( diff --git a/Commands/basecommands.cs b/Commands/basecommands.cs index b4033fb..95e18b4 100644 --- a/Commands/basecommands.cs +++ b/Commands/basecommands.cs @@ -1,4 +1,4 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; @@ -33,7 +33,20 @@ namespace CS2_SimpleAdmin commandSql.CommandText = commandText; await commandSql.ExecuteNonQueryAsync(); - command.ReplyToCommand("Successfully updated the database"); + commandText = "ALTER TABLE `sa_servers` MODIFY COLUMN `hostname` varchar(128);"; + using var commandSql1 = connection.CreateCommand(); + commandSql1.CommandText = commandText; + await commandSql1.ExecuteNonQueryAsync(); + + commandText = "ALTER TABLE `sa_bans` MODIFY `ends` TIMESTAMP NULL DEFAULT NULL;"; + using var commandSql2 = connection.CreateCommand(); + commandSql2.CommandText = commandText; + await commandSql2.ExecuteNonQueryAsync(); + + Server.NextFrame(() => + { + command.ReplyToCommand($"Successfully updated the database - {ModuleVersion}"); + }); } catch (Exception ex) { @@ -118,18 +131,20 @@ namespace CS2_SimpleAdmin int time = 0; int.TryParse(command.GetArg(5), out time); - AddAdmin(caller, steamid, name, flags, immunity, time, globalAdmin); + AddAdmin(caller, steamid, name, flags, immunity, time, globalAdmin, command); } - public void AddAdmin(CCSPlayerController? caller, string steamid, string name, string flags, int immunity, int time = 0, bool globalAdmin = false, CommandInfo? command = null) + public static void AddAdmin(CCSPlayerController? caller, string steamid, string name, string flags, int immunity, int time = 0, bool globalAdmin = false, CommandInfo? command = null) { if (_database == null) return; AdminSQLManager _adminManager = new(_database); - _ = _adminManager.AddAdminBySteamId(steamid, name, flags, immunity, time, globalAdmin); - string commandName = $"css_addadmin {steamid} {name} {flags} {immunity} {time}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + List flagsList = flags.Split(',').Select(flag => flag.Trim()).ToList(); + _ = _adminManager.AddAdminBySteamId(steamid, name, flagsList, immunity, time, globalAdmin); + + if (command != null) + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, $"css_addadmin {steamid} {name} {flags} {immunity} {time}"); string msg = $"Added '{flags}' flags to '{name}' ({steamid})"; if (command != null) @@ -157,7 +172,7 @@ namespace CS2_SimpleAdmin string steamid = command.GetArg(1); bool globalDelete = command.GetArg(2).ToLower().Equals("-g"); - RemoveAdmin(caller, steamid, globalDelete); + RemoveAdmin(caller, steamid, globalDelete, command); } public void RemoveAdmin(CCSPlayerController? caller, string steamid, bool globalDelete = false, CommandInfo? command = null) @@ -180,9 +195,9 @@ namespace CS2_SimpleAdmin } }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - string commandName = $"css_deladmin {steamid}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, $"css_deladmin {steamid}"); string msg = $"Removed flags from '{steamid}'"; if (command != null) @@ -208,10 +223,7 @@ namespace CS2_SimpleAdmin public void ReloadAdmins(CCSPlayerController? caller) { if (_database == null) return; - - string commandName = "css_reladmin"; - Helper.TryLogCommandOnDiscord(caller, commandName); - + foreach (SteamID steamId in AdminSQLManager._adminCache.Keys.ToList()) { if (AdminSQLManager._adminCache.TryRemove(steamId, out _)) @@ -267,11 +279,8 @@ namespace CS2_SimpleAdmin TargetResult? targets = GetTarget(command); if (targets == null) return; - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } + Helper.LogCommand(caller, command); + //Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.SteamID.ToString().Length == 17 && !player.IsHLTV).ToList(); @@ -365,7 +374,7 @@ namespace CS2_SimpleAdmin public void OnKickCommand(CCSPlayerController? caller, CommandInfo command) { string callerName = caller == null ? "Console" : caller.PlayerName; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; TargetResult? targets = GetTarget(command); @@ -389,12 +398,12 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - Kick(caller, player, reason, callerName); + Kick(caller, player, reason, callerName, command); } }); } - public void Kick(CCSPlayerController? caller, CCSPlayerController player, string reason = "Unknown", string? callerName = null) + public void Kick(CCSPlayerController? caller, CCSPlayerController player, string reason = "Unknown", string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; if (player.PawnIsAlive) @@ -402,11 +411,11 @@ namespace CS2_SimpleAdmin player.Pawn.Value!.Freeze(); } - reason = reason ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; - - string commandName = $"css_kick {player.PlayerName} {reason}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); + reason ??= _localizer?["sa_unknown"] ?? "Unknown"; + + if (command != null) + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, $"css_kick {player.PlayerName} {reason}"); if (string.IsNullOrEmpty(reason) == false) { @@ -416,12 +425,14 @@ namespace CS2_SimpleAdmin player.PrintToCenter(_localizer!["sa_player_kick_message", reason, caller == null ? "Console" : caller.PlayerName]); } if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value, reason), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value, reason), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } else { if (player.UserId.HasValue) - AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + AddTimer(Config.KickTime, () => Helper.KickPlayer(player.UserId.Value), + CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } if (caller == null || caller != null && caller.UserId != null && !silentPlayers.Contains(caller.Slot)) @@ -466,12 +477,7 @@ namespace CS2_SimpleAdmin _command = $"ds_workshop_changelevel {map.Replace("ws:", "")}"; } - string commandName = command?.GetCommandString ?? $"css_changewsmap {map}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - if (command is not null) - Helper.LogCommand(caller, command); - - AddTimer(2.0f, () => + AddTimer(3.0f, () => { Server.ExecuteCommand(_command); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); @@ -489,6 +495,11 @@ namespace CS2_SimpleAdmin Server.PrintToConsole(msg); return; } + + AddTimer(3.0f, () => + { + Server.ExecuteCommand($"changelevel {map}"); + }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) @@ -504,15 +515,10 @@ namespace CS2_SimpleAdmin } } - if (!map.StartsWith("ws:")) + if (command != null) { - string commandName = command?.GetCommandString ?? $"css_changemap {map}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - - AddTimer(2.0f, () => - { - Server.ExecuteCommand($"changelevel {map}"); - }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); } } @@ -555,16 +561,17 @@ namespace CS2_SimpleAdmin } } } - - string commandName = command?.GetCommandString ?? $"css_changewsmap {map}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - if (command is not null) - Helper.LogCommand(caller, command); - AddTimer(2.0f, () => + AddTimer(3.0f, () => { Server.ExecuteCommand(_command); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); + + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } } [ConsoleCommand("css_cvar", "Change a cvar.")] @@ -587,12 +594,7 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); var value = command.GetArg(2); @@ -610,12 +612,7 @@ namespace CS2_SimpleAdmin { string callerName = caller == null ? "Console" : caller.PlayerName; - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); Server.ExecuteCommand(command.ArgString); @@ -636,13 +633,10 @@ namespace CS2_SimpleAdmin public static void RestartGame(CCSPlayerController? admin) { + Helper.LogCommand(admin, "css_restartgame"); + // TODO: Localize - string name = admin == null ? "Console" : admin.PlayerName; - - string commandName = "css_restartgame"; - Helper.TryLogCommandOnDiscord(admin, commandName); - Helper.LogCommand(admin, commandName); - + var name = admin == null ? "Console" : admin.PlayerName; Server.PrintToChatAll($"[SA] {name}: Restarting game..."); Server.ExecuteCommand("mp_restartgame 2"); } diff --git a/Commands/basecomms.cs b/Commands/basecomms.cs index e7e57f4..f3c3816 100644 --- a/Commands/basecomms.cs +++ b/Commands/basecomms.cs @@ -1,11 +1,10 @@ -using CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; -using CounterStrikeSharp.API.Modules.Entities; using System.Text; namespace CS2_SimpleAdmin @@ -21,7 +20,7 @@ namespace CS2_SimpleAdmin string callerName = caller == null ? "Console" : caller.PlayerName; int time = 0; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; TargetResult? targets = GetTarget(command); if (targets == null) return; @@ -44,12 +43,12 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - Gag(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager); + Gag(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager, command); } }); } - internal void Gag(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null) + internal void Gag(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null, CommandInfo? command = null) { if (_database == null) return; callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -69,10 +68,6 @@ namespace CS2_SimpleAdmin Name = caller?.PlayerName, IpAddress = caller?.IpAddress?.Split(":")[0] }; - - string commandName = $"css_gag {player?.SteamID} {time} {reason}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); Task.Run(async () => { @@ -82,8 +77,7 @@ namespace CS2_SimpleAdmin if (TagsDetected) Server.ExecuteCommand($"css_tag_mute {player!.SteamID}"); - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Gag, DateTime.Now.AddMinutes(time), time); - + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Gag, DateTime.Now.AddMinutes(time), time); if (time == 0) { if (!player!.IsBot && !player.IsHLTV) @@ -130,6 +124,13 @@ namespace CS2_SimpleAdmin } } } + + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Gag, _discordWebhookClientPenalty, _localizer); + Helper.LogCommand(caller, command); + } } [ConsoleCommand("css_addgag")] @@ -153,14 +154,8 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - int time = 0; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; MuteManager _muteManager = new(_database); PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); @@ -177,8 +172,6 @@ namespace CS2_SimpleAdmin IpAddress = caller?.IpAddress?.Split(":")[0] }; - Helper.LogCommand(caller, command); - List matches = Helper.GetPlayerFromSteamid64(steamid); if (matches.Count == 1) { @@ -237,8 +230,10 @@ namespace CS2_SimpleAdmin if (TagsDetected) Server.ExecuteCommand($"css_tag_mute {player!.SteamID}"); - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Gag, DateTime.Now.AddMinutes(time), time); + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Gag, DateTime.Now.AddMinutes(time), time); } + + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Gag, _discordWebhookClientPenalty, _localizer); } Task.Run(async () => @@ -246,18 +241,27 @@ namespace CS2_SimpleAdmin await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 0); }); - command.ReplyToCommand($"Gagged player with steamid {steamid}."); + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } + + command?.ReplyToCommand($"Gagged player with steamid {steamid}."); } [ConsoleCommand("css_ungag")] [RequiresPermissions("@css/chat")] - [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + [CommandHelper(minArgs: 1, usage: " [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnUngagCommand(CCSPlayerController? caller, CommandInfo command) { if (_database == null) return; string callerName = caller == null ? "Console" : caller.PlayerName; + string callerSteamId = caller?.SteamID.ToString() ?? "Console"; + string foundPlayerName = string.Empty; string foundPlayerSteamId64 = string.Empty; + string reason = command.GetArg(2); if (command.GetArg(1).Length <= 1) { @@ -265,12 +269,7 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); bool found = false; @@ -288,7 +287,7 @@ namespace CS2_SimpleAdmin CCSPlayerController? player = matches.FirstOrDefault(); if (player != null && player.IsValid) { - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Gag); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Gag); if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); @@ -307,7 +306,7 @@ namespace CS2_SimpleAdmin CCSPlayerController? player = matches.FirstOrDefault(); if (player != null && player.IsValid) { - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Gag); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Gag); if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID.ToString()}"); @@ -323,12 +322,12 @@ namespace CS2_SimpleAdmin if (found) { - Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, 0); }); // Unmute by type 0 (gag) + Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, callerSteamId, reason, 0); }); // Unmute by type 0 (gag) command.ReplyToCommand($"Ungaged player {foundPlayerName}."); } else { - Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, 0); }); // Unmute by type 0 (gag) + Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, callerSteamId, reason, 0); }); // Unmute by type 0 (gag) command.ReplyToCommand($"Ungaged offline player with pattern {pattern}."); } @@ -372,7 +371,7 @@ namespace CS2_SimpleAdmin string callerName = caller == null ? "Console" : caller.PlayerName; int time = 0; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; TargetResult? targets = GetTarget(command); if (targets == null) return; @@ -395,12 +394,12 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - Mute(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager); + Mute(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager, command); } }); } - internal void Mute(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null) + internal void Mute(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null, CommandInfo? command = null) { if (_database == null) return; callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -420,10 +419,6 @@ namespace CS2_SimpleAdmin Name = caller?.PlayerName, IpAddress = caller?.IpAddress?.Split(":")[0] }; - - string commandName = $"css_mute {player?.SteamID} {time} {reason}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); player!.VoiceFlags = VoiceFlags.Muted; @@ -432,7 +427,7 @@ namespace CS2_SimpleAdmin await muteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1); }); - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Mute, DateTime.Now.AddMinutes(time), time); + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Mute, DateTime.Now.AddMinutes(time), time); if (time == 0) { @@ -475,6 +470,13 @@ namespace CS2_SimpleAdmin } } } + + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Mute, _discordWebhookClientPenalty, _localizer); + Helper.LogCommand(caller, command); + } } [ConsoleCommand("css_addmute")] @@ -497,16 +499,8 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - - Helper.LogCommand(caller, command); - int time = 0; - string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + string reason = _localizer?["sa_unknown"] ?? "Unknown"; MuteManager _muteManager = new(_database); PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); @@ -535,7 +529,7 @@ namespace CS2_SimpleAdmin return; } - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Mute, DateTime.Now.AddMinutes(time), time); + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Mute, DateTime.Now.AddMinutes(time), time); if (time == 0) { @@ -578,6 +572,8 @@ namespace CS2_SimpleAdmin } } } + + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Mute, _discordWebhookClientPenalty, _localizer); } Task.Run(async () => @@ -585,7 +581,13 @@ namespace CS2_SimpleAdmin await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1); }); - command.ReplyToCommand($"Muted player with steamid {steamid}."); + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } + + command?.ReplyToCommand($"Muted player with steamid {steamid}."); } [ConsoleCommand("css_unmute")] @@ -595,8 +597,11 @@ namespace CS2_SimpleAdmin { if (_database == null) return; string callerName = caller == null ? "Console" : caller.PlayerName; + string callerSteamId = caller?.SteamID.ToString() ?? "Console"; + string foundPlayerName = string.Empty; string foundPlayerSteamId64 = string.Empty; + string reason = command.GetArg(2); if (command.GetArg(1).Length <= 1) { @@ -604,18 +609,13 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); string pattern = command.GetArg(1); bool found = false; MuteManager _muteManager = new(_database); - PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + PlayerPenaltyManager playerPenaltyManager = new(); if (Helper.IsValidSteamID64(pattern)) { @@ -625,7 +625,7 @@ namespace CS2_SimpleAdmin CCSPlayerController? player = matches.FirstOrDefault(); if (player != null && player.IsValid) { - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Mute); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Mute); player.VoiceFlags = VoiceFlags.Normal; found = true; foundPlayerName = player.PlayerName; @@ -641,7 +641,7 @@ namespace CS2_SimpleAdmin CCSPlayerController? player = matches.FirstOrDefault(); if (player != null && player.IsValid) { - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Mute); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Mute); player.VoiceFlags = VoiceFlags.Normal; pattern = player.SteamID.ToString(); found = true; @@ -653,12 +653,12 @@ namespace CS2_SimpleAdmin if (found) { - Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, 1); }); // Unmute by type 1 (mute) + Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, callerSteamId, reason, 1); }); // Unmute by type 1 (mute) command.ReplyToCommand($"Unmuted player {foundPlayerName}."); } else { - Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, 1); }); // Unmute by type 1 (mute) + Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, callerSteamId, reason, 1); }); // Unmute by type 1 (mute) command.ReplyToCommand($"Unmuted offline player with pattern {pattern}."); } @@ -720,12 +720,12 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - Silence(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager); + Silence(caller, player, time, reason, callerName, _muteManager, playerPenaltyManager, command); } }); } - internal void Silence(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null) + internal void Silence(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, MuteManager? muteManager = null, PlayerPenaltyManager? playerPenaltyManager = null, CommandInfo? command = null) { if (_database == null) return; callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -745,10 +745,6 @@ namespace CS2_SimpleAdmin Name = caller?.PlayerName, IpAddress = caller?.IpAddress?.Split(":")[0] }; - - string commandName = $"css_silence {player?.SteamID} {time} {reason}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); Task.Run(async () => { @@ -759,8 +755,7 @@ namespace CS2_SimpleAdmin Server.ExecuteCommand($"css_tag_mute {player!.SteamID}"); player!.VoiceFlags = VoiceFlags.Muted; - - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Silence, DateTime.Now.AddMinutes(time), time); + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Silence, DateTime.Now.AddMinutes(time), time); if (time == 0) { @@ -808,6 +803,13 @@ namespace CS2_SimpleAdmin } } } + + if (command != null) + { + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Mute, _discordWebhookClientPenalty, _localizer); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } } [ConsoleCommand("css_addsilence")] @@ -830,14 +832,6 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - - Helper.LogCommand(caller, command); - int time = 0; string reason = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; @@ -871,7 +865,7 @@ namespace CS2_SimpleAdmin if (TagsDetected) Server.ExecuteCommand($"css_tag_mute {player!.SteamID}"); - playerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Silence, DateTime.Now.AddMinutes(time), time); + PlayerPenaltyManager.AddPenalty(player!.Slot, PenaltyType.Silence, DateTime.Now.AddMinutes(time), time); if (time == 0) { @@ -913,6 +907,8 @@ namespace CS2_SimpleAdmin } } } + + Helper.SendDiscordPenaltyMessage(caller, player, reason, time, Helper.PenaltyType.Mute, _discordWebhookClientPenalty, _localizer); } } Task.Run(async () => @@ -920,18 +916,27 @@ namespace CS2_SimpleAdmin await _muteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2); }); - command.ReplyToCommand($"Silenced player with steamid {steamid}."); + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } + + command?.ReplyToCommand($"Silenced player with steamid {steamid}."); } [ConsoleCommand("css_unsilence")] [RequiresPermissions("@css/chat")] - [CommandHelper(minArgs: 1, usage: "", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] + [CommandHelper(minArgs: 1, usage: " [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)] public void OnUnsilenceCommand(CCSPlayerController? caller, CommandInfo command) { if (_database == null) return; string callerName = caller == null ? "Console" : caller.PlayerName; + string callerSteamId = caller?.SteamID.ToString() ?? "Console"; + string foundPlayerName = string.Empty; string foundPlayerSteamId64 = string.Empty; + string reason = command.GetArg(2); if (command.GetArg(1).Length <= 1) { @@ -939,18 +944,13 @@ namespace CS2_SimpleAdmin return; } - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); string pattern = command.GetArg(1); bool found = false; MuteManager _muteManager = new(_database); - PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + PlayerPenaltyManager playerPenaltyManager = new(); if (Helper.IsValidSteamID64(pattern)) { @@ -963,7 +963,7 @@ namespace CS2_SimpleAdmin if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Silence); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Silence); player.VoiceFlags = VoiceFlags.Normal; found = true; foundPlayerName = player.PlayerName; @@ -982,7 +982,7 @@ namespace CS2_SimpleAdmin if (TagsDetected) Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); - playerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Silence); + PlayerPenaltyManager.RemovePenaltiesByType(player!.Slot, PenaltyType.Silence); player.VoiceFlags = VoiceFlags.Normal; pattern = player.SteamID.ToString(); found = true; @@ -994,13 +994,13 @@ namespace CS2_SimpleAdmin if (found) { - Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, 2); }); // Unmute by type 2 (silence) + Task.Run(async () => { await _muteManager.UnmutePlayer(foundPlayerSteamId64, callerSteamId, reason, 2); }); // Unmute by type 2 (silence) command.ReplyToCommand($"Unsilenced player {foundPlayerName}."); return; } else { - Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, 2); }); // Unmute by type 2 (silence) + Task.Run(async () => { await _muteManager.UnmutePlayer(pattern, callerSteamId, reason, 2); }); // Unmute by type 2 (silence) command.ReplyToCommand($"Unsilenced offline player with pattern {pattern}."); return; } diff --git a/Commands/basevotes.cs b/Commands/basevotes.cs index 03965c1..088ada6 100644 --- a/Commands/basevotes.cs +++ b/Commands/basevotes.cs @@ -3,7 +3,6 @@ using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Menu; using System.Text; @@ -20,12 +19,7 @@ namespace CS2_SimpleAdmin if (command.GetArg(1) == null || command.GetArg(1).Length < 0 || command.ArgCount < 2) return; - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); Helper.LogCommand(caller, command); voteAnswers.Clear(); diff --git a/Commands/funcommands.cs b/Commands/funcommands.cs index 6d32789..f2b7f53 100644 --- a/Commands/funcommands.cs +++ b/Commands/funcommands.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; -using CounterStrikeSharp.API.Modules.Entities; using System.Text; namespace CS2_SimpleAdmin @@ -21,6 +20,8 @@ namespace CS2_SimpleAdmin TargetResult? targets = GetTarget(command); List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.SteamID.ToString().Length == 17 && player.PawnIsAlive && !player.IsHLTV).ToList(); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + playersToTarget.ForEach(player => { if (caller!.CanTarget(player)) @@ -35,9 +36,7 @@ namespace CS2_SimpleAdmin callerName ??= caller == null ? "Console" : caller.PlayerName; player!.Pawn.Value!.ToggleNoclip(); - string commandName = $"css_noclip {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + Helper.LogCommand(caller, $"css_noclip {player.PlayerName}"); if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -64,6 +63,8 @@ namespace CS2_SimpleAdmin TargetResult? targets = GetTarget(command); List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.PawnIsAlive && !player.IsHLTV).ToList(); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + playersToTarget.ForEach(player => { if (!player.IsBot && player.SteamID.ToString().Length != 17) @@ -82,9 +83,7 @@ namespace CS2_SimpleAdmin player.Pawn.Value!.Freeze(); - string commandName = $"css_freeze {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + Helper.LogCommand(caller, $"css_freeze {player.PlayerName}"); if (time > 0) AddTimer(time, () => player.Pawn.Value!.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); @@ -118,19 +117,21 @@ namespace CS2_SimpleAdmin if (!player.IsBot && player.SteamID.ToString().Length != 17) return; - Unfreeze(caller, player, callerName); + Unfreeze(caller, player, callerName, command); }); } - public void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null) + public void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; player!.Pawn.Value!.Unfreeze(); - string commandName = $"css_unfreeze {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { diff --git a/Commands/playercommands.cs b/Commands/playercommands.cs index 598db7e..190f3e5 100644 --- a/Commands/playercommands.cs +++ b/Commands/playercommands.cs @@ -1,10 +1,9 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Core.Translations; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Commands.Targeting; -using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; @@ -27,11 +26,11 @@ namespace CS2_SimpleAdmin playersToTarget.ForEach(player => { - Slay(caller, player, callerName); + Slay(caller, player, callerName, command); }); } - public void Slay(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null) + public void Slay(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null) { if (!player.IsBot && player.SteamID.ToString().Length != 17) return; @@ -40,9 +39,11 @@ namespace CS2_SimpleAdmin player.CommitSuicide(false, true); - string commandName = $"css_slay {player.PlayerName}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); + if (command != null) + { + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + Helper.LogCommand(caller, command); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -99,7 +100,7 @@ namespace CS2_SimpleAdmin if (!player.IsBot && player.SteamID.ToString().Length != 17) return; - GiveWeapon(caller, player, weaponName, callerName); + GiveWeapon(caller, player, weaponName, callerName, command); }); } @@ -111,9 +112,13 @@ namespace CS2_SimpleAdmin SubGiveWeapon(caller, player!, weapon.ToString(), callerName); } - public void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null) + public void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null, CommandInfo? command = null) { - Helper.LogCommand(caller, $"css_give {player?.PlayerName} {weaponName}"); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } player?.GiveNamedItem(weaponName); SubGiveWeapon(caller, player!, weaponName, callerName); @@ -122,11 +127,7 @@ namespace CS2_SimpleAdmin public void SubGiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; - - string commandName = $"css_give {player.PlayerName} {weaponName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); - + if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { foreach (CCSPlayerController _player in Helper.GetValidPlayers()) @@ -156,12 +157,12 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - StripWeapons(caller, player, callerName); + StripWeapons(caller, player, callerName, command); } }); } - public void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null) + public void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; @@ -170,9 +171,11 @@ namespace CS2_SimpleAdmin player.RemoveWeapons(); - string commandName = $"css_strip {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -206,12 +209,12 @@ namespace CS2_SimpleAdmin { if (caller!.CanTarget(player)) { - SetHp(caller, player, health, callerName); + SetHp(caller, player, health, callerName, command); } }); } - public void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, string? callerName = null) + public void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, string? callerName = null, CommandInfo? command = null) { if (!player.IsBot && player.SteamID.ToString().Length != 17) return; @@ -220,9 +223,11 @@ namespace CS2_SimpleAdmin player.SetHp(health); - string commandName = $"css_hp {player.PlayerName} {health}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -259,20 +264,22 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - SetSpeed(caller, player, speed, callerName); + SetSpeed(caller, player, speed, callerName, command); } }); } - public void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, double speed, string? callerName = null) + public void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, double speed, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; player.SetSpeed((float)speed); - string commandName = $"css_speed {player?.PlayerName} {speed}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -300,6 +307,8 @@ namespace CS2_SimpleAdmin TargetResult? targets = GetTarget(command); if (targets == null) return; + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && player.PawnIsAlive && !player.IsHLTV).ToList(); playersToTarget.ForEach(player => @@ -309,20 +318,22 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - SetGravity(caller, player, gravity, callerName); + SetGravity(caller, player, gravity, callerName, command); } }); } - public void SetGravity(CCSPlayerController? caller, CCSPlayerController player, double gravity, string? callerName = null) + public void SetGravity(CCSPlayerController? caller, CCSPlayerController player, double gravity, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; player.SetGravity((float)gravity); - string commandName = $"css_gravity {player?.PlayerName} {gravity}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -359,20 +370,22 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - SetMoney(caller, player, money, callerName); + SetMoney(caller, player, money, callerName, command); } }); } - public void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, string? callerName = null) + public void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; player.SetMoney(money); - string commandName = $"css_money {player?.PlayerName} {money}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -406,40 +419,42 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - God(caller, player, callerName); + God(caller, player, callerName, command); } }); } - public void God(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null) + public void God(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; - if (player == null || player.IsValid == false) - return; - - string commandName = $"css_god {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, callerName); - - if (!godPlayers.Contains(player.Slot)) + if (player != null) { - godPlayers.Add(player.Slot); - } - else - { - RemoveFromConcurrentBag(godPlayers, player.Slot); - } - - if (caller == null || !silentPlayers.Contains(caller.Slot)) - { - foreach (CCSPlayerController _player in Helper.GetValidPlayers()) + if (command != null) { - using (new WithTemporaryCulture(_player.GetLanguage())) + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } + + if (!godPlayers.Contains(player.Slot)) + { + godPlayers.Add(player.Slot); + } + else + { + RemoveFromConcurrentBag(godPlayers, player.Slot); + } + + if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) + { + foreach (CCSPlayerController _player in Helper.GetValidPlayers()) { - StringBuilder sb = new(_localizer!["sa_prefix"]); - sb.Append(_localizer["sa_admin_god_message", callerName, player.PlayerName]); - _player.PrintToChat(sb.ToString()); + using (new WithTemporaryCulture(_player.GetLanguage())) + { + StringBuilder sb = new(_localizer!["sa_prefix"]); + sb.Append(_localizer["sa_admin_god_message", callerName, player.PlayerName]); + _player.PrintToChat(sb.ToString()); + } } } } @@ -470,19 +485,21 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - Slap(caller, player, damage); + Slap(caller, player, damage, command); } }); } - public void Slap(CCSPlayerController? caller, CCSPlayerController player, int damage, string? callerName = null) + public void Slap(CCSPlayerController? caller, CCSPlayerController player, int damage, CommandInfo? command = null) { - callerName ??= caller == null ? "Console" : caller.PlayerName; + string callerName = caller == null ? "Console" : caller.PlayerName; player!.Pawn.Value!.Slap(damage); - string commandName = $"css_slap {player.PlayerName} {damage}"; - Helper.LogCommand(caller, callerName); - Helper.TryLogCommandOnDiscord(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -540,23 +557,18 @@ namespace CS2_SimpleAdmin bool kill = command.GetArg(3).ToLower().Equals("-k"); - Helper.LogCommand(caller, command); - playersToTarget.ForEach(player => { - ChangeTeam(caller, player, _teamName, teamNum, kill, callerName); + ChangeTeam(caller, player, _teamName, teamNum, kill, callerName, command); }); } - public void ChangeTeam(CCSPlayerController? caller, CCSPlayerController player, string teamName, CsTeam teamNum, bool kill, string? callerName = null) + public void ChangeTeam(CCSPlayerController? caller, CCSPlayerController player, string teamName, CsTeam teamNum, bool kill, string? callerName = null, CommandInfo? command = null) { if (!player.IsBot && player.SteamID.ToString().Length != 17) return; callerName ??= caller == null ? "Console" : caller.PlayerName; - string commandName = $"css_team {player.PlayerName} {teamName} {teamNum} {kill}"; - Helper.LogCommand(caller, commandName); - Helper.TryLogCommandOnDiscord(caller, commandName); if (!teamName.Equals("swap")) { @@ -594,6 +606,12 @@ namespace CS2_SimpleAdmin } } } + + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } } [ConsoleCommand("css_rename", "Rename a player.")] @@ -610,13 +628,8 @@ namespace CS2_SimpleAdmin TargetResult? targets = GetTarget(command); List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && !player.IsHLTV).ToList(); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); playersToTarget.ForEach(player => { @@ -625,8 +638,6 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - player.Rename(newName); - if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { foreach (CCSPlayerController _player in Helper.GetValidPlayers()) @@ -639,6 +650,8 @@ namespace CS2_SimpleAdmin } } } + + player.Rename(newName); } }); } @@ -660,25 +673,27 @@ namespace CS2_SimpleAdmin if (caller!.CanTarget(player)) { - Respawn(caller, player, callerName); + Respawn(caller, player, callerName, command); } }); } - public void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null) + public void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null) { callerName ??= caller == null ? "Console" : caller.PlayerName; if (CBasePlayerController_SetPawnFunc == null || player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) return; - CCSPlayerPawn? playerPawn = player.PlayerPawn.Value; + var playerPawn = player.PlayerPawn.Value; CBasePlayerController_SetPawnFunc.Invoke(player, playerPawn, true, false); VirtualFunction.CreateVoid(player.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(player); - string commandName = $"css_respawn {player.PlayerName}"; - Helper.TryLogCommandOnDiscord(caller, commandName); - Helper.LogCommand(caller, commandName); + if (command != null) + { + Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); + } if (caller == null || caller != null && !silentPlayers.Contains(caller.Slot)) { @@ -712,13 +727,8 @@ namespace CS2_SimpleAdmin List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && !player.IsHLTV).ToList(); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); playersToTarget.ForEach(player => { @@ -768,13 +778,8 @@ namespace CS2_SimpleAdmin List playersToTarget = targets!.Players.Where(player => player != null && player.IsValid && !player.IsHLTV).ToList(); - if (_discordWebhookClientLog != null && _localizer != null) - { - string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; - _discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(_localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); - } - Helper.LogCommand(caller, command); + Helper.SendDiscordLogMessage(caller, command, _discordWebhookClientLog, _localizer); playersToTarget.ForEach(player => { diff --git a/Config.cs b/Config.cs index 5f07dc7..595e8cf 100644 --- a/Config.cs +++ b/Config.cs @@ -29,7 +29,7 @@ namespace CS2_SimpleAdmin public class CS2_SimpleAdminConfig : BasePluginConfig { - [JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 8; + [JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 9; [JsonPropertyName("DatabaseHost")] public string DatabaseHost { get; set; } = ""; @@ -46,6 +46,9 @@ namespace CS2_SimpleAdmin [JsonPropertyName("DatabaseName")] public string DatabaseName { get; set; } = ""; + [JsonPropertyName("EnableMetrics")] + public bool EnableMetrics { get; set; } = true; + [JsonPropertyName("UseChatMenu")] public bool UseChatMenu { get; set; } = false; diff --git a/Database/Database.cs b/Database/Database.cs index 521c8ca..3a2addd 100644 --- a/Database/Database.cs +++ b/Database/Database.cs @@ -1,31 +1,60 @@ using Microsoft.Extensions.Logging; using MySqlConnector; -namespace CS2_SimpleAdmin +namespace CS2_SimpleAdmin; + +public class Database(string dbConnectionString) { - public class Database + private readonly string _dbConnectionString = dbConnectionString; + + public MySqlConnection GetConnection() { - private readonly string _dbConnectionString; - - public Database(string dbConnectionString) + try { - _dbConnectionString = dbConnectionString; + var connection = new MySqlConnection(_dbConnectionString); + connection.Open(); + return connection; } - - public async Task GetConnectionAsync() + catch (Exception ex) { - try - { - var connection = new MySqlConnection(_dbConnectionString); - await connection.OpenAsync(); - return connection; - } - catch (Exception ex) - { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical($"Unable to connect to database: {ex.Message}"); - throw; - } + if (CS2_SimpleAdmin._logger != null) + CS2_SimpleAdmin._logger.LogCritical($"Unable to connect to database: {ex.Message}"); + throw; } } -} \ No newline at end of file + + public async Task GetConnectionAsync() + { + try + { + var connection = new MySqlConnection(_dbConnectionString); + await connection.OpenAsync(); + return connection; + } + catch (Exception ex) + { + CS2_SimpleAdmin._logger?.LogCritical($"Unable to connect to database: {ex.Message}"); + throw; + } + } + + public void DatabaseMigration() + { + Migration migrator = new(this); + migrator.ExecuteMigrations(); + } + + public bool CheckDatabaseConnection() + { + using MySqlConnection connection = GetConnection(); + + try + { + return connection.Ping(); + } + catch + { + return false; + } + } +} diff --git a/Database/Migration.cs b/Database/Migration.cs new file mode 100644 index 0000000..80ade5a --- /dev/null +++ b/Database/Migration.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.Logging; +using MySqlConnector; + +namespace CS2_SimpleAdmin; + +public class Migration(Database database) +{ + private readonly Database _database = database; + + public void ExecuteMigrations() + { + string migrationsDirectory = CS2_SimpleAdmin.Instance.ModuleDirectory + "/Database/Migrations"; + + var files = Directory.GetFiles(migrationsDirectory, "*.sql") + .OrderBy(f => f); + + using MySqlConnection connection = _database.GetConnection(); + + // Create sa_migrations table if not exists + using var cmd = new MySqlCommand(@" + CREATE TABLE IF NOT EXISTS `sa_migrations` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `version` VARCHAR(255) NOT NULL + );", connection); + + cmd.ExecuteNonQuery(); + + // Get the last applied migration version + var lastAppliedVersion = GetLastAppliedVersion(connection); + + foreach (var file in files) + { + var version = Path.GetFileNameWithoutExtension(file); + + // Check if the migration has already been applied + if (string.Compare(version, lastAppliedVersion, StringComparison.OrdinalIgnoreCase) > 0) + { + var sqlScript = File.ReadAllText(file); + + using var cmdMigration = new MySqlCommand(sqlScript, connection); + cmdMigration.ExecuteNonQuery(); + + // Update the last applied migration version + UpdateLastAppliedVersion(connection, version); + + CS2_SimpleAdmin._logger?.LogInformation($"Migration \"{version}\" successfully applied."); + } + } + } + + private static string GetLastAppliedVersion(MySqlConnection connection) + { + using var cmd = new MySqlCommand("SELECT `version` FROM `sa_migrations` ORDER BY `id` DESC LIMIT 1;", connection); + var result = cmd.ExecuteScalar(); + return result?.ToString() ?? string.Empty; + } + + private static void UpdateLastAppliedVersion(MySqlConnection connection, string version) + { + using var cmd = new MySqlCommand("INSERT INTO `sa_migrations` (`version`) VALUES (@Version);", connection); + cmd.Parameters.AddWithValue("@Version", version); + cmd.ExecuteNonQuery(); + } +} diff --git a/Database/database_setup.sql b/Database/Migrations/001_CreateTables.sql similarity index 94% rename from Database/database_setup.sql rename to Database/Migrations/001_CreateTables.sql index 44622a4..26c50b7 100644 --- a/Database/database_setup.sql +++ b/Database/Migrations/001_CreateTables.sql @@ -1,13 +1,13 @@ CREATE TABLE IF NOT EXISTS `sa_bans` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `player_steamid` VARCHAR(64), `player_name` VARCHAR(128), + `player_steamid` VARCHAR(64), `player_ip` VARCHAR(128), `admin_steamid` VARCHAR(64) NOT NULL, `admin_name` VARCHAR(128) NOT NULL, `reason` VARCHAR(255) NOT NULL, `duration` INT NOT NULL, - `ends` TIMESTAMP NOT NULL, + `ends` TIMESTAMP NULL, `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `server_id` INT NULL, `status` ENUM('ACTIVE', 'UNBANNED', 'EXPIRED', '') NOT NULL DEFAULT 'ACTIVE' @@ -15,13 +15,13 @@ CREATE TABLE IF NOT EXISTS `sa_bans` ( CREATE TABLE IF NOT EXISTS `sa_mutes` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `player_steamid` varchar(64) NOT NULL, `player_name` varchar(128) NULL, + `player_steamid` varchar(64) NOT NULL, `admin_steamid` varchar(64) NOT NULL, `admin_name` varchar(128) NOT NULL, `reason` varchar(255) NOT NULL, `duration` int(11) NOT NULL, - `ends` timestamp NOT NULL, + `ends` timestamp NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `type` enum('GAG','MUTE','SILENCE','') NOT NULL DEFAULT 'GAG', `server_id` INT NULL, @@ -31,8 +31,8 @@ CREATE TABLE IF NOT EXISTS `sa_mutes` ( CREATE TABLE IF NOT EXISTS `sa_admins` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `player_steamid` varchar(64) NOT NULL, `player_name` varchar(128) NOT NULL, + `player_steamid` varchar(64) NOT NULL, `flags` TEXT NOT NULL, `immunity` varchar(64) NOT NULL DEFAULT '0', `server_id` INT NULL, @@ -43,8 +43,8 @@ CREATE TABLE IF NOT EXISTS `sa_admins` ( CREATE TABLE IF NOT EXISTS `sa_servers` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `hostname` varchar(128) NOT NULL, `address` varchar(64) NOT NULL, - `hostname` varchar(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `address` (`address`) ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; \ No newline at end of file diff --git a/Database/Migrations/002_CreateFlagsTable.sql b/Database/Migrations/002_CreateFlagsTable.sql new file mode 100644 index 0000000..3c9b75b --- /dev/null +++ b/Database/Migrations/002_CreateFlagsTable.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `sa_admins_flags` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `admin_id` int(11) NOT NULL, + `flag` varchar(64) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`admin_id`) REFERENCES `sa_admins` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +ALTER TABLE `sa_admins` CHANGE `flags` `flags` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL; diff --git a/Database/Migrations/003_ChangeColumnsPosition.sql b/Database/Migrations/003_ChangeColumnsPosition.sql new file mode 100644 index 0000000..d25915a --- /dev/null +++ b/Database/Migrations/003_ChangeColumnsPosition.sql @@ -0,0 +1,4 @@ +ALTER TABLE `sa_bans` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`; +ALTER TABLE `sa_mutes` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`; +ALTER TABLE `sa_admins` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`; +ALTER TABLE `sa_servers` CHANGE `hostname` `hostname` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`; \ No newline at end of file diff --git a/Database/Migrations/004_MoveOldFlagsToFlagsTable.sql b/Database/Migrations/004_MoveOldFlagsToFlagsTable.sql new file mode 100644 index 0000000..63d42c8 --- /dev/null +++ b/Database/Migrations/004_MoveOldFlagsToFlagsTable.sql @@ -0,0 +1,30 @@ +INSERT INTO sa_admins_flags (admin_id, flag) +WITH RECURSIVE numbers AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM numbers + WHERE n < (SELECT MAX(CHAR_LENGTH(flags) - CHAR_LENGTH(REPLACE(flags, ',', '')) + 1) FROM sa_admins) +) +SELECT + min_admins.admin_id, + TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(sa_admins.flags, ',', numbers.n), ',', -1)) AS flag +FROM numbers +JOIN ( + SELECT MIN(id) AS admin_id, player_steamid, server_id + FROM sa_admins + WHERE player_steamid != 'Console' + GROUP BY player_steamid, server_id +) AS min_admins ON 1=1 +JOIN sa_admins ON CHAR_LENGTH(sa_admins.flags) - CHAR_LENGTH(REPLACE(sa_admins.flags, ',', '')) >= numbers.n - 1 + AND min_admins.player_steamid = sa_admins.player_steamid + AND (min_admins.server_id = sa_admins.server_id OR (min_admins.server_id IS NULL AND sa_admins.server_id IS NULL)) + +UNION + +SELECT + (SELECT MAX(id) + 1 FROM sa_admins WHERE server_id IS NULL) AS admin_id, + TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(sa_admins.flags, ',', numbers.n), ',', -1)) AS flag +FROM numbers +JOIN sa_admins ON CHAR_LENGTH(sa_admins.flags) - CHAR_LENGTH(REPLACE(sa_admins.flags, ',', '')) >= numbers.n - 1 + AND sa_admins.server_id IS NULL +WHERE sa_admins.player_steamid != 'Console'; diff --git a/Database/Migrations/005_CreateUnbansTable.sql b/Database/Migrations/005_CreateUnbansTable.sql new file mode 100644 index 0000000..e005441 --- /dev/null +++ b/Database/Migrations/005_CreateUnbansTable.sql @@ -0,0 +1,29 @@ +CREATE TABLE IF NOT EXISTS `sa_unbans` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ban_id` int(11) NOT NULL, + `admin_id` int(11) NOT NULL DEFAULT 0, + `reason` varchar(255) NOT NULL DEFAULT 'Unknown', + `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE IF NOT EXISTS `sa_unmutes` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `mute_id` int(11) NOT NULL, + `admin_id` int(11) NOT NULL DEFAULT 0, + `reason` varchar(255) NOT NULL DEFAULT 'Unknown', + `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +INSERT INTO `sa_admins` (`id`, `player_name`, `player_steamid`, `flags`, `immunity`, `server_id`, `ends`, `created`) +VALUES (-1, 'Console', 'Console', '', '0', NULL, NULL, '0000-00-00 00:00:00'); + +UPDATE `sa_admins` SET `id` = 0 WHERE `id` = -1; + +ALTER TABLE `sa_bans` ADD `unban_id` INT NULL AFTER `server_id`; +ALTER TABLE `sa_mutes` ADD `unmute_id` INT NULL AFTER `server_id`; +ALTER TABLE `sa_bans` ADD FOREIGN KEY (`unban_id`) REFERENCES `sa_unbans`(`id`) ON DELETE CASCADE; +ALTER TABLE `sa_mutes` ADD FOREIGN KEY (`unmute_id`) REFERENCES `sa_unmutes`(`id`) ON DELETE CASCADE; +ALTER TABLE `sa_unbans` ADD FOREIGN KEY (`admin_id`) REFERENCES `sa_admins`(`id`) ON DELETE CASCADE; +ALTER TABLE `sa_unmutes` ADD FOREIGN KEY (`admin_id`) REFERENCES `sa_admins`(`id`) ON DELETE CASCADE; diff --git a/Events.cs b/Events.cs index e22b946..e100d6e 100644 --- a/Events.cs +++ b/Events.cs @@ -32,70 +32,83 @@ public partial class CS2_SimpleAdmin CCSPlayerController? player = @event.Userid; #if DEBUG - Logger.LogCritical("[OnClientDisconnect] Before"); + Logger.LogCritical("[OnClientDisconnect] Before"); #endif - if (player is null || !player.IsValid || string.IsNullOrEmpty(player.IpAddress) || player.IsBot || player.IsHLTV) return HookResult.Continue; - if (!loadedPlayers.Contains(player.Slot)) return HookResult.Continue; + if (player == null || !player.IsValid || string.IsNullOrEmpty(player.IpAddress) || player.IsBot || player.IsHLTV) + { + return HookResult.Continue; + } + + if (!loadedPlayers.Contains(player.Slot)) + { + return HookResult.Continue; + } #if DEBUG - Logger.LogCritical("[OnClientDisconnect] After Check"); + Logger.LogCritical("[OnClientDisconnect] After Check"); #endif - - PlayerPenaltyManager playerPenaltyManager = new(); - playerPenaltyManager.RemoveAllPenalties(player.Slot); - - if (TagsDetected) - Server.ExecuteCommand($"css_tag_unmute {player.SteamID}"); - - if (silentPlayers.Contains(player.Slot)) - RemoveFromConcurrentBag(silentPlayers, player.Slot); - if (godPlayers.Contains(player.Slot)) - RemoveFromConcurrentBag(godPlayers, player.Slot); - - loadedPlayers.Remove(player.Slot); - - SteamID? authorizedSteamID = player.AuthorizedSteamID; - - if (authorizedSteamID == null) return HookResult.Continue; - - Task.Run(() => + try { - if (AdminSQLManager._adminCache.TryGetValue(authorizedSteamID, out DateTime? expirationTime) + PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + PlayerPenaltyManager.RemoveAllPenalties(player.Slot); + + if (TagsDetected) + { + Server.ExecuteCommand($"css_tag_unmute {player.SteamID}"); + } + + if (silentPlayers.Contains(player.Slot)) + { + RemoveFromConcurrentBag(silentPlayers, player.Slot); + } + + if (godPlayers.Contains(player.Slot)) + { + RemoveFromConcurrentBag(godPlayers, player.Slot); + } + + SteamID? authorizedSteamID = player.AuthorizedSteamID; + if (authorizedSteamID != null && AdminSQLManager._adminCache.TryGetValue(authorizedSteamID, out DateTime? expirationTime) && expirationTime <= DateTime.Now) { AdminManager.ClearPlayerPermissions(authorizedSteamID); AdminManager.RemovePlayerAdminData(authorizedSteamID); } - }); - return HookResult.Continue; + loadedPlayers.Remove(player.Slot); + + return HookResult.Continue; + } + catch (Exception ex) + { + Logger.LogError($"An error occurred in OnClientDisconnect: {ex.Message}"); + return HookResult.Continue; + } } + [GameEventHandler] public HookResult OnPlayerFullConnect(EventPlayerConnectFull @event, GameEventInfo info) { CCSPlayerController? player = @event.Userid; -#if DEBUG - Logger.LogCritical($"[OnPlayerConnect] Before check {player.PlayerName} : {player.IpAddress}"); -#endif - if (player is null - || string.IsNullOrEmpty(player.IpAddress) || player.IpAddress.Contains("127.0.0.1") - || player.IsBot || player.IsHLTV || !player.UserId.HasValue) return HookResult.Continue; -#if DEBUG - Logger.LogCritical("[OnPlayerConnect] After Check"); -#endif + if (player == null || string.IsNullOrEmpty(player.IpAddress) || player.IpAddress.Contains("127.0.0.1") + || player.IsBot || player.IsHLTV || !player.UserId.HasValue) + return HookResult.Continue; + string ipAddress = player.IpAddress.Split(":")[0]; + // Check if the player's IP or SteamID is in the bannedPlayers list if (bannedPlayers.Contains(ipAddress) || bannedPlayers.Contains(player.SteamID.ToString())) { - if (!player.UserId.HasValue) return HookResult.Continue; - Helper.KickPlayer(player.UserId.Value, "Banned"); + // Kick the player if banned + if (player.UserId.HasValue) + Helper.KickPlayer(player.UserId.Value, "Banned"); + return HookResult.Continue; } - if (_database == null || !player.UserId.HasValue || player.UserId == null) - return HookResult.Continue; + if (_database == null) return HookResult.Continue; PlayerInfo playerInfo = new PlayerInfo { @@ -107,77 +120,92 @@ public partial class CS2_SimpleAdmin IpAddress = ipAddress }; - BanManager _banManager = new(_database, Config); - MuteManager _muteManager = new(_database); - PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); - + // Perform asynchronous database operations within a single method Task.Run(async () => { - if (await _banManager.IsPlayerBanned(playerInfo)) + // Initialize managers + BanManager _banManager = new(_database, Config); + MuteManager _muteManager = new(_database); + PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); + + try { - if (playerInfo.IpAddress != null && !bannedPlayers.Contains(playerInfo.IpAddress)) - bannedPlayers.Add(playerInfo.IpAddress); - - if (playerInfo.SteamId != null && !bannedPlayers.Contains(playerInfo.SteamId)) - bannedPlayers.Add(playerInfo.SteamId); - - Server.NextFrame(() => + // Check if the player is banned + bool isBanned = await _banManager.IsPlayerBanned(playerInfo); + if (isBanned) { - var victim = Utilities.GetPlayerFromUserid(playerInfo.UserId); - if (victim != null && victim.UserId.HasValue) + // Add player's IP and SteamID to bannedPlayers list if not already present + if (playerInfo.IpAddress != null && !bannedPlayers.Contains(playerInfo.IpAddress)) + bannedPlayers.Add(playerInfo.IpAddress); + + if (playerInfo.SteamId != null && !bannedPlayers.Contains(playerInfo.SteamId)) + bannedPlayers.Add(playerInfo.SteamId); + + // Kick the player if banned + Server.NextFrame(() => { - Helper.KickPlayer(victim.UserId.Value, "Banned"); - } - }); + var victim = Utilities.GetPlayerFromUserid(playerInfo.UserId); + if (victim != null && victim.UserId.HasValue) + { + Helper.KickPlayer(victim.UserId.Value, "Banned"); + } + }); - return; - } + return; + } - List activeMutes = await _muteManager.IsPlayerMuted(playerInfo.SteamId); - - if (activeMutes.Count > 0) - { - foreach (dynamic mute in activeMutes) + // Check if the player is muted + List activeMutes = await _muteManager.IsPlayerMuted(playerInfo.SteamId); + if (activeMutes.Count > 0) { - string muteType = mute.type; - DateTime ends = mute.ends; - int duration = mute.duration; + foreach (dynamic mute in activeMutes) + { + string muteType = mute.type; + DateTime ends = mute.ends; + int duration = mute.duration; - if (muteType == "GAG") - { - playerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Gag, ends, duration); - Server.NextFrame(() => + // Apply mute penalty based on mute type + if (muteType == "GAG") { - if (TagsDetected) + PlayerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Gag, ends, duration); + Server.NextFrame(() => { - Server.ExecuteCommand($"css_tag_mute {playerInfo.SteamId}"); - } - }); - } - else if (muteType == "MUTE") - { - playerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Mute, ends, duration); - Server.NextFrame(() => + if (TagsDetected) + { + Server.ExecuteCommand($"css_tag_mute {playerInfo.SteamId}"); + } + }); + } + else if (muteType == "MUTE") { - player.VoiceFlags = VoiceFlags.Muted; - }); - } - else - { - playerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Silence, ends, duration); - Server.NextFrame(() => - { - player.VoiceFlags = VoiceFlags.Muted; - if (TagsDetected) + PlayerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Mute, ends, duration); + Server.NextFrame(() => { - Server.ExecuteCommand($"css_tag_mute {playerInfo.SteamId}"); - } - }); + player.VoiceFlags = VoiceFlags.Muted; + }); + } + else + { + PlayerPenaltyManager.AddPenalty(playerInfo.Slot, PenaltyType.Silence, ends, duration); + Server.NextFrame(() => + { + player.VoiceFlags = VoiceFlags.Muted; + if (TagsDetected) + { + Server.ExecuteCommand($"css_tag_mute {playerInfo.SteamId}"); + } + }); + } } } } + catch (Exception ex) + { + Logger.LogError($"Error processing player connection: {ex}"); + } }); + // Add player to loadedPlayers if (!loadedPlayers.Contains(player.Slot)) loadedPlayers.Add(player.Slot); @@ -197,11 +225,16 @@ public partial class CS2_SimpleAdmin public HookResult OnCommandSay(CCSPlayerController? player, CommandInfo info) { - if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || info.GetArg(1).Length == 0) return HookResult.Continue; + if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || info.GetArg(1).StartsWith("/") + || info.GetArg(1).StartsWith("!") && info.GetArg(1).Length >= 12) + return HookResult.Continue; + + if (info.GetArg(1).Length == 0) + return HookResult.Handled; PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); - if (playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) || playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) + if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) || PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) return HookResult.Handled; return HookResult.Continue; @@ -209,11 +242,16 @@ public partial class CS2_SimpleAdmin public HookResult OnCommandTeamSay(CCSPlayerController? player, CommandInfo info) { - if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || info.GetArg(1).Length == 0) return HookResult.Continue; + if (player is null || !player.IsValid || player.IsBot || player.IsHLTV || info.GetArg(1).StartsWith("/") + || info.GetArg(1).StartsWith("!") && info.GetArg(1).Length >= 12) + return HookResult.Continue; + + if (info.GetArg(1).Length == 0) + return HookResult.Handled; PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); - if (playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) || playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) + if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) || PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) return HookResult.Handled; if (info.GetArg(1).StartsWith("@")) @@ -256,69 +294,86 @@ public partial class CS2_SimpleAdmin silentPlayers.Clear(); PlayerPenaltyManager playerPenaltyManager = new PlayerPenaltyManager(); - playerPenaltyManager.RemoveAllPenalties(); + PlayerPenaltyManager.RemoveAllPenalties(); _database = new(dbConnectionString); if (_database == null) return; - AddTimer(61.0f, async () => + AddTimer(61.0f, () => { #if DEBUG Logger.LogCritical("[OnMapStart] Expired check"); #endif - AdminSQLManager _adminManager = new(_database); - BanManager _banManager = new(_database, Config); - MuteManager _muteManager = new(_database); - await _banManager.ExpireOldBans(); - await _muteManager.ExpireOldMutes(); - await _adminManager.DeleteOldAdmins(); - bannedPlayers.Clear(); + List players = Helper.GetValidPlayers(); + List<(string? IpAddress, ulong SteamID, int? UserId)> onlinePlayers = players + .Where(player => player.IpAddress != null && player.SteamID.ToString().Length == 17) + .Select(player => (player.IpAddress, player.SteamID, player.UserId)) + .ToList(); - Server.NextFrame(() => + Task.Run(async () => { + AdminSQLManager _adminManager = new(_database); + BanManager _banManager = new(_database, Config); + MuteManager _muteManager = new(_database); + + await _banManager.ExpireOldBans(); + await _muteManager.ExpireOldMutes(); + await _adminManager.DeleteOldAdmins(); + try { - foreach (CCSPlayerController player in Helper.GetValidPlayers()) + await _banManager.CheckOnlinePlayers(onlinePlayers); + } + catch { } + + bannedPlayers.Clear(); + + Server.NextFrame(() => + { + try { - if (playerPenaltyManager.IsSlotInPenalties(player.Slot)) + foreach (CCSPlayerController player in players) { - if (!playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && !playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) - player.VoiceFlags = VoiceFlags.Normal; - - if (!playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) && !playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) + if (PlayerPenaltyManager.IsSlotInPenalties(player.Slot)) { - if (TagsDetected) - Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); - } + if (!PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) + player.VoiceFlags = VoiceFlags.Normal; - if ( - !playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence) && - !playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && - !playerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) - ) - { - player.VoiceFlags = VoiceFlags.Normal; + if (!PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) && !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence)) + { + if (TagsDetected) + Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); + } - if (TagsDetected) - Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); + if ( + !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence) && + !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Mute) && + !PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) + ) + { + player.VoiceFlags = VoiceFlags.Normal; + + if (TagsDetected) + Server.ExecuteCommand($"css_tag_unmute {player!.SteamID}"); + } } } - } - } - catch (Exception) { } - }); - playerPenaltyManager.RemoveExpiredPenalties(); + PlayerPenaltyManager.RemoveExpiredPenalties(); + } + catch (Exception) { } + }); + }); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.REPEAT | CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - AddTimer(2.0f, async () => + AddTimer(2.0f, () => { string? address = $"{ConVar.Find("ip")!.StringValue}:{ConVar.Find("hostport")!.GetPrimitiveValue()}"; string? hostname = ConVar.Find("hostname")!.StringValue; - await Task.Run(async () => + Task.Run(async () => { AdminSQLManager _adminManager = new(_database); try @@ -337,7 +392,7 @@ public partial class CS2_SimpleAdmin else { await connection.ExecuteAsync( - "UPDATE `sa_servers` SET hostname = @hostname WHERE address = @address", + "UPDATE `sa_servers` SET `hostname` = @hostname, `id` = `id` WHERE `address` = @address", new { address, hostname }); } @@ -352,19 +407,24 @@ public partial class CS2_SimpleAdmin _logger?.LogCritical("Unable to create or get server_id" + ex.Message); } + if (Config.EnableMetrics) + { + string queryString = $"?address={address}&hostname={hostname}"; + using HttpClient client = new(); + + try + { + HttpResponseMessage response = await client.GetAsync($"https://api.daffyy.love/index.php{queryString}"); + } + catch (HttpRequestException ex) + { + Logger.LogWarning($"Unable to make metrics call: {ex.Message}"); + } + } + await _adminManager.GiveAllFlags(); }); }, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - - AddTimer(3.0f, () => - { - ConVar? botQuota = ConVar.Find("bot_quota"); - - if (botQuota != null && botQuota.GetPrimitiveValue() > 0) - { - Logger.LogWarning("Due to bugs with bots (game bug), consider disabling bots by setting `bot_quota 0` in the gamemode config if your server crashes after a map change."); - } - }); } [GameEventHandler] diff --git a/Extensions/PlayerExtensions.cs b/Extensions/PlayerExtensions.cs index eb67428..0c2f6c5 100644 --- a/Extensions/PlayerExtensions.cs +++ b/Extensions/PlayerExtensions.cs @@ -121,7 +121,7 @@ public static class PlayerExtensions if (CS2_SimpleAdmin.Instance == null) return; - newName = CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; + newName = newName ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; SchemaString playerName = new SchemaString(controller, "m_iszPlayerName"); playerName.Set(newName + " "); diff --git a/Helper.cs b/Helper.cs index 32d9962..51e9e56 100644 --- a/Helper.cs +++ b/Helper.cs @@ -7,6 +7,8 @@ using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Menu; using Discord; +using Discord.Webhook; +using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using System.Reflection; using System.Runtime.CompilerServices; @@ -45,13 +47,13 @@ namespace CS2_SimpleAdmin public static List GetValidPlayers() { - return Utilities.GetPlayers().FindAll(p => p != null && p.IsValid && p.SteamID.ToString().Length == 17 && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsBot && !p.IsHLTV); + return Utilities.GetPlayers().FindAll(p => p != null && p.IsValid && p.SteamID.ToString().Length == 17 && !string.IsNullOrEmpty(p.IpAddress) && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsBot && !p.IsHLTV); } public static List GetValidPlayersWithBots() { return Utilities.GetPlayers().FindAll(p => - p != null && p.IsValid && p.SteamID.ToString().Length == 17 && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsBot && !p.IsHLTV || + p != null && p.IsValid && p.SteamID.ToString().Length == 17 && !string.IsNullOrEmpty(p.IpAddress) && p.Connected == PlayerConnectedState.PlayerConnected && !p.IsBot && !p.IsHLTV || p != null && p.IsValid && p.Connected == PlayerConnectedState.PlayerConnected && p.IsBot && !p.IsHLTV ); } @@ -196,6 +198,88 @@ namespace CS2_SimpleAdmin return new List { embed.Build() }; } + public static void SendDiscordLogMessage(CCSPlayerController? caller, CommandInfo command, DiscordWebhookClient? discordWebhookClientLog, IStringLocalizer? localizer) + { + if (discordWebhookClientLog != null && localizer != null) + { + string communityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; + string callerName = caller != null ? caller.PlayerName : "Console"; + discordWebhookClientLog.SendMessageAsync(Helper.GenerateMessageDiscord(localizer["sa_discord_log_command", $"[{callerName}]({communityUrl})", command.GetCommandString])); + } + } + + public enum PenaltyType + { + Ban, + Mute, + Gag, + Silence, + } + + public static string ConvertMinutesToTime(int minutes) + { + TimeSpan time = TimeSpan.FromMinutes(minutes); + + return time.Days > 0 ? $"{time.Days}d {time.Hours}h {time.Minutes}m" : time.Hours > 0 ? $"{time.Hours}h {time.Minutes}m" : $"{time.Minutes}m"; + } + + public static void SendDiscordPenaltyMessage(CCSPlayerController? caller, CCSPlayerController? target, string reason, int duration, PenaltyType penalty, DiscordWebhookClient? discordWebhookClientPenalty, IStringLocalizer? localizer) + { + if (discordWebhookClientPenalty != null && localizer != null) + { + string callercommunityUrl = caller != null ? "<" + new SteamID(caller.SteamID).ToCommunityUrl().ToString() + ">" : ""; + string targetcommunityUrl = target != null ? "<" + new SteamID(target.SteamID).ToCommunityUrl().ToString() + ">" : ""; + string callerName = caller != null ? caller.PlayerName : "Console"; + string targetName = target != null ? target.PlayerName : localizer?["sa_unknown"] ?? "Unknown"; + string targetSteamId = target != null ? new SteamID(target.SteamID).SteamId2.ToString() : localizer?["sa_unknown"] ?? "Unknown"; + + string time = duration != 0 ? ConvertMinutesToTime(duration) : localizer?["sa_permanent"] ?? "Permanent"; + + string[] fieldNames = [ + localizer?["sa_player"] ?? "Player:", + localizer?["sa_steamid"] ?? "SteamID:", + localizer?["sa_duration"] ?? "Duration:", + localizer?["sa_reason"] ?? "Reason:", + localizer?["sa_admin"] ?? "Admin:"]; + string[] fieldValues = [$"[{targetName}]({targetcommunityUrl})", targetSteamId, time, reason, $"[{callerName}]({callercommunityUrl})"]; + bool[] inlineFlags = [true, true, true, false, false]; + + string? hostname = ConVar.Find("hostname")!.StringValue ?? localizer?["sa_unknown"] ?? "Unknown"; + + var embed = new EmbedBuilder + { + Title = penalty switch + { + PenaltyType.Ban => localizer?["sa_discord_penalty_ban"] ?? "Ban registrered", + PenaltyType.Mute => localizer?["sa_discord_penalty_mute"] ?? "Mute registrered", + PenaltyType.Gag => localizer?["sa_discord_penalty_gag"] ?? "Gag registrered", + PenaltyType.Silence => localizer?["sa_discord_penalty_silence"] ?? "Silence registrered", + _ => localizer?["sa_discord_penalty_unknown"] ?? "Unknown registrered", + }, + + Color = penalty switch + { + PenaltyType.Ban => Color.Red, + PenaltyType.Mute => Color.Blue, + PenaltyType.Gag => Color.Gold, + PenaltyType.Silence => Color.Green, + _ => Color.Default, + }, + + Description = $"{hostname}", + + Timestamp = DateTimeOffset.UtcNow + }; + + for (int i = 0; i < fieldNames.Length; i++) + { + embed.AddField(fieldNames[i], fieldValues[i], inlineFlags[i]); + } + + discordWebhookClientPenalty.SendMessageAsync(embeds: [embed.Build()]); + } + } + public static string GenerateMessageDiscord(string message) { string? hostname = ConVar.Find("hostname")!.StringValue ?? CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown"; @@ -223,12 +307,12 @@ namespace CS2_SimpleAdmin var updatedJsonContent = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true, Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); File.WriteAllText(CfgPath, updatedJsonContent); } - + public static void TryLogCommandOnDiscord(CCSPlayerController? caller, string commandString) { if (CS2_SimpleAdmin._discordWebhookClientLog == null || CS2_SimpleAdmin._localizer == null) return; - + if (caller != null && caller.IsValid == false) caller = null; diff --git a/Managers/AdminSQLManager.cs b/Managers/AdminSQLManager.cs index 871f54f..b26ee30 100644 --- a/Managers/AdminSQLManager.cs +++ b/Managers/AdminSQLManager.cs @@ -1,30 +1,25 @@ using CounterStrikeSharp.API.Modules.Entities; using Dapper; using Microsoft.Extensions.Logging; +using MySqlConnector; using System.Collections.Concurrent; namespace CS2_SimpleAdmin; -public class AdminSQLManager +public class AdminSQLManager(Database database) { - private readonly Database _database; + private readonly Database _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) - { - _database = database; - } + public static readonly ConcurrentDictionary _adminCache = new(); + /* public async Task, int)>> GetAdminFlags(string steamId) { DateTime now = DateTime.UtcNow.ToLocalTime(); - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection 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(); @@ -34,7 +29,7 @@ public class AdminSQLManager return new List<(List, int)>(); } - List<(List, int)> filteredFlagsWithImmunity = new List<(List, int)>(); + List<(List, int)> filteredFlagsWithImmunity = []; foreach (dynamic flags in activeFlags) { @@ -60,6 +55,7 @@ public class AdminSQLManager return filteredFlagsWithImmunity; } + */ public async Task, int, DateTime?)>> GetAllPlayersFlags() { @@ -67,63 +63,76 @@ public class AdminSQLManager try { - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + string sql = @" + SELECT sa_admins.player_steamid, sa_admins_flags.flag, sa_admins.immunity, sa_admins.ends + FROM sa_admins_flags + JOIN sa_admins ON sa_admins_flags.admin_id = sa_admins.id + WHERE (sa_admins.ends IS NULL OR sa_admins.ends > @CurrentTime) + AND (sa_admins.server_id IS NULL OR sa_admins.server_id = @serverid) + ORDER BY sa_admins.player_steamid"; - 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<(string, List, int, DateTime?)>(); + return []; } - List<(string, List, int, DateTime?)> filteredFlagsWithImmunity = new List<(string, List, int, DateTime?)>(); + List<(string, List, int, DateTime?)> filteredFlagsWithImmunity = []; + string currentSteamId = string.Empty; + List currentFlags = []; + int immunityValue = 0; + DateTime? ends = null; - foreach (dynamic flags in activeFlags) + foreach (dynamic flagInfo in activeFlags) { - if (flags is not IDictionary flagsDict) + if (flagInfo is not IDictionary flagInfoDict) { 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)) + if (!flagInfoDict.TryGetValue("player_steamid", out var steamIdObj) || + !flagInfoDict.TryGetValue("flag", out var flagObj) || + !flagInfoDict.TryGetValue("immunity", out var immunityValueObj) || + !flagInfoDict.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 (steamIdObj is not string steamId || + flagObj is not string flag || + !int.TryParse(immunityValueObj.ToString(), out immunityValue)) { - if (!DateTime.TryParse(endsObj.ToString(), out var parsedEnds)) - { - //Console.WriteLine("Failed to parse 'ends' value."); - continue; - } + continue; + } + if (endsObj != null && DateTime.TryParse(endsObj.ToString(), out var parsedEnds)) + { ends = parsedEnds; } - if (!(steamIdObj is string steamId) || - !(flagsValueObj is string flagsValue) || - !int.TryParse(immunityValueObj.ToString(), out var immunityValue)) + if (currentSteamId != steamId && !string.IsNullOrEmpty(currentSteamId)) { - //Console.WriteLine("Failed to parse one or more values."); - continue; + filteredFlagsWithImmunity.Add((currentSteamId, currentFlags, immunityValue, ends)); + currentFlags = []; } - filteredFlagsWithImmunity.Add((steamId, flagsValue.Split(',').ToList(), immunityValue, ends)); + currentSteamId = steamId; + currentFlags.Add(flag); + } + + if (!string.IsNullOrEmpty(currentSteamId)) + { + filteredFlagsWithImmunity.Add((currentSteamId, currentFlags, immunityValue, ends)); } return filteredFlagsWithImmunity; } catch (Exception) { - return new List<(string, List, int, DateTime?)>(); + return []; } } @@ -160,67 +169,87 @@ public class AdminSQLManager //_adminCache.TryRemove(playerSteamId, out _); - await using var connection = await _database.GetConnectionAsync(); - - string sql = ""; - - if (globalDelete) + try { - sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID"; - } - else - { - sql = "DELETE FROM sa_admins WHERE player_steamid = @PlayerSteamID AND server_id = @ServerId"; - } + await using MySqlConnection connection = await _database.GetConnectionAsync(); + string sql = ""; - await connection.ExecuteAsync(sql, new { PlayerSteamID = playerSteamId, ServerId = CS2_SimpleAdmin.ServerId }); + 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, CS2_SimpleAdmin.ServerId }); + } + catch { }; } - public async Task AddAdminBySteamId(string playerSteamId, string playerName, string flags, int immunity = 0, int time = 0, bool globalAdmin = false) + public async Task AddAdminBySteamId(string playerSteamId, string playerName, List flagsList, int immunity = 0, int time = 0, bool globalAdmin = false) { - if (string.IsNullOrEmpty(playerSteamId)) return; - - flags = flags.Replace(" ", ""); + if (string.IsNullOrEmpty(playerSteamId) || flagsList == null || flagsList.Count == 0) return; DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime? futureTime; + if (time != 0) futureTime = now.ToLocalTime().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 + try { - playerSteamId, - playerName, - flags, - immunity, - ends = futureTime, - created = now, - serverid = serverId - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + + // Insert admin into sa_admins table + var insertAdminSql = "INSERT INTO `sa_admins` (`player_steamid`, `player_name`, `immunity`, `ends`, `created`, `server_id`) " + + "VALUES (@playerSteamid, @playerName, @immunity, @ends, @created, @serverid); SELECT LAST_INSERT_ID();"; + + int adminId = await connection.ExecuteScalarAsync(insertAdminSql, new + { + playerSteamId, + playerName, + immunity, + ends = futureTime, + created = now, + serverid = globalAdmin ? null : CS2_SimpleAdmin.ServerId + }); + + // Insert flags into sa_admins_flags table + foreach (var flag in flagsList) + { + Console.WriteLine(flag); + var insertFlagsSql = "INSERT INTO `sa_admins_flags` (`admin_id`, `flag`) " + + "VALUES (@adminId, @flag)"; + + await connection.ExecuteAsync(insertFlagsSql, new + { + adminId, + flag + }); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } } public async Task DeleteOldAdmins() { try { - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection 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.ToLocalTime() }); } catch (Exception) { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired admins"); + CS2_SimpleAdmin._logger?.LogCritical("Unable to remove expired admins"); } } } \ No newline at end of file diff --git a/Managers/BanManager.cs b/Managers/BanManager.cs index 208aed8..723c393 100644 --- a/Managers/BanManager.cs +++ b/Managers/BanManager.cs @@ -1,42 +1,42 @@ -using Dapper; +using CounterStrikeSharp.API; +using Dapper; using Microsoft.Extensions.Logging; +using MySqlConnector; namespace CS2_SimpleAdmin; -internal class BanManager +internal class BanManager(Database database, CS2_SimpleAdminConfig config) { - private readonly Database _database; - private readonly CS2_SimpleAdminConfig _config; - - public BanManager(Database database, CS2_SimpleAdminConfig config) - { - _database = database; - _config = config; - } + private readonly Database _database = database; + private readonly CS2_SimpleAdminConfig _config = config; public async Task BanPlayer(PlayerInfo player, PlayerInfo issuer, string reason, int time = 0) { DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - 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 + try { - 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 - }); + await using MySqlConnection 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 ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task AddBanBySteamid(string playerSteamId, PlayerInfo issuer, string reason, int time = 0) @@ -46,22 +46,26 @@ internal class BanManager DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - 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 + try { - 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 - }); + await using MySqlConnection 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 ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task AddBanByIp(string playerIp, PlayerInfo issuer, string reason, int time = 0) @@ -71,27 +75,31 @@ internal class BanManager DateTime now = DateTime.UtcNow.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); - 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 + try { - 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 - }); + await using MySqlConnection 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 ?? "Console", + adminName = issuer.Name ?? "Console", + banReason = reason, + duration = time, + ends = futureTime, + created = now, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { } } public async Task IsPlayerBanned(PlayerInfo player) { - if (player.SteamId == null && player.IpAddress == null) + if (player.SteamId == null || player.IpAddress == null) { return false; } @@ -120,7 +128,7 @@ internal class BanManager AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime);"; - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection connection = await _database.GetConnectionAsync(); var parameters = new { @@ -142,34 +150,112 @@ internal class BanManager 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)) + try { - 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 }); - } + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP)"; + int banCount; - return banCount; + await using MySqlConnection 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; + } + catch { } + + return 0; } - public async Task UnbanPlayer(string playerPattern) + public async Task UnbanPlayer(string playerPattern, string adminSteamId, string reason) { if (playerPattern == null || playerPattern.Length <= 1) { return; } + try + { + await using MySqlConnection connection = await _database.GetConnectionAsync(); - await using var connection = await _database.GetConnectionAsync(); + string sqlRetrieveBans = "SELECT id FROM sa_bans WHERE (player_steamid = @pattern OR player_name = @pattern OR player_ip = @pattern) AND status = 'ACTIVE'"; + var bans = await connection.QueryAsync(sqlRetrieveBans, new { pattern = playerPattern }); - 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 }); + if (!bans.Any()) + return; + + string sqlAdmin = "SELECT id FROM sa_admins WHERE player_steamid = @adminSteamId"; + string sqlInsertUnban = "INSERT INTO sa_unbans (ban_id, admin_id, reason) VALUES (@banId, @adminId, @reason); SELECT LAST_INSERT_ID();"; + + int? sqlAdminId = await connection.ExecuteScalarAsync(sqlAdmin, new { adminSteamId }); + int adminId = sqlAdminId ?? 0; + + foreach (var ban in bans) + { + int banId = ban.id; + int? unbanId; + + // Insert into sa_unbans + if (reason != null) + { + unbanId = await connection.ExecuteScalarAsync(sqlInsertUnban, new { banId, adminId, reason }); + } + else + { + sqlInsertUnban = "INSERT INTO sa_unbans (ban_id, admin_id) VALUES (@banId, @adminId); SELECT LAST_INSERT_ID();"; + unbanId = await connection.ExecuteScalarAsync(sqlInsertUnban, new { banId, adminId }); + } + + // Update sa_bans to set unban_id + string sqlUpdateBan = "UPDATE sa_bans SET status = 'UNBANNED', unban_id = @unbanId WHERE id = @banId"; + await connection.ExecuteAsync(sqlUpdateBan, new { unbanId, banId }); + } + + /* + 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 }); + */ + + } + catch { } + } + + public async Task CheckOnlinePlayers(List<(string? IpAddress, ulong SteamID, int? UserId)> players) + { + try + { + await using MySqlConnection connection = await _database.GetConnectionAsync(); + string sql = "SELECT COUNT(*) FROM sa_bans WHERE (player_steamid = @PlayerSteamID OR player_ip = @PlayerIP) AND status = 'ACTIVE'"; + + foreach (var (IpAddress, SteamID, UserId) in players) + { + if (!UserId.HasValue) continue; + + int banCount = 0; + if (!string.IsNullOrEmpty(IpAddress)) + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = SteamID, PlayerIP = IpAddress }); + } + else + { + banCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = SteamID, PlayerIP = DBNull.Value }); + } + + if (banCount > 0) + { + Server.NextFrame(() => + { + Helper.KickPlayer(UserId.Value, "Banned"); + }); + } + } + } + catch { } } public async Task ExpireOldBans() @@ -178,11 +264,11 @@ internal class BanManager { DateTime currentTime = DateTime.UtcNow.ToLocalTime(); - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection connection = await _database.GetConnectionAsync(); /* string sql = ""; - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection connection = await _database.GetConnectionAsync(); sql = "UPDATE sa_bans SET status = 'EXPIRED' WHERE status = 'ACTIVE' AND `duration` > 0 AND ends <= @CurrentTime"; await connection.ExecuteAsync(sql, new { CurrentTime = DateTime.UtcNow.ToLocalTime() }); diff --git a/Managers/MuteManager.cs b/Managers/MuteManager.cs index da693ea..d9d550d 100644 --- a/Managers/MuteManager.cs +++ b/Managers/MuteManager.cs @@ -1,22 +1,17 @@ using Dapper; using Microsoft.Extensions.Logging; +using MySqlConnector; namespace CS2_SimpleAdmin; -internal class MuteManager +internal class MuteManager(Database database) { - private readonly Database _database; - - public MuteManager(Database database) - { - _database = database; - } + private readonly Database _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.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); @@ -27,29 +22,33 @@ internal class MuteManager 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 + try { - 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 - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + 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, @muteReason, @duration, @ends, @created, @type, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = player.SteamId, + playerName = player.Name, + adminSteamid = issuer.SteamId ?? "Console", + adminName = issuer.SteamId == null ? "Console" : issuer.Name, + muteReason = reason, + duration = time, + ends = futureTime, + created = now, + type = muteType, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { }; } 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.ToLocalTime(); DateTime futureTime = now.AddMinutes(time).ToLocalTime(); @@ -60,28 +59,33 @@ internal class MuteManager 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 + try { - 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 - }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); + var sql = "INSERT INTO `sa_mutes` (`player_steamid`, `admin_steamid`, `admin_name`, `reason`, `duration`, `ends`, `created`, `type`, `server_id`) " + + "VALUES (@playerSteamid, @adminSteamid, @adminName, @muteReason, @duration, @ends, @created, @type, @serverid)"; + + await connection.ExecuteAsync(sql, new + { + playerSteamid = playerSteamId, + adminSteamid = issuer.SteamId ?? "Console", + adminName = issuer.Name ?? "Console", + muteReason = reason, + duration = time, + ends = futureTime, + created = now, + type = muteType, + serverid = CS2_SimpleAdmin.ServerId + }); + } + catch { }; } public async Task> IsPlayerMuted(string steamId) { if (string.IsNullOrEmpty(steamId)) { - return new List(); + return []; } #if DEBUG @@ -91,7 +95,7 @@ internal class MuteManager try { - await using var connection = await _database.GetConnectionAsync(); + await using MySqlConnection connection = await _database.GetConnectionAsync(); DateTime currentTime = DateTime.Now.ToLocalTime(); string sql = "SELECT * FROM sa_mutes WHERE player_steamid = @PlayerSteamID AND status = 'ACTIVE' AND (duration = 0 OR ends > @CurrentTime)"; @@ -101,64 +105,98 @@ internal class MuteManager } catch (Exception) { - return new List(); + return []; } } public async Task GetPlayerMutes(string steamId) { - await using var connection = await _database.GetConnectionAsync(); + try + { + await using MySqlConnection connection = await _database.GetConnectionAsync(); - int muteCount; - string sql = "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; + int muteCount; + string sql = "SELECT COUNT(*) FROM sa_mutes WHERE player_steamid = @PlayerSteamID"; - muteCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = steamId }); - - return muteCount; + muteCount = await connection.ExecuteScalarAsync(sql, new { PlayerSteamID = steamId }); + return muteCount; + } + catch (Exception) + { + return 0; + } } - public async Task UnmutePlayer(string playerPattern, int type = 0) + public async Task UnmutePlayer(string playerPattern, string adminSteamId, string reason, int type = 0) { if (playerPattern == null || playerPattern.Length <= 1) { return; } - await using var connection = await _database.GetConnectionAsync(); - - if (type == 2) + try { - 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 }); + await using MySqlConnection connection = await _database.GetConnectionAsync(); - return; + string muteType = "GAG"; + if (type == 1) + { + muteType = "MUTE"; + } + else if (type == 2) + muteType = "SILENCE"; + + string sqlRetrieveMutes = "SELECT id FROM sa_mutes WHERE (player_steamid = @pattern OR player_name = @pattern) AND type = @muteType AND status = 'ACTIVE'"; + var mutes = await connection.QueryAsync(sqlRetrieveMutes, new { pattern = playerPattern, muteType }); + + if (!mutes.Any()) + return; + + string sqlAdmin = "SELECT id FROM sa_admins WHERE player_steamid = @adminSteamId"; + string sqlInsertUnmute = "INSERT INTO sa_unmutes (mute_id, admin_id, reason) VALUES (@muteId, @adminId, @reason); SELECT LAST_INSERT_ID();"; + + int? sqlAdminId = await connection.ExecuteScalarAsync(sqlAdmin, new { adminSteamId }); + int adminId = sqlAdminId ?? 0; + + foreach (var mute in mutes) + { + int muteId = mute.id; + int? unmuteId; + + // Insert into sa_unmutes + if (reason != null) + { + unmuteId = await connection.ExecuteScalarAsync(sqlInsertUnmute, new { muteId, adminId, reason }); + } + else + { + sqlInsertUnmute = "INSERT INTO sa_unmutes (muteId, admin_id) VALUES (@muteId, @adminId); SELECT LAST_INSERT_ID();"; + unmuteId = await connection.ExecuteScalarAsync(sqlInsertUnmute, new { muteId, adminId }); + } + + // Update sa_mutes to set unmute_id + string sqlUpdateMute = "UPDATE sa_mutes SET status = 'UNMUTED', unmute_id = @unmuteId WHERE id = @muteId"; + await connection.ExecuteAsync(sqlUpdateMute, new { unmuteId, muteId }); + } } - - string muteType = "GAG"; - if (type == 1) + catch (Exception ex) { - muteType = "MUTE"; + Console.WriteLine(ex); } - 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(); + await using MySqlConnection 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.ToLocalTime() }); } catch (Exception) { - if (CS2_SimpleAdmin._logger != null) - CS2_SimpleAdmin._logger.LogCritical("Unable to remove expired mutes"); + CS2_SimpleAdmin._logger?.LogCritical("Unable to remove expired mutes"); } } } \ No newline at end of file diff --git a/Managers/PlayerPenaltyManager.cs b/Managers/PlayerPenaltyManager.cs index f50cba9..5a9efb8 100644 --- a/Managers/PlayerPenaltyManager.cs +++ b/Managers/PlayerPenaltyManager.cs @@ -15,22 +15,29 @@ public class PlayerPenaltyManager new ConcurrentDictionary>>(); // Add a penalty for a player - public void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationSeconds) + public static void AddPenalty(int slot, PenaltyType penaltyType, DateTime endDateTime, int durationSeconds) { - 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.AddOrUpdate(slot, + (_) => + { + var dict = new Dictionary> + { + [penaltyType] = [(endDateTime, durationSeconds)] + }; + return dict; + }, + (_, existingDict) => + { + if (!existingDict.ContainsKey(penaltyType)) + { + existingDict[penaltyType] = new List<(DateTime, int)>(); + } + existingDict[penaltyType].Add((endDateTime, durationSeconds)); + return existingDict; + }); } - public bool IsPenalized(int slot, PenaltyType penaltyType) + public static bool IsPenalized(int slot, PenaltyType penaltyType) { //Console.WriteLine($"Checking penalties for player with slot {slot} and penalty type {penaltyType}"); @@ -73,23 +80,23 @@ public class PlayerPenaltyManager } // 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) + public static 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) { return penaltiesList; } - return new List<(DateTime EndDateTime, int Duration)>(); + return []; } - public bool IsSlotInPenalties(int slot) + public static bool IsSlotInPenalties(int slot) { return penalties.ContainsKey(slot); } // Remove all penalties for a player slot - public void RemoveAllPenalties(int slot) + public static void RemoveAllPenalties(int slot) { if (penalties.ContainsKey(slot)) { @@ -98,13 +105,13 @@ public class PlayerPenaltyManager } // Remove all penalties - public void RemoveAllPenalties() + public static void RemoveAllPenalties() { penalties.Clear(); } // Remove all penalties of a selected type from a specific player - public void RemovePenaltiesByType(int slot, PenaltyType penaltyType) + public static void RemovePenaltiesByType(int slot, PenaltyType penaltyType) { if (penalties.TryGetValue(slot, out Dictionary>? penaltyDict) && penaltyDict.ContainsKey(penaltyType)) @@ -114,7 +121,7 @@ public class PlayerPenaltyManager } // Remove all expired penalties for all players and penalty types - public void RemoveExpiredPenalties() + public static void RemoveExpiredPenalties() { DateTime now = DateTime.UtcNow.ToLocalTime(); foreach (var kvp in penalties.ToList()) // Use ToList to avoid modification while iterating diff --git a/Menus/AdminMenu.cs b/Menus/AdminMenu.cs index c3754cb..4384a53 100644 --- a/Menus/AdminMenu.cs +++ b/Menus/AdminMenu.cs @@ -8,7 +8,7 @@ namespace CS2_SimpleAdmin.Menus { public static BaseMenu CreateMenu(string title) { - return CS2_SimpleAdmin.Instance.Config.UseChatMenu ? new ChatMenu(title) : new CenterHtmlMenu(title); + return CS2_SimpleAdmin.Instance.Config.UseChatMenu ? new ChatMenu(title) : new CenterHtmlMenu(title, CS2_SimpleAdmin.Instance); } public static void OpenMenu(CCSPlayerController player, BaseMenu menu) @@ -44,7 +44,7 @@ namespace CS2_SimpleAdmin.Menus new ChatMenuOptionData("Manage Server", () => ManageServerMenu.OpenMenu(admin)), new ChatMenuOptionData("Fun actions", () => FunActionsMenu.OpenMenu(admin)), }; - + List customCommands = CS2_SimpleAdmin.Instance.Config.CustomServerCommands; if (customCommands.Count > 0) { diff --git a/Menus/ManageAdminsMenu.cs b/Menus/ManageAdminsMenu.cs index ac4127f..0fb1fd0 100644 --- a/Menus/ManageAdminsMenu.cs +++ b/Menus/ManageAdminsMenu.cs @@ -69,7 +69,7 @@ namespace CS2_SimpleAdmin.Menus private static void AddAdmin(CCSPlayerController admin, CCSPlayerController player, string flag) { // TODO: Change default immunity? - CS2_SimpleAdmin.Instance.AddAdmin(admin, player.SteamID.ToString(), player.PlayerName, flag, 10); + CS2_SimpleAdmin.AddAdmin(admin, player.SteamID.ToString(), player.PlayerName, flag, 10); } private static void RemoveAdmin(CCSPlayerController admin, CCSPlayerController player) diff --git a/Menus/ManagePlayersMenu.cs b/Menus/ManagePlayersMenu.cs index 399080f..7825838 100644 --- a/Menus/ManagePlayersMenu.cs +++ b/Menus/ManagePlayersMenu.cs @@ -20,7 +20,7 @@ namespace CS2_SimpleAdmin.Menus } BaseMenu menu = AdminMenu.CreateMenu("Manage Players"); - List options = new(); + List options = []; // permissions bool hasSlay = AdminManager.PlayerHasPermissions(admin, "@css/slay"); @@ -71,15 +71,16 @@ namespace CS2_SimpleAdmin.Menus private static void SlapMenu(CCSPlayerController admin, CCSPlayerController player) { BaseMenu menu = AdminMenu.CreateMenu($"Slap: {player.PlayerName}"); - List options = new(); - - // options added in order - options.Add(new ChatMenuOptionData("0 hp", () => ApplySlapAndKeepMenu(admin, player, 0))); - options.Add(new ChatMenuOptionData("1 hp", () => ApplySlapAndKeepMenu(admin, player, 1))); - options.Add(new ChatMenuOptionData("5 hp", () => ApplySlapAndKeepMenu(admin, player, 5))); - options.Add(new ChatMenuOptionData("10 hp", () => ApplySlapAndKeepMenu(admin, player, 10))); - options.Add(new ChatMenuOptionData("50 hp", () => ApplySlapAndKeepMenu(admin, player, 50))); - options.Add(new ChatMenuOptionData("100 hp", () => ApplySlapAndKeepMenu(admin, player, 100))); + List options = + [ + // options added in order + new ChatMenuOptionData("0 hp", () => ApplySlapAndKeepMenu(admin, player, 0)), + new ChatMenuOptionData("1 hp", () => ApplySlapAndKeepMenu(admin, player, 1)), + new ChatMenuOptionData("5 hp", () => ApplySlapAndKeepMenu(admin, player, 5)), + new ChatMenuOptionData("10 hp", () => ApplySlapAndKeepMenu(admin, player, 10)), + new ChatMenuOptionData("50 hp", () => ApplySlapAndKeepMenu(admin, player, 50)), + new ChatMenuOptionData("100 hp", () => ApplySlapAndKeepMenu(admin, player, 100)), + ]; foreach (ChatMenuOptionData menuOptionData in options) { @@ -92,29 +93,37 @@ namespace CS2_SimpleAdmin.Menus private static void ApplySlapAndKeepMenu(CCSPlayerController admin, CCSPlayerController player, int damage) { - CS2_SimpleAdmin.Instance.Slap(admin, player, damage); - SlapMenu(admin, player); + if (player is not null && player.IsValid) + { + CS2_SimpleAdmin.Instance.Slap(admin, player, damage); + SlapMenu(admin, player); + } } private static void Slay(CCSPlayerController admin, CCSPlayerController player) { - CS2_SimpleAdmin.Instance.Slay(admin, player); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Slay(admin, player); } private static void KickMenu(CCSPlayerController admin, CCSPlayerController player) { BaseMenu menu = AdminMenu.CreateMenu($"Kick: {player.PlayerName}"); - List options = new() - { + List options = + [ "Voice Abuse", "Chat Abuse", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Kick(admin, player, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Kick(admin, player, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -122,24 +131,29 @@ namespace CS2_SimpleAdmin.Menus private static void Kick(CCSPlayerController admin, CCSPlayerController player, string reason) { - CS2_SimpleAdmin.Instance.Kick(admin, player, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Kick(admin, player, reason); } private static void BanMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { BaseMenu menu = AdminMenu.CreateMenu($"Ban: {player.PlayerName}"); - List options = new() - { + List options = + [ "Hacking", "Voice Abuse", "Chat Abuse", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Ban(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Ban(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -147,26 +161,31 @@ namespace CS2_SimpleAdmin.Menus private static void Ban(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason); } private static void GagMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Gag: {player.PlayerName}"); - List options = new() - { + List options = + [ "Advertising", "Spamming", "Spectator camera abuse", "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Gag(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Gag(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -174,15 +193,16 @@ namespace CS2_SimpleAdmin.Menus private static void Gag(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason); } private static void MuteMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Mute: {player.PlayerName}"); - List options = new() - { + List options = + [ "Shouting", "Playing music", "Advertising", @@ -191,11 +211,15 @@ namespace CS2_SimpleAdmin.Menus "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Mute(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Mute(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -203,15 +227,16 @@ namespace CS2_SimpleAdmin.Menus private static void Mute(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason); } private static void SilenceMenu(CCSPlayerController admin, CCSPlayerController player, int duration) { // TODO: Localize and make options in config? BaseMenu menu = AdminMenu.CreateMenu($"Silence: {player.PlayerName}"); - List options = new() - { + List options = + [ "Shouting", "Playing music", "Advertising", @@ -220,11 +245,15 @@ namespace CS2_SimpleAdmin.Menus "Hate", "Admin disrespect", "Other" - }; + ]; foreach (string option in options) { - menu.AddMenuOption(option, (_, _) => { Silence(admin, player, duration, option); }); + menu.AddMenuOption(option, (_, _) => + { + if (player is not null && player.IsValid) + Silence(admin, player, duration, option); + }); } AdminMenu.OpenMenu(admin, menu); @@ -232,18 +261,21 @@ namespace CS2_SimpleAdmin.Menus private static void Silence(CCSPlayerController admin, CCSPlayerController player, int duration, string reason) { - CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason); } private static void ForceTeamMenu(CCSPlayerController admin, CCSPlayerController player) { // TODO: Localize BaseMenu menu = AdminMenu.CreateMenu($"Force {player.PlayerName}'s Team"); - List options = new(); - options.Add(new ChatMenuOptionData("CT", () => ForceTeam(admin, player, "ct", CsTeam.CounterTerrorist))); - options.Add(new ChatMenuOptionData("T", () => ForceTeam(admin, player, "t", CsTeam.Terrorist))); - options.Add(new ChatMenuOptionData("Swap", () => ForceTeam(admin, player, "swap", CsTeam.Spectator))); - options.Add(new ChatMenuOptionData("Spectator", () => ForceTeam(admin, player, "spec", CsTeam.Spectator))); + List options = + [ + new ChatMenuOptionData("CT", () => ForceTeam(admin, player, "ct", CsTeam.CounterTerrorist)), + new ChatMenuOptionData("T", () => ForceTeam(admin, player, "t", CsTeam.Terrorist)), + new ChatMenuOptionData("Swap", () => ForceTeam(admin, player, "swap", CsTeam.Spectator)), + new ChatMenuOptionData("Spectator", () => ForceTeam(admin, player, "spec", CsTeam.Spectator)), + ]; foreach (ChatMenuOptionData menuOptionData in options) { @@ -256,7 +288,8 @@ namespace CS2_SimpleAdmin.Menus private static void ForceTeam(CCSPlayerController admin, CCSPlayerController player, string teamName, CsTeam teamNum) { - CS2_SimpleAdmin.Instance.ChangeTeam(admin, player, teamName, teamNum, true); + if (player is not null && player.IsValid) + CS2_SimpleAdmin.Instance.ChangeTeam(admin, player, teamName, teamNum, true); } } } \ No newline at end of file diff --git a/Menus/PlayersMenu.cs b/Menus/PlayersMenu.cs index 7d0525f..dd7989d 100644 --- a/Menus/PlayersMenu.cs +++ b/Menus/PlayersMenu.cs @@ -1,7 +1,7 @@ -using System.Web; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Menu; +using System.Web; namespace CS2_SimpleAdmin.Menus { @@ -32,9 +32,13 @@ namespace CS2_SimpleAdmin.Menus BaseMenu menu = AdminMenu.CreateMenu(menuName); IEnumerable players = Helper.GetValidPlayersWithBots(); + string playerName = string.Empty; + foreach (CCSPlayerController player in players) { - string optionName = HttpUtility.HtmlEncode(player.PlayerName); + playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName; + + string optionName = HttpUtility.HtmlEncode(playerName); if (enableFilter != null && enableFilter(player) == false) continue; diff --git a/README.md b/README.md index 4dc8bbd..ef83c9d 100644 --- a/README.md +++ b/README.md @@ -61,14 +61,18 @@ Manage your Counter-Strike 2 server by simple commands :) - team_chat @Message - Say message to all admins // @css/chat ``` -### Requirments -- [CounterStrikeSharp](https://github.com/roflmuffin/CounterStrikeSharp/) **tested on v168** +### Requirements +- [CounterStrikeSharp](https://github.com/roflmuffin/CounterStrikeSharp/) **tested on v201** - MySQL **tested on MySQL (MariaDB) Server version: 10.11.4-MariaDB-1~deb12u1 Debian 12** ### Configuration After first launch, u need to configure plugin in addons/counterstrikesharp/configs/plugins/CS2-SimpleAdmin/CS2-SimpleAdmin.json +### Metrics +From version 1.3.7a, CS2-SimpleAdmin now initiates metrics data collection. This includes gathering essential information such as the `server name`, `server address` and `country`. +You can disable metrics by set `EnableMetrics` to false in plugin configuration. + ### Colors ``` public static char Default = '\x01'; diff --git a/lang/ar.json b/lang/ar.json index 2564212..02e81ce 100644 --- a/lang/ar.json +++ b/lang/ar.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "مجهول", + "sa_player": "اللاعب", + "sa_steamid": "معرف البخار", + "sa_duration": "المدة", + "sa_reason": "السبب", + "sa_admin": "المشرف", + "sa_permanent": "دائم", + + "sa_discord_penalty_ban": "الحظر مسجل", + "sa_discord_penalty_mute": "الكتم مسجل", + "sa_discord_penalty_gag": "الصمت مسجل", + "sa_discord_penalty_silence": "الصمت مسجل", + "sa_discord_penalty_unknown": "غير معروف مسجل", + "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 dfb7116..a2d39ce 100644 --- a/lang/en.json +++ b/lang/en.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Unknown", + "sa_player": "Player", + "sa_steamid": "SteamID", + "sa_duration": "Duration", + "sa_reason": "Reason", + "sa_admin": "Admin", + "sa_permanent": "Permanent", + + "sa_discord_penalty_ban": "Ban registrered", + "sa_discord_penalty_mute": "Mute registrered", + "sa_discord_penalty_gag": "Gag registrered", + "sa_discord_penalty_silence": "Silence registrered", + "sa_discord_penalty_unknown": "Unknown registrered", + "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 4c8cc39..cd1c49c 100644 --- a/lang/es.json +++ b/lang/es.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Desconocido", + "sa_player": "Jugador", + "sa_steamid": "ID de Steam", + "sa_duration": "Duración", + "sa_reason": "Motivo", + "sa_admin": "Admin", + "sa_permanent": "Permanente", + + "sa_discord_penalty_ban": "Ban registrado", + "sa_discord_penalty_mute": "Silencio registrado", + "sa_discord_penalty_gag": "Mordaza registrada", + "sa_discord_penalty_silence": "Silencio registrado", + "sa_discord_penalty_unknown": "Registro desconocido", + "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} durante {lightred}{1}{default}!", diff --git a/lang/fa.json b/lang/fa.json index 5c200bc..1c057ba 100644 --- a/lang/fa.json +++ b/lang/fa.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "ناشناخته", + "sa_player": "بازیکن", + "sa_steamid": "شناسه استیم", + "sa_duration": "مدت زمان", + "sa_reason": "دلیل", + "sa_admin": "مدیر", + "sa_permanent": "دائمی", + + "sa_discord_penalty_ban": "بن انجام شده", + "sa_discord_penalty_mute": "سکوت انجام شده", + "sa_discord_penalty_gag": "بند زدن انجام شده", + "sa_discord_penalty_silence": "سکوت انجام شده", + "sa_discord_penalty_unknown": "ناشناخته انجام شده", + "sa_player_ban_message_time": "شما توسط {lightred}{2}{default} برای {lightred}{1}{default} دقیقه به دلیل {lightred}{0}{default} مسدود شده‌اید!", "sa_player_ban_message_perm": "شما توسط {lightred}{1}{default} به دلیل {lightred}{0}{default} برای همیشه مسدود شده‌اید!", "sa_player_kick_message": "شما توسط {lightred}{1}{default} به دلیل {lightred}{0}{default} اخراج شده‌اید!", diff --git a/lang/fr.json b/lang/fr.json index c4c0ff2..27797e7 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Inconnu", + "sa_player": "Joueur", + "sa_steamid": "ID Steam", + "sa_duration": "Durée", + "sa_reason": "Raison", + "sa_admin": "Admin", + "sa_permanent": "Permanent", + + "sa_discord_penalty_ban": "Bannissement enregistré", + "sa_discord_penalty_mute": "Mute enregistré", + "sa_discord_penalty_gag": "Gag enregistré", + "sa_discord_penalty_silence": "Silence enregistré", + "sa_discord_penalty_unknown": "Inconnu enregistré", + "sa_player_ban_message_time": "Vous avez été banni pour {lightred}{0}{default} pendant {lightred}{1}{default} minutes par {lightred}{2}{default}!", "sa_player_ban_message_perm": "Vous avez été banni définitivement pour {lightred}{0}{default} par {lightred}{1}{default}!", "sa_player_kick_message": "Vous avez été expulsé pour {lightred}{0}{default} par {lightred}{1}{default}!", diff --git a/lang/lv.json b/lang/lv.json index fe09668..f8e2ea1 100644 --- a/lang/lv.json +++ b/lang/lv.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Nezināms", + "sa_player": "Spēlētājs", + "sa_steamid": "Steam ID", + "sa_duration": "Ilgums", + "sa_reason": "Iemesls", + "sa_admin": "Admins", + "sa_permanent": "Pastāvīgs", + + "sa_discord_penalty_ban": "Bans reģistrēts", + "sa_discord_penalty_mute": "Mute reģistrēts", + "sa_discord_penalty_gag": "Gag reģistrēts", + "sa_discord_penalty_silence": "Klusums reģistrēts", + "sa_discord_penalty_unknown": "Nezināms reģistrēts", + "sa_player_ban_message_time": "Tu esi nobanots uz {lightred}{0}{default} uz {lightred}{1}{default} minūtēm, iemesls: {lightred}{2}{default}!", "sa_player_ban_message_perm": "Tevis bans ir uz mūžu, iemesls: {lightred}{0}{default}, Admins: {lightred}{1}{default}!", "sa_player_kick_message": "Tu esi izmests, iemesls: {lightred}{0}{default}, Admins: {lightred}{1}{default}!", diff --git a/lang/pl.json b/lang/pl.json index 1746cb8..2ddddd7 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Brak", + "sa_player": "Gracz", + "sa_steamid": "SteamID", + "sa_duration": "Czas trwania", + "sa_reason": "Powód", + "sa_admin": "Administrator", + "sa_permanent": "Na zawsze", + + "sa_discord_penalty_ban": "Nowy ban", + "sa_discord_penalty_mute": "Nowe wyciszenie", + "sa_discord_penalty_gag": "Nowe zakneblowanie", + "sa_discord_penalty_silence": "Nowe uciszenie", + "sa_discord_penalty_unknown": "Nowa nieznana blokada", + "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 36518a2..b8a987d 100644 --- a/lang/pt-BR.json +++ b/lang/pt-BR.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Desconhecido", + "sa_player": "Jogador", + "sa_steamid": "SteamID", + "sa_duration": "Duração", + "sa_reason": "Motivo", + "sa_admin": "Admin", + "sa_permanent": "Permanente", + + "sa_discord_penalty_ban": "Banimento registrado", + "sa_discord_penalty_mute": "Mute registrado", + "sa_discord_penalty_gag": "Gag registrado", + "sa_discord_penalty_silence": "Silêncio registrado", + "sa_discord_penalty_unknown": "Desconhecido registrado", + "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 expulso por {lightred}{0}{default} por {lightred}{1}{default}!", diff --git a/lang/ru.json b/lang/ru.json index 46a49ee..6b30dd0 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Неизвестный", + "sa_player": "Игрок", + "sa_steamid": "SteamID", + "sa_duration": "Продолжительность", + "sa_reason": "Причина", + "sa_admin": "Администратор", + "sa_permanent": "Постоянный", + + "sa_discord_penalty_ban": "Бан зарегистрирован", + "sa_discord_penalty_mute": "Мут зарегистрирован", + "sa_discord_penalty_gag": "Запрет зарегистрирован", + "sa_discord_penalty_silence": "Молчание зарегистрировано", + "sa_discord_penalty_unknown": "Неизвестно зарегистрировано", + "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 a4df1ea..b337b6d 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "Bilinmeyen", + "sa_player": "Oyuncu", + "sa_steamid": "SteamID", + "sa_duration": "Süre", + "sa_reason": "Neden", + "sa_admin": "Yönetici", + "sa_permanent": "Kalıcı", + + "sa_discord_penalty_ban": "Yasak kaydedildi", + "sa_discord_penalty_mute": "Susturma kaydedildi", + "sa_discord_penalty_gag": "Susturma kaydedildi", + "sa_discord_penalty_silence": "Sessizlik kaydedildi", + "sa_discord_penalty_unknown": "Bilinmeyen kaydedildi", + "sa_player_ban_message_time": "Senaryo nedeniyle {lightred}{0}{default} dakika boyunca {lightred}{1}{default} tarafından yasaklandınız!", "sa_player_ban_message_perm": "Senaryo nedeniyle kalıcı olarak {lightred}{0}{default} tarafından yasaklandınız!", "sa_player_kick_message": "Senaryo nedeniyle {lightred}{0}{default} tarafından atıldınız!", diff --git a/lang/zh-Hans.json b/lang/zh-Hans.json index a8dc380..895c242 100644 --- a/lang/zh-Hans.json +++ b/lang/zh-Hans.json @@ -2,6 +2,19 @@ "sa_prefix": "{lightred}[SA] {default}", "sa_unknown": "未知", + "sa_player": "玩家", + "sa_steamid": "SteamID", + "sa_duration": "持续时间", + "sa_reason": "原因", + "sa_admin": "管理员", + "sa_permanent": "永久", + + "sa_discord_penalty_ban": "封禁已记录", + "sa_discord_penalty_mute": "禁言已记录", + "sa_discord_penalty_gag": "禁言已记录", + "sa_discord_penalty_silence": "禁声已记录", + "sa_discord_penalty_unknown": "未知已记录", + "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}踢出!",