From 11ae91281f64c5a77f35e5e4ca2855eb368111e3 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Sun, 26 Jan 2020 18:06:50 -0600 Subject: [PATCH] start work to allow customizing command properties via configuration --- Application/ApplicationManager.cs | 84 +- Application/IW4MServer.cs | 10 +- Application/Localization/Configure.cs | 11 +- Application/Main.cs | 20 +- Plugins/Tests/ClientTests.cs | 12 +- SharedLibraryCore/BaseController.cs | 2 +- SharedLibraryCore/Command.cs | 129 +- SharedLibraryCore/Commands/CommandArgument.cs | 18 + SharedLibraryCore/Commands/NativeCommands.cs | 1210 ++++++++++------- .../Commands/RequestTokenCommand.cs | 20 +- .../Commands/UnlinkClientCommand.cs | 17 +- .../Configuration/CommandConfiguration.cs | 24 + .../Configuration/CommandProperties.cs | 28 + .../Interfaces/IManagerCommand.cs | 38 + .../Interfaces/ITranslationLookup.cs | 15 + SharedLibraryCore/Localization/Layout.cs | 10 +- 16 files changed, 1061 insertions(+), 587 deletions(-) create mode 100644 SharedLibraryCore/Commands/CommandArgument.cs create mode 100644 SharedLibraryCore/Configuration/CommandConfiguration.cs create mode 100644 SharedLibraryCore/Configuration/CommandProperties.cs create mode 100644 SharedLibraryCore/Interfaces/IManagerCommand.cs create mode 100644 SharedLibraryCore/Interfaces/ITranslationLookup.cs diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index f16218461..cb07eb714 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -44,7 +44,7 @@ namespace IW4MAdmin.Application public string ExternalIPAddress { get; private set; } public bool IsRestartRequested { get; private set; } public IMiddlewareActionHandler MiddlewareActionHandler { get; } - private readonly List Commands; + private readonly List _commands; private readonly List MessageTokens; private readonly ClientService ClientSvc; readonly AliasService AliasSvc; @@ -57,12 +57,13 @@ namespace IW4MAdmin.Application private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0); private readonly CancellationTokenSource _tokenSource; private readonly Dictionary> _operationLookup = new Dictionary>(); + private readonly ITranslationLookup _translationLookup; + private readonly CommandConfiguration _commandConfiguration; - public ApplicationManager(ILogger logger, IMiddlewareActionHandler actionHandler) + public ApplicationManager(ILogger logger, IMiddlewareActionHandler actionHandler, IEnumerable commands, ITranslationLookup translationLookup, CommandConfiguration commandConfiguration) { MiddlewareActionHandler = actionHandler; _servers = new ConcurrentBag(); - Commands = new List(); MessageTokens = new List(); ClientSvc = new ClientService(); AliasSvc = new AliasService(); @@ -76,6 +77,9 @@ namespace IW4MAdmin.Application _metaService = new MetaService(); _tokenSource = new CancellationTokenSource(); _loggers.Add(0, logger); + _commands = commands.ToList(); + _translationLookup = translationLookup; + _commandConfiguration = commandConfiguration; } public async Task ExecuteEvent(GameEvent newEvent) @@ -155,7 +159,7 @@ namespace IW4MAdmin.Application public IList GetCommands() { - return Commands; + return new List(); } public async Task UpdateServerStates() @@ -293,7 +297,7 @@ namespace IW4MAdmin.Application serverConfig.AddEventParser(parser); } - newConfig.Servers[0] = (ServerConfiguration)serverConfig.Generate(); + newConfig.Servers = newConfig.Servers.Append((ServerConfiguration)serverConfig.Generate()).ToArray(); } while (Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["SETUP_SERVER_SAVE"])); config = newConfig; @@ -367,55 +371,35 @@ namespace IW4MAdmin.Application #endregion #region COMMANDS - if (ClientSvc.GetOwners().Result.Count == 0) + if (ClientSvc.GetOwners().Result.Count > 0) { - Commands.Add(new COwner()); + _commands.RemoveAll(_cmd => _cmd.GetType() == typeof(OwnerCommand)); } - Commands.Add(new CQuit()); - Commands.Add(new CRestart()); - Commands.Add(new CKick()); - Commands.Add(new CSay()); - Commands.Add(new CTempBan()); - Commands.Add(new CBan()); - Commands.Add(new CWhoAmI()); - Commands.Add(new CList()); - Commands.Add(new CHelp()); - Commands.Add(new CFastRestart()); - Commands.Add(new CMapRotate()); - Commands.Add(new CSetLevel()); - Commands.Add(new CUsage()); - Commands.Add(new CUptime()); - Commands.Add(new CWarn()); - Commands.Add(new CWarnClear()); - Commands.Add(new CUnban()); - Commands.Add(new CListAdmins()); - Commands.Add(new CLoadMap()); - Commands.Add(new CFindPlayer()); - Commands.Add(new CListRules()); - Commands.Add(new CPrivateMessage()); - Commands.Add(new CFlag()); - Commands.Add(new CUnflag()); - Commands.Add(new CReport()); - Commands.Add(new CListReports()); - Commands.Add(new CListBanInfo()); - Commands.Add(new CListAlias()); - Commands.Add(new CExecuteRCON()); - Commands.Add(new CPlugins()); - Commands.Add(new CIP()); - Commands.Add(new CMask()); - Commands.Add(new CPruneAdmins()); - //Commands.Add(new CKillServer()); - Commands.Add(new CSetPassword()); - Commands.Add(new CPing()); - Commands.Add(new CSetGravatar()); - Commands.Add(new CNextMap()); - Commands.Add(new RequestTokenCommand()); - Commands.Add(new UnlinkClientCommand()); - foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands) { - Commands.Add(C); + _commands.Add(C); + } + + if (_commandConfiguration == null) + { + // todo: this is here for now. it's not the most elegant but currently there's no way to know all the plugin comamnds during DI + var handler = new BaseConfigurationHandler("CommandConfiguration"); + var cmdConfig = new CommandConfiguration(); + + foreach (var cmd in _commands) + { + cmdConfig.Commands.Add(cmd.GetType().Name, + new CommandProperties() + { + Name = cmd.Name, + Alias = cmd.Alias, + MinimumPermission = cmd.Permission + }); + } + + handler.Set(cmdConfig); + await handler.Save(); } #endregion @@ -557,7 +541,7 @@ namespace IW4MAdmin.Application try { - var ServerInstance = new IW4MServer(this, Conf); + var ServerInstance = new IW4MServer(this, Conf, _translationLookup); await ServerInstance.Initialize(); _servers.Add(ServerInstance); diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 3c67255a2..93a1d44f4 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -23,14 +23,16 @@ namespace IW4MAdmin { public class IW4MServer : Server { - private static readonly SharedLibraryCore.Localization.Index loc = Utilities.CurrentLocalization.LocalizationIndex; + private static readonly SharedLibraryCore.Localization.TranslationLookup loc = Utilities.CurrentLocalization.LocalizationIndex; private GameLogEventDetection LogEvent; + private readonly ITranslationLookup _translationLookup; private const int REPORT_FLAG_COUNT = 4; public int Id { get; private set; } - public IW4MServer(IManager mgr, ServerConfiguration cfg) : base(mgr, cfg) + public IW4MServer(IManager mgr, ServerConfiguration cfg, ITranslationLookup lookup) : base(mgr, cfg) { + _translationLookup = lookup; } override public async Task OnClientConnected(EFClient clientFromLog) @@ -1186,8 +1188,8 @@ namespace IW4MAdmin { Manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYERS", (Server s) => Task.Run(async () => (await Manager.GetClientService().GetTotalClientsAsync()).ToString()))); Manager.GetMessageTokens().Add(new MessageToken("VERSION", (Server s) => Task.FromResult(Application.Program.Version.ToString()))); - Manager.GetMessageTokens().Add(new MessageToken("NEXTMAP", (Server s) => SharedLibraryCore.Commands.CNextMap.GetNextMap(s))); - Manager.GetMessageTokens().Add(new MessageToken("ADMINS", (Server s) => Task.FromResult(SharedLibraryCore.Commands.CListAdmins.OnlineAdmins(s)))); + Manager.GetMessageTokens().Add(new MessageToken("NEXTMAP", (Server s) => SharedLibraryCore.Commands.NextMapCommand.GetNextMap(s, _translationLookup))); + Manager.GetMessageTokens().Add(new MessageToken("ADMINS", (Server s) => Task.FromResult(SharedLibraryCore.Commands.ListAdminsCommand.OnlineAdmins(s, _translationLookup)))); } } } diff --git a/Application/Localization/Configure.cs b/Application/Localization/Configure.cs index 24eaa259f..a22e88da8 100644 --- a/Application/Localization/Configure.cs +++ b/Application/Localization/Configure.cs @@ -1,30 +1,29 @@ using IW4MAdmin.Application.API.Master; using SharedLibraryCore; +using SharedLibraryCore.Interfaces; using System; using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace IW4MAdmin.Application.Localization { public class Configure { - public static void Initialize(string customLocale = null) + public static ITranslationLookup Initialize(bool useLocalTranslation, string customLocale = null) { string currentLocale = string.IsNullOrEmpty(customLocale) ? CultureInfo.CurrentCulture.Name : customLocale; string[] localizationFiles = Directory.GetFiles(Path.Join(Utilities.OperatingDirectory, "Localization"), $"*.{currentLocale}.json"); - if (!Program.ServerManager.GetApplicationSettings()?.Configuration()?.UseLocalTranslations ?? false) + if (!useLocalTranslation) { try { var api = Endpoint.Get(); var localization = api.GetLocalization(currentLocale).Result; Utilities.CurrentLocalization = localization; - return; + return localization.LocalizationIndex; } catch (Exception) @@ -73,6 +72,8 @@ namespace IW4MAdmin.Application.Localization { LocalizationName = currentLocale, }; + + return Utilities.CurrentLocalization.LocalizationIndex; } } } diff --git a/Application/Main.cs b/Application/Main.cs index 5bf79a111..58a47aca7 100644 --- a/Application/Main.cs +++ b/Application/Main.cs @@ -2,10 +2,12 @@ using IW4MAdmin.Application.Misc; using Microsoft.Extensions.DependencyInjection; using SharedLibraryCore; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Exceptions; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; using System; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -69,9 +71,6 @@ namespace IW4MAdmin.Application ServerManager = (ApplicationManager)builder.GetRequiredService(); } - var configuration = ServerManager.GetApplicationSettings().Configuration(); - Localization.Configure.Initialize(configuration?.EnableCustomLocale ?? false ? (configuration.CustomLocale ?? "en-US") : "en-US"); - // do any needed housekeeping file/folder migrations ConfigurationMigration.MoveConfigFolder10518(null); ConfigurationMigration.CheckDirectories(); @@ -259,8 +258,21 @@ namespace IW4MAdmin.Application { var serviceProvider = new ServiceCollection(); serviceProvider.AddSingleton() + .AddSingleton(_serviceProvider => new BaseConfigurationHandler("IW4MAdminSettings").Configuration()) + .AddSingleton(_serviceProvider => new BaseConfigurationHandler("CommandConfiguration").Configuration()) .AddSingleton(_serviceProvider => new Logger("IW4MAdmin-Manager")) - .AddSingleton(); + .AddSingleton() + .AddSingleton(_serviceProvider => + { + var config = _serviceProvider.GetRequiredService(); + return Localization.Configure.Initialize(config?.UseLocalTranslations ?? false, config?.EnableCustomLocale ?? false ? (config.CustomLocale ?? "en-US") : "en-US"); + }); + + + foreach (var commandDefinition in typeof(SharedLibraryCore.Commands.QuitCommand).Assembly.GetTypes().Where(_command => _command.BaseType == typeof(Command))) + { + serviceProvider.AddTransient(typeof(IManagerCommand), commandDefinition); + } return serviceProvider; } diff --git a/Plugins/Tests/ClientTests.cs b/Plugins/Tests/ClientTests.cs index 92da5a042..e72f0dfab 100644 --- a/Plugins/Tests/ClientTests.cs +++ b/Plugins/Tests/ClientTests.cs @@ -293,7 +293,7 @@ namespace Tests var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault(); Assert.False(client == null, "no client found to tempban"); - var tbCommand = new CTempBan(); + /* var tbCommand = new TempBanCommand(); tbCommand.ExecuteAsync(new GameEvent() { Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }, @@ -304,7 +304,7 @@ namespace Tests }).Wait(); Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.TempBan) == 1, - "tempban was not added"); + "tempban was not added");*/ } [Fact] @@ -317,8 +317,8 @@ namespace Tests var client = _manager.Servers.First().GetClientsAsList().FirstOrDefault(); Assert.False(client == null, "no client found to ban"); - - var banCommand = new CBan(); +/* + var banCommand = new BanCommand(); banCommand.ExecuteAsync(new GameEvent() { Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }, @@ -331,7 +331,7 @@ namespace Tests Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 1, "ban was not added"); - var unbanCommand = new CUnban(); + var unbanCommand = new UnbanCommand(); unbanCommand.ExecuteAsync(new GameEvent() { Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer }, @@ -342,7 +342,7 @@ namespace Tests }).Wait(); Assert.True(_manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId).Result.Count(p => p.Type == EFPenalty.PenaltyType.Ban) == 0, - "ban was not removed"); + "ban was not removed");*/ } } diff --git a/SharedLibraryCore/BaseController.cs b/SharedLibraryCore/BaseController.cs index c175e393d..dbda938f5 100644 --- a/SharedLibraryCore/BaseController.cs +++ b/SharedLibraryCore/BaseController.cs @@ -25,7 +25,7 @@ namespace SharedLibraryCore public IManager Manager { get; private set; } protected readonly DatabaseContext Context; protected bool Authorized { get; set; } - protected SharedLibraryCore.Localization.Index Localization { get; private set; } + protected SharedLibraryCore.Localization.TranslationLookup Localization { get; private set; } protected EFClient Client { get; private set; } private static readonly byte[] LocalHost = { 127, 0, 0, 1 }; private static string SocialLink; diff --git a/SharedLibraryCore/Command.cs b/SharedLibraryCore/Command.cs index 89805e405..a9ea491f0 100644 --- a/SharedLibraryCore/Command.cs +++ b/SharedLibraryCore/Command.cs @@ -1,38 +1,121 @@ -using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using SharedLibraryCore.Commands; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; namespace SharedLibraryCore { - public class CommandArgument + /// + /// Abstract class for command + /// + public abstract class Command : IManagerCommand { - public string Name { get; set; } - public bool Required { get; set; } - } + private readonly CommandConfiguration _config; + protected readonly ITranslationLookup _translationLookup; - public abstract class Command - { - public Command(String commandName, String commandDescription, String commandAlias, EFClient.Permission requiredPermission, bool requiresTarget, CommandArgument[] param = null) - { - Name = commandName; - Description = commandDescription; - Alias = commandAlias; - Permission = requiredPermission; - RequiresTarget = requiresTarget; - Arguments = param ?? new CommandArgument[0]; + public Command(CommandConfiguration config, ITranslationLookup layout) + { + _config = config; + _translationLookup = layout; } - //Execute the command + /// + /// Executes the command + /// + /// + /// abstract public Task ExecuteAsync(GameEvent E); - public String Name { get; private set; } - public String Description { get; private set; } - public String Syntax => $"{Utilities.CurrentLocalization.LocalizationIndex["COMMAND_HELP_SYNTAX"]} !{Alias} {String.Join(" ", Arguments.Select(a => $"<{(a.Required ? "" : Utilities.CurrentLocalization.LocalizationIndex["COMMAND_HELP_OPTIONAL"] + " ")}{a.Name}>"))}"; - public String Alias { get; private set; } + /// + /// Specifies the name and string that triggers the command + /// + public string Name + { + get => name; + protected set + { + try + { + name = _config?.Commands[GetType().Name].Name ?? value; + } + + catch (KeyNotFoundException) + { + name = value; + } + } + } + private string name; + + /// + /// Specifies the command description + /// + public string Description { get; protected set; } + + /// + /// Helper property to provide the syntax of the command + /// + public string Syntax => $"{_translationLookup["COMMAND_HELP_SYNTAX"]} !{Alias} {string.Join(" ", Arguments.Select(a => $"<{(a.Required ? "" : _translationLookup["COMMAND_HELP_OPTIONAL"] + " ")}{a.Name}>"))}"; + + /// + /// Alternate name for this command to be executed by + /// + public string Alias + { + get => alias; + protected set + { + try + { + alias = _config?.Commands[GetType().Name].Alias ?? value; + } + + catch (KeyNotFoundException) + { + alias = value; + } + } + } + private string alias; + + /// + /// Helper property to determine the number of required args + /// public int RequiredArgumentCount => Arguments.Count(c => c.Required); - public bool RequiresTarget { get; private set; } - public EFClient.Permission Permission { get; private set; } - public CommandArgument[] Arguments { get; private set; } + + /// + /// Indicates if the command requires a target to execute on + /// + public bool RequiresTarget { get; protected set; } + + /// + /// Minimum permission level to execute command + /// + public EFClient.Permission Permission + { + get => permission; + protected set + { + try + { + permission = _config?.Commands[GetType().Name].MinimumPermission ?? value; + } + + catch (KeyNotFoundException) + { + permission = value; + } + } + } + private EFClient.Permission permission; + + + /// + /// Argument list for the command + /// + public CommandArgument[] Arguments { get; protected set; } = new CommandArgument[0]; } } diff --git a/SharedLibraryCore/Commands/CommandArgument.cs b/SharedLibraryCore/Commands/CommandArgument.cs new file mode 100644 index 000000000..bd41170ec --- /dev/null +++ b/SharedLibraryCore/Commands/CommandArgument.cs @@ -0,0 +1,18 @@ +namespace SharedLibraryCore.Commands +{ + /// + /// Holds information about command args + /// + public class CommandArgument + { + /// + /// Name of the argument + /// + public string Name { get; set; } + + /// + /// Indicates if the argument is required + /// + public bool Required { get; set; } + } +} diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 7c64ae9cf..056f17fa7 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -1,12 +1,13 @@ using Microsoft.EntityFrameworkCore; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; using SharedLibraryCore.Helpers; +using SharedLibraryCore.Interfaces; using SharedLibraryCore.Services; using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -15,11 +16,19 @@ using static SharedLibraryCore.Database.Models.EFClient; namespace SharedLibraryCore.Commands { - public class CQuit : Command + /// + /// Quits IW4MAdmin + /// + public class QuitCommand : Command { - public CQuit() : - base("quit", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_QUIT_DESC"], "q", EFClient.Permission.Owner, false) - { } + public QuitCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "quit"; + Description = _translationLookup["COMMANDS_QUIT_DESC"]; + Alias = "q"; + Permission = Permission.Owner; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { @@ -28,172 +37,233 @@ namespace SharedLibraryCore.Commands } } - public class CRestart : Command + /// + /// Restarts IW4MAdmin + /// + public class RestartCommand : Command { - public CRestart() : - base("restart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_DESC"], "res", EFClient.Permission.Owner, false) - { } + public RestartCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "restart"; + Description = _translationLookup["COMMANDS_RESTART_DESC"]; + Alias = "res"; + Permission = Permission.Owner; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { MetaService.Clear(); E.Owner.Manager.Restart(); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RESTART_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_RESTART_SUCCESS"]); return Task.CompletedTask; } } - public class COwner : Command + /// + /// Claims ownership of the server + /// + public class OwnerCommand : Command { - public COwner() : - base("owner", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_DESC"], "iamgod", EFClient.Permission.User, false) - { } + public OwnerCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "owner"; + Description = _translationLookup["COMMANDS_OWNER_DESC"]; + Alias = "iamgod"; + Permission = Permission.User; + RequiresTarget = false; + } public override async Task ExecuteAsync(GameEvent E) { if (await (E.Owner.Manager.GetClientService() as ClientService).GetOwnerCount() == 0 && !E.Origin.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_OWNER_SUCCESS"]); } else { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_FAIL"]); + E.Origin.Tell(_translationLookup["COMMANDS_OWNER_FAIL"]); } } } - public class CWarn : Command + /// + /// Warns given client for reason + /// + public class WarnCommand : Command { - public CWarn() : - base("warn", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_DESC"], "w", EFClient.Permission.Trusted, true, new CommandArgument[] + public WarnCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "warn"; + Description = _translationLookup["COMMANDS_WARN_DESC"]; + Alias = "w"; + Permission = Permission.Trusted; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } public override Task ExecuteAsync(GameEvent E) { if (E.Target.Warn(E.Data, E.Origin).Failed) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_WARN_FAIL"].FormatExt(E.Target.Name)); } return Task.CompletedTask; } } - public class CWarnClear : Command + /// + /// Clears all warnings for given client + /// + public class WarnClearCommand : Command { - public CWarnClear() : - base("warnclear", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_DESC"], "wc", EFClient.Permission.Trusted, true, new CommandArgument[] + public WarnClearCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "warnclear"; + Description = _translationLookup["COMMANDS_WARNCLEAR_DESC"]; + Alias = "wc"; + Permission = Permission.Trusted; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + } + }; + } public override Task ExecuteAsync(GameEvent E) { if (!E.Target.WarnClear(E.Origin).Failed) { - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_SUCCESS"].FormatExt(E.Target.Name)); + E.Owner.Broadcast(_translationLookup["COMMANDS_WARNCLEAR_SUCCESS"].FormatExt(E.Target.Name)); } return Task.CompletedTask; } } - public class CKick : Command + /// + /// Kicks client for given reason + /// + public class KickCommand : Command { - public CKick() : - base("kick", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_DESC"], "k", EFClient.Permission.Moderator, true, new CommandArgument[] + public KickCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "kick"; + Description = _translationLookup["COMMANDS_KICK_DESC"]; + Alias = "k"; + Permission = Permission.Moderator; + RequiresTarget = true; + Arguments = new[] { new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], Required = true }, new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], + Name = _translationLookup["COMMANDS_ARGS_REASON"], Required = true } - }) - { } + }; + } public override async Task ExecuteAsync(GameEvent E) { switch ((await E.Target.Kick(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_SUCCESS"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_KICK_SUCCESS"].FormatExt(E.Target.Name)); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_KICK_FAIL"].FormatExt(E.Target.Name)); break; } } } - public class CSay : Command + /// + /// Prints out a message to all clients on the server + /// + public class SayCommand : Command { - public CSay() : - base("say", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_DESC"], "s", EFClient.Permission.Moderator, false, new CommandArgument[] + public SayCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "say"; + Description = _translationLookup["COMMANDS_SAY_DESC"]; + Alias = "s"; + Permission = Permission.Moderator; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_MESSAGE"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_MESSAGE"], + Required = true + } + }; + } public override Task ExecuteAsync(GameEvent E) { E.Owner.Broadcast($"{(E.Owner.GameName == Server.Game.IW4 ? "^:" : "")}{E.Origin.Name} - ^6{E.Data}^7", E.Origin); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_SAY_SUCCESS"]); return Task.CompletedTask; } } - public class CTempBan : Command + /// + /// Temporarily bans a client + /// + public class TempBanCommand : Command { - public CTempBan() : - base("tempban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_DESC"], "tb", EFClient.Permission.Administrator, true, new CommandArgument[] + public TempBanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "tempban"; + Description = _translationLookup["COMMANDS_TEMPBAN_DESC"]; + Alias = "tb"; + Permission = Permission.Administrator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_DURATION"], - Required = true, - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_DURATION"], + Required = true, + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } private static readonly string TempBanRegex = @"([0-9]+\w+)\ (.+)"; @@ -207,7 +277,7 @@ namespace SharedLibraryCore.Commands if (length > E.Owner.Manager.GetApplicationSettings().Configuration().MaximumTempBanTime) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_FAIL_TOOLONG"]); + E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL_TOOLONG"]); } else @@ -215,13 +285,13 @@ namespace SharedLibraryCore.Commands switch ((await E.Target.TempBan(tempbanReason, length, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.TimeSpanText())); + E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_SUCCESS"].FormatExt(E.Target, length.TimeSpanText())); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_TEMPBAN_FAIL"].FormatExt(E.Target.Name)); break; } } @@ -229,58 +299,76 @@ namespace SharedLibraryCore.Commands } } - public class CBan : Command + /// + /// Permanently bans a client + /// + public class BanCommand : Command { - public CBan() : - base("ban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_DESC"], "b", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] + public BanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "ban"; + Description = _translationLookup["COMMANDS_BAN_DESC"]; + Alias = "b"; + Permission = Permission.SeniorAdmin; + RequiresTarget = true; + Arguments = new[] { new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], Required = true }, new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], + Name = _translationLookup["COMMANDS_ARGS_REASON"], Required = true } - }) - { } + }; + } public override async Task ExecuteAsync(GameEvent E) { switch ((await E.Target.Ban(E.Data, E.Origin, false).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_SUCCESS"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_BAN_SUCCESS"].FormatExt(E.Target.Name)); break; case GameEvent.EventFailReason.Exception: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_BAN_FAIL"].FormatExt(E.Target.Name)); break; } } } - public class CUnban : Command + /// + /// Unbans a banned client + /// + public class UnbanCommand : Command { - public CUnban() : - base("unban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_DESC"], "ub", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] + public UnbanCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "unban"; + Description = _translationLookup["COMMANDS_UNBAN_DESC"]; + Alias = "ub"; + Permission = Permission.SeniorAdmin; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_CLIENTID"], - Required = true, - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_CLIENTID"], + Required = true, + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -291,41 +379,57 @@ namespace SharedLibraryCore.Commands switch ((await E.Target.Unban(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_SUCCESS"].FormatExt(E.Target)); + E.Origin.Tell(_translationLookup["COMMANDS_UNBAN_SUCCESS"].FormatExt(E.Target)); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; } } else { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_FAIL"].FormatExt(E.Target)); + E.Origin.Tell(_translationLookup["COMMANDS_UNBAN_FAIL"].FormatExt(E.Target)); } } } - public class CWhoAmI : Command + /// + /// Prints client information + /// + public class WhoAmICommand : Command { - public CWhoAmI() : - base("whoami", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WHO_DESC"], "who", EFClient.Permission.User, false) - { } + public WhoAmICommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "whoami"; + Description = _translationLookup["COMMANDS_WHO_DESC"]; + Alias = "who"; + Permission = Permission.User; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { - String You = String.Format("{0} [^3#{1}^7] {2} ^7[^3@{3}^7] ^7[{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level, E.Origin.ClientPermission.Name), E.Origin.IPAddressString); - E.Origin.Tell(You); + string you = string.Format("{0} [^3#{1}^7] {2} ^7[^3@{3}^7] ^7[{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientNumber, E.Origin.NetworkId, E.Origin.ClientId, Utilities.ConvertLevelToColor(E.Origin.Level, E.Origin.ClientPermission.Name), E.Origin.IPAddressString); + E.Origin.Tell(you); return Task.CompletedTask; } } - public class CList : Command + /// + /// List online clients + /// + public class ListClientsCommand : Command { - public CList() : - base("list", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_LIST_DESC"], "l", EFClient.Permission.Moderator, false) - { } + public ListClientsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "list"; + Description = _translationLookup["COMMANDS_LIST_DESC"]; + Alias = "l"; + Permission = Permission.Moderator; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { @@ -372,18 +476,27 @@ namespace SharedLibraryCore.Commands } } - public class CHelp : Command + /// + /// Prints help information + /// + public class HelpCommand : Command { - public CHelp() : - base("help", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_DESC"], "h", EFClient.Permission.User, false, new CommandArgument[] + public HelpCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "help"; + Description = _translationLookup["COMMANDS_HELP_DESC"]; + Alias = "h"; + Permission = Permission.User; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_COMMANDS"], - Required = false - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_COMMANDS"], + Required = false + } + }; + } public override Task ExecuteAsync(GameEvent E) { @@ -405,7 +518,7 @@ namespace SharedLibraryCore.Commands if (!found) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_NOTFOUND"]); + E.Origin.Tell(_translationLookup["COMMANDS_HELP_NOTFOUND"]); } } @@ -430,63 +543,88 @@ namespace SharedLibraryCore.Commands } } E.Origin.Tell(helpResponse.ToString()); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_MOREINFO"]); + E.Origin.Tell(_translationLookup["COMMANDS_HELP_MOREINFO"]); } return Task.CompletedTask; } } - public class CFastRestart : Command + /// + /// Fast restarts the map + /// + public class FastRestartCommand : Command { - public CFastRestart() : - base("fastrestart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_DESC"], "fr", EFClient.Permission.Moderator, false) - { } + public FastRestartCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "fastrestart"; + Description = _translationLookup["COMMANDS_FASTRESTART_DESC"]; + Alias = "fr"; + Permission = Permission.Moderator; + RequiresTarget = false; + } public override async Task ExecuteAsync(GameEvent E) { await E.Owner.ExecuteCommandAsync("fast_restart"); var _ = !E.Origin.Masked ? - E.Owner.Broadcast($"^5{E.Origin.Name} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_UNMASKED"]}") : - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_MASKED"]); + E.Owner.Broadcast($"^5{E.Origin.Name} ^7{_translationLookup["COMMANDS_FASTRESTART_UNMASKED"]}") : + E.Owner.Broadcast(_translationLookup["COMMANDS_FASTRESTART_MASKED"]); } } - public class CMapRotate : Command + /// + /// Cycles to the next map in rotation + /// + public class MapRotateCommand : Command { - public CMapRotate() : - base("maprotate", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE_DESC"], "mr", EFClient.Permission.Administrator, false) - { } + public MapRotateCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "maprotate"; + Description = _translationLookup["COMMANDS_MAPROTATE_DESC"]; + Alias = "mr"; + Permission = Permission.Administrator; + RequiresTarget = false; + } public override async Task ExecuteAsync(GameEvent E) { var _ = !E.Origin.Masked ? - E.Owner.Broadcast($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE"]} [^5{E.Origin.Name}^7]", E.Origin) : - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE"], E.Origin); + E.Owner.Broadcast($"{_translationLookup["COMMANDS_MAPROTATE"]} [^5{E.Origin.Name}^7]", E.Origin) : + E.Owner.Broadcast(_translationLookup["COMMANDS_MAPROTATE"], E.Origin); await Task.Delay(5000); await E.Owner.ExecuteCommandAsync("map_rotate"); } } - public class CSetLevel : Command + /// + /// Sets the level of given client + /// + public class SetLevelCommand : Command { - public CSetLevel() : - base("setlevel", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DESC"], "sl", EFClient.Permission.Moderator, true, new CommandArgument[] - { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_LEVEL"], - Required = true - } - }) - { } + public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "setlevel"; + Description = _translationLookup["COMMANDS_SETLEVEL_DESC"]; + Alias = "sl"; + Permission = Permission.Moderator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_LEVEL"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -495,7 +633,7 @@ namespace SharedLibraryCore.Commands if (E.Target == E.Origin) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SELF"]); + E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SELF"]); return; } @@ -504,7 +642,7 @@ namespace SharedLibraryCore.Commands await E.Owner.Manager.GetClientService().GetOwnerCount() > 0) { // only one owner is allowed - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_OWNER"]); + E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]); return; } @@ -512,7 +650,7 @@ namespace SharedLibraryCore.Commands !E.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy) { // only the owner is allowed to set levels - E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{E.Target.Name}"); + E.Origin.Tell($"{_translationLookup["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{E.Target.Name}"); return; } @@ -522,7 +660,7 @@ namespace SharedLibraryCore.Commands { // can't promote a client to higher than your current perms // or your peer - E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString())); + E.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString())); return; } @@ -539,7 +677,7 @@ namespace SharedLibraryCore.Commands // we don't really want to tell them if they're demoted haha if (newPerm > oldPerm) { - ActiveClient.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm)); + ActiveClient.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm)); } } @@ -550,66 +688,90 @@ namespace SharedLibraryCore.Commands // inform the origin that the client has been updated _ = newPerm < oldPerm ? - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(E.Target.Name)) : - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(E.Target.Name)) : + E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(E.Target.Name)); } else { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_FAIL"]); + E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]); } } } - public class CUsage : Command + /// + /// Prints the amount of memory IW4MAdmin is using + /// + public class MemoryUsageCommand : Command { - public CUsage() : - base("usage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_DESC"], "us", EFClient.Permission.Moderator, false) - { } + public MemoryUsageCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "usage"; + Description = _translationLookup["COMMANDS_USAGE_DESC"]; + Alias = "us"; + Permission = Permission.Moderator; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_TEXT"].FormatExt(Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1))); + E.Origin.Tell(_translationLookup["COMMANDS_USAGE_TEXT"].FormatExt(Math.Round(((System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / 2048f) / 1200f), 1))); return Task.CompletedTask; } } - public class CUptime : Command + /// + /// Prints out how long IW4MAdmin has been running + /// + public class UptimeCommand : Command { - public CUptime() : - base("uptime", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UPTIME_DESC"], "up", EFClient.Permission.Moderator, false) - { } + public UptimeCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "uptime"; + Description = _translationLookup["COMMANDS_UPTIME_DESC"]; + Alias = "up"; + Permission = Permission.Moderator; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { TimeSpan uptime = DateTime.Now - System.Diagnostics.Process.GetCurrentProcess().StartTime; - var loc = Utilities.CurrentLocalization.LocalizationIndex; + var loc = _translationLookup; E.Origin.Tell(loc["COMMANDS_UPTIME_TEXT"].FormatExt(uptime.Days, uptime.Hours, uptime.Minutes)); return Task.CompletedTask; } } - public class CListAdmins : Command + /// + /// Lists all unmasked admins + /// + public class ListAdminsCommand : Command { - public CListAdmins() : - base("admins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_DESC"], "a", EFClient.Permission.User, false) - { } + public ListAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "admins"; + Description = _translationLookup["COMMANDS_ADMINS_DESC"]; + Alias = "a"; + Permission = Permission.User; + RequiresTarget = false; + } - public static string OnlineAdmins(Server S) + public static string OnlineAdmins(Server S, ITranslationLookup lookup) { var onlineAdmins = S.GetClientsAsList() - .Where(p => p.Level > EFClient.Permission.Flagged) + .Where(p => p.Level > Permission.Flagged) .Where(p => !p.Masked) .Select(p => $"[^3{Utilities.ConvertLevelToColor(p.Level, p.ClientPermission.Name)}^7] {p.Name}"); return onlineAdmins.Count() > 0 ? string.Join(Environment.NewLine, onlineAdmins) : - Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_NONE"]; + lookup["COMMANDS_ADMINS_NONE"]; } public override Task ExecuteAsync(GameEvent E) { - foreach (string line in OnlineAdmins(E.Owner).Split(Environment.NewLine)) + foreach (string line in OnlineAdmins(E.Owner, _translationLookup).Split(Environment.NewLine)) { var _ = E.Message.IsBroadcastCommand() ? E.Owner.Broadcast(line) : E.Origin.Tell(line); } @@ -618,18 +780,27 @@ namespace SharedLibraryCore.Commands } } - public class CLoadMap : Command + /// + /// Attempts to load the specified map + /// + public class LoadMapCommand : Command { - public CLoadMap() : - base("map", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_DESC"], "m", EFClient.Permission.Administrator, false, new CommandArgument[] + public LoadMapCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "map"; + Description = _translationLookup["COMMANDS_MAP_DESC"]; + Alias = "m"; + Permission = Permission.Administrator; + RequiresTarget = false; + Arguments = new[] { new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_MAP"], + Name = _translationLookup["COMMANDS_ARGS_MAP"], Required = true } - }) - { } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -638,7 +809,7 @@ namespace SharedLibraryCore.Commands { if (m.Name.ToLower() == newMap || m.Alias.ToLower() == newMap) { - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_SUCCESS"].FormatExt(m.Alias)); + E.Owner.Broadcast(_translationLookup["COMMANDS_MAP_SUCCESS"].FormatExt(m.Alias)); await Task.Delay((int)(Utilities.DefaultCommandTimeout.TotalMilliseconds / 2.0)); await E.Owner.LoadMap(m.Name); return; @@ -646,30 +817,39 @@ namespace SharedLibraryCore.Commands } // todo: this can be moved into a single statement - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_UKN"].FormatExt(newMap)); + E.Owner.Broadcast(_translationLookup["COMMANDS_MAP_UKN"].FormatExt(newMap)); await Task.Delay(5000); await E.Owner.LoadMap(newMap); } } - public class CFindPlayer : Command + /// + /// Finds player by name + /// + public class FindPlayerCommand : Command { - public CFindPlayer() : - base("find", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_DESC"], "f", EFClient.Permission.Administrator, false, new CommandArgument[] + public FindPlayerCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "find"; + Description = _translationLookup["COMMANDS_FIND_DESC"]; + Alias = "f"; + Permission = Permission.Administrator; + RequiresTarget = false; + Arguments = new[] { new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], Required = true } - }) - { } + }; + } public override async Task ExecuteAsync(GameEvent E) { if (E.Data.Length < 3) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_MIN"]); + E.Origin.Tell(_translationLookup["COMMANDS_FIND_MIN"]); return; } @@ -677,7 +857,7 @@ namespace SharedLibraryCore.Commands if (db_players.Count == 0) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_EMPTY"]); + E.Origin.Tell(_translationLookup["COMMANDS_FIND_EMPTY"]); return; } @@ -693,11 +873,19 @@ namespace SharedLibraryCore.Commands } } - public class CListRules : Command + /// + /// Lists server and global rules + /// + public class ListRulesCommands : Command { - public CListRules() : - base("rules", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_DESC"], "r", EFClient.Permission.User, false) - { } + public ListRulesCommands(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "rules"; + Description = _translationLookup["COMMANDS_RULES_DESC"]; + Alias = "r"; + Permission = Permission.User; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { @@ -705,8 +893,8 @@ namespace SharedLibraryCore.Commands E.Owner.ServerConfig.Rules?.Length < 1) { var _ = E.Message.IsBroadcastCommand() ? - E.Owner.Broadcast(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_NONE"]) : - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_NONE"]); + E.Owner.Broadcast(_translationLookup["COMMANDS_RULES_NONE"]) : + E.Origin.Tell(_translationLookup["COMMANDS_RULES_NONE"]); } else @@ -728,23 +916,32 @@ namespace SharedLibraryCore.Commands } } - public class CPrivateMessage : Command + /// + /// Sends a private message to another player + /// + public class PrivateMessageCommand : Command { - public CPrivateMessage() : - base("privatemessage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PM_DESC"], "pm", EFClient.Permission.User, true, new CommandArgument[] + public PrivateMessageCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "privatemessage"; + Description = _translationLookup["COMMANDS_PM_DESC"]; + Alias = "pm"; + Permission = Permission.User; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_MESSAGE"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_MESSAGE"], + Required = true + } + }; + } public override Task ExecuteAsync(GameEvent E) { @@ -754,102 +951,132 @@ namespace SharedLibraryCore.Commands } } - - public class CFlag : Command + /// + /// Flag given client for specified reason + /// + public class FlagClientCommand : Command { - public CFlag() : - base("flag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_DESC"], "fp", EFClient.Permission.Moderator, true, new CommandArgument[] + public FlagClientCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "flag"; + Description = _translationLookup["COMMANDS_FLAG_DESC"]; + Alias = "fp"; + Permission = Permission.Moderator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { switch ((await E.Target.Flag(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.Permission: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_FLAG_FAIL"].FormatExt(E.Target.Name)); break; case GameEvent.EventFailReason.Invalid: - E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_ALREADYFLAGGED"]}"); + E.Origin.Tell($"{_translationLookup["COMMANDS_FLAG_ALREADYFLAGGED"]}"); break; case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_SUCCESS"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_FLAG_SUCCESS"].FormatExt(E.Target.Name)); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; } } } - public class CUnflag : Command + /// + /// Unflag given client for specified reason + /// + public class UnflagClientCommand : Command { - public CUnflag() : - base("unflag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_DESC"], "uf", EFClient.Permission.Moderator, true, new CommandArgument[] + public UnflagClientCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "unflag"; + Description = _translationLookup["COMMANDS_UNFLAG_DESC"]; + Alias = "uf"; + Permission = Permission.Moderator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { switch ((await E.Target.Unflag(E.Data, E.Origin).WaitAsync(Utilities.DefaultCommandTimeout, E.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_UNFLAG"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_FLAG_UNFLAG"].FormatExt(E.Target.Name)); break; case GameEvent.EventFailReason.Permission: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_FAIL"].FormatExt(E.Target.Name)); + E.Origin.Tell(_translationLookup["COMMANDS_UNFLAG_FAIL"].FormatExt(E.Target.Name)); break; case GameEvent.EventFailReason.Invalid: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_NOTFLAGGED"]); + E.Origin.Tell(_translationLookup["COMMANDS_UNFLAG_NOTFLAGGED"]); break; default: - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_COMMAND_INGAME"]); + E.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); break; } } } - - public class CReport : Command + /// + /// Report client for given reason + /// + public class ReportClientCommand : Command { - public CReport() : - base("report", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_DESC"], "rep", EFClient.Permission.User, true, new CommandArgument[] + public ReportClientCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "report"; + Description = _translationLookup["COMMANDS_REPORT_DESC"]; + Alias = "rep"; + Permission = Permission.User; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - }, - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_REASON"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + }, + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_REASON"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent commandEvent) { if (commandEvent.Data.ToLower().Contains("camp")) { - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_CAMP"]); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_FAIL_CAMP"]); return; } @@ -858,20 +1085,20 @@ namespace SharedLibraryCore.Commands switch ((await commandEvent.Target.Report(commandEvent.Data, commandEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, commandEvent.Owner.Manager.CancellationToken)).FailReason) { case GameEvent.EventFailReason.None: - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_SUCCESS"]); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_SUCCESS"]); success = true; break; case GameEvent.EventFailReason.Exception: - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_DUPLICATE"]); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_FAIL_DUPLICATE"]); break; case GameEvent.EventFailReason.Permission: - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL"].FormatExt(commandEvent.Target.Name)); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_FAIL"].FormatExt(commandEvent.Target.Name)); break; case GameEvent.EventFailReason.Invalid: - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_SELF"]); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_FAIL_SELF"]); break; case GameEvent.EventFailReason.Throttle: - commandEvent.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_FAIL_TOOMANY"]); + commandEvent.Origin.Tell(_translationLookup["COMMANDS_REPORT_FAIL_TOOMANY"]); break; } @@ -882,31 +1109,40 @@ namespace SharedLibraryCore.Commands } } - public class CListReports : Command + /// + /// List all reports on the server + /// + public class ListReportsCommand : Command { - public CListReports() : - base("reports", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_DESC"], "reps", EFClient.Permission.Moderator, false, new CommandArgument[] + public ListReportsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "reports"; + Description = _translationLookup["COMMANDS_REPORTS_DESC"]; + Alias = "reps"; + Permission = Permission.Moderator; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_CLEAR"], - Required = false - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_CLEAR"], + Required = false + } + }; + } public override Task ExecuteAsync(GameEvent E) { - if (E.Data != null && E.Data.ToLower().Contains(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_CLEAR"])) + if (E.Data != null && E.Data.ToLower().Contains(_translationLookup["COMMANDS_ARGS_CLEAR"])) { E.Owner.Reports = new List(); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_CLEAR_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_REPORTS_CLEAR_SUCCESS"]); return Task.CompletedTask; } if (E.Owner.Reports.Count < 1) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_NONE"]); + E.Origin.Tell(_translationLookup["COMMANDS_REPORTS_NONE"]); return Task.CompletedTask; } @@ -919,41 +1155,58 @@ namespace SharedLibraryCore.Commands } } - public class CMask : Command + /// + /// Masks client from announcements and online admin list + /// + public class MaskCommand : Command { - public CMask() : - base("mask", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_DESC"], "hide", EFClient.Permission.Moderator, false) - { } + public MaskCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "mask"; + Description = _translationLookup["COMMANDS_MASK_DESC"]; + Alias = "hide"; + Permission = EFClient.Permission.Moderator; + RequiresTarget = false; + } public override async Task ExecuteAsync(GameEvent E) { if (E.Origin.Masked) { E.Origin.Masked = false; - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_OFF"]); + E.Origin.Tell(_translationLookup["COMMANDS_MASK_OFF"]); } else { E.Origin.Masked = true; - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_ON"]); + E.Origin.Tell(_translationLookup["COMMANDS_MASK_ON"]); } await E.Owner.Manager.GetClientService().Update(E.Origin); } } - public class CListBanInfo : Command + /// + /// Lists ban information for given client + /// + public class ListBanInfoCommand : Command { - public CListBanInfo() : - base("baninfo", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_DESC"], "bi", EFClient.Permission.Moderator, true, new CommandArgument[] + public ListBanInfoCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "baninfo"; + Description = _translationLookup["COMMANDS_BANINFO_DESC"]; + Alias = "bi"; + Permission = Permission.Moderator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -962,35 +1215,44 @@ namespace SharedLibraryCore.Commands if (penalty == null) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_NONE"]); + E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_NONE"]); return; } if (penalty.Type == EFPenalty.PenaltyType.Ban) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense)); + E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense)); } else { string remainingTime = (penalty.Expires.Value - DateTime.UtcNow).TimeSpanText(); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_TB_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense, remainingTime)); + E.Origin.Tell(_translationLookup["COMMANDS_BANINFO_TB_SUCCESS"].FormatExt(E.Target.Name, penalty.Offense, remainingTime)); } } } - public class CListAlias : Command + /// + /// Lists alises of specified client + /// + public class ListAliasesCommand : Command { - public CListAlias() : - base("alias", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_DESC"], "known", EFClient.Permission.Moderator, true, new CommandArgument[] + public ListAliasesCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "alias"; + Description = _translationLookup["COMMANDS_ALIAS_DESC"]; + Alias = "known"; + Permission = EFClient.Permission.Moderator; + RequiresTarget = true; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = true, - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = true, + } + }; + } public override Task ExecuteAsync(GameEvent E) { @@ -1000,12 +1262,12 @@ namespace SharedLibraryCore.Commands E.Origin.Tell($"[^3{E.Target}^7]"); - message.Append($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_ALIASES"]}: "); + message.Append($"{_translationLookup["COMMANDS_ALIAS_ALIASES"]}: "); message.Append(String.Join(" | ", names)); E.Origin.Tell(message.ToString()); message.Clear(); - message.Append($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_IPS"]}: "); + message.Append($"{_translationLookup["COMMANDS_ALIAS_IPS"]}: "); message.Append(String.Join(" | ", IPs)); E.Origin.Tell(message.ToString()); @@ -1013,18 +1275,27 @@ namespace SharedLibraryCore.Commands } } - public class CExecuteRCON : Command + /// + /// Executes RCon command + /// + public class ExecuteRConCommand : Command { - public CExecuteRCON() : - base("rcon", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_DESC"], "rcon", EFClient.Permission.Owner, false, new CommandArgument[] + public ExecuteRConCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "rcon"; + Description = _translationLookup["COMMANDS_RCON_DESC"]; + Alias = "rcon"; + Permission = Permission.Owner; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_COMMANDS"], - Required = true - } - }) - { } + Name = _translationLookup["COMMANDS_ARGS_COMMANDS"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -1036,52 +1307,78 @@ namespace SharedLibraryCore.Commands if (Response.Length == 0) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_RCON_SUCCESS"]); } } } - public class CPlugins : Command + /// + /// Lists the loaded plugins + /// + public class ListPluginsCommand : Command { - public CPlugins() : - base("plugins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_DESC"], "p", EFClient.Permission.Administrator, false) - { } + public ListPluginsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "plugins"; + Description = _translationLookup["COMMANDS_PLUGINS_DESC"]; + Alias = "p"; + Permission = Permission.Administrator; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_LOADED"]); + E.Origin.Tell(_translationLookup["COMMANDS_PLUGINS_LOADED"]); foreach (var P in Plugins.PluginImporter.ActivePlugins) { - E.Origin.Tell(String.Format("^3{0} ^7[v^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author)); + E.Origin.Tell(string.Format("^3{0} ^7[v^3{1}^7] by ^5{2}^7", P.Name, P.Version, P.Author)); } return Task.CompletedTask; } } - public class CIP : Command + /// + /// Lists external IP + /// + public class ListExternalIPCommand : Command { - public CIP() : - base("getexternalip", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_DESC"], "ip", EFClient.Permission.User, false) - { } + public ListExternalIPCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "getexternalip"; + Description = _translationLookup["COMMANDS_IP_DESC"]; + Alias = "ip"; + Permission = Permission.User; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_SUCCESS"].FormatExt(E.Origin.IPAddressString)); + E.Origin.Tell(_translationLookup["COMMANDS_IP_SUCCESS"].FormatExt(E.Origin.IPAddressString)); return Task.CompletedTask; } } - public class CPruneAdmins : Command + /// + /// Prunes inactive privileged clients + /// + public class PruneAdminsCommand : Command { - public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_DESC"], "pa", EFClient.Permission.Owner, false, new CommandArgument[] + public PruneAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { - new CommandArgument() + Name = "prune"; + Description = _translationLookup["COMMANDS_PRUNE_DESC"]; + Alias = "pa"; + Permission = Permission.Owner; + RequiresTarget = false; + Arguments = new[] { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_INACTIVE"], - Required = false - } - }) - { } + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_INACTIVE"], + Required = false + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -1091,7 +1388,7 @@ namespace SharedLibraryCore.Commands { if (E.Data.Length > 0) { - inactiveDays = Int32.Parse(E.Data); + inactiveDays = int.Parse(E.Data); if (inactiveDays < 1) { throw new FormatException(); @@ -1101,7 +1398,7 @@ namespace SharedLibraryCore.Commands catch (FormatException) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_FAIL"]); + E.Origin.Tell(_translationLookup["COMMANDS_PRUNE_FAIL"]); return; } @@ -1112,33 +1409,44 @@ namespace SharedLibraryCore.Commands { var lastActive = DateTime.UtcNow.AddDays(-inactiveDays); inactiveUsers = await context.Clients - .Where(c => c.Level > EFClient.Permission.Flagged && c.Level <= EFClient.Permission.Moderator) + .Where(c => c.Level > Permission.Flagged && c.Level <= Permission.Moderator) .Where(c => c.LastConnection < lastActive) .ToListAsync(); inactiveUsers.ForEach(c => c.SetLevel(Permission.User, E.Origin)); await context.SaveChangesAsync(); } - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_SUCCESS"].FormatExt(inactiveUsers.Count)); + E.Origin.Tell(_translationLookup["COMMANDS_PRUNE_SUCCESS"].FormatExt(inactiveUsers.Count)); } } - public class CSetPassword : Command + + /// + /// Sets login password + /// + public class SetPasswordCommand : Command { - public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETPASSWORD_DESC"], "sp", EFClient.Permission.Moderator, false, new CommandArgument[] + public SetPasswordCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "setpassword"; + Description = _translationLookup["COMMANDS_SETPASSWORD_DESC"]; + Alias = "sp"; + Permission = Permission.Moderator; + RequiresTarget = false; + Arguments = new[] { new CommandArgument() { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PASSWORD"], + Name = _translationLookup["COMMANDS_ARGS_PASSWORD"], Required = true } - }) - { } + }; + } public override async Task ExecuteAsync(GameEvent E) { if (E.Data.Length < 5) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PASSWORD_FAIL"]); + E.Origin.Tell(_translationLookup["COMMANDS_PASSWORD_FAIL"]); return; } @@ -1148,104 +1456,32 @@ namespace SharedLibraryCore.Commands E.Origin.PasswordSalt = hashedPassword[1]; await E.Owner.Manager.GetClientService().Update(E.Origin); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PASSWORD_SUCCESS"]); + E.Origin.Tell(_translationLookup["COMMANDS_PASSWORD_SUCCESS"]); } } - public class CKillServer : Command + /// + /// Gets the ping of a client + /// + public class GetClientPingCommand : Command { - public CKillServer() : base("killserver", "kill the game server", "kill", EFClient.Permission.Administrator, false) + public GetClientPingCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { + Name = "ping"; + Description = _translationLookup["COMMANDS_PING_DESC"]; + Alias = "pi"; + Permission = Permission.User; + RequiresTarget = false; + Arguments = new[] + { + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_PLAYER"], + Required = false + } + }; } - public override async Task ExecuteAsync(GameEvent E) - { - if (E.Owner.ServerConfig.GameLogServerUrl != null) - { - using (var wc = new WebClient()) - { - E.Owner.RestartRequested = true; - var response = await wc.DownloadStringTaskAsync(new Uri($"{E.Owner.ServerConfig.GameLogServerUrl}/restart")); - } - } - - else - { - var gameserverProcesses = System.Diagnostics.Process.GetProcessesByName("iw4x"); - - System.Diagnostics.Process currentProcess = null; - - foreach (var p in gameserverProcesses) - { - string cmdLine = Utilities.GetCommandLine(p.Id); - - var regex = Regex.Match(cmdLine, @".*((?:\+set|\+) net_port) +([0-9]+).*"); - - if (regex.Success && Int32.Parse(regex.Groups[2].Value) == E.Owner.Port) - { - currentProcess = p; - } - } - - - if (currentProcess == null) - { - E.Origin.Tell("Could not find running/stalled instance of IW4x"); - } - - else - { - // attempt to kill it natively - try - { - if (!E.Owner.Throttled) - { -#if !DEBUG - await E.Owner.ExecuteCommandAsync("quit"); -#endif - } - } - - catch (Exceptions.NetworkException) - { - E.Origin.Tell("Unable to cleanly shutdown server, forcing"); - } - - if (!currentProcess.HasExited) - { - try - { - currentProcess.Kill(); - E.Origin.Tell("Successfully killed server process"); - } - catch (Exception e) - { - E.Origin.Tell("Could not kill server process"); - E.Owner.Logger.WriteDebug("Unable to kill process"); - E.Owner.Logger.WriteDebug($"Exception: {e.Message}"); - return; - } - } - } - - return; - } - } - } - - - public class CPing : Command - { - public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_DESC"], "pi", EFClient.Permission.User, false, new CommandArgument[] - { - new CommandArgument() - { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_PLAYER"], - Required = false - } - }) - { } - public override Task ExecuteAsync(GameEvent E) { if (E.Target == null) @@ -1255,28 +1491,38 @@ namespace SharedLibraryCore.Commands if (E.Target == null) { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_SELF"].FormatExt(E.Origin.Ping)); + E.Origin.Tell(_translationLookup["COMMANDS_PING_SELF"].FormatExt(E.Origin.Ping)); } else { - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_TARGET"].FormatExt(E.Target.Name, E.Target.Ping)); + E.Origin.Tell(_translationLookup["COMMANDS_PING_TARGET"].FormatExt(E.Target.Name, E.Target.Ping)); } return Task.CompletedTask; } } - public class CSetGravatar : Command + /// + /// Sets the email for gravatar in webfront + /// + public class SetGravatarCommand : Command { - public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", EFClient.Permission.User, false, new CommandArgument[] + public SetGravatarCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) { - new CommandArgument() + Name = "setgravatar"; + Description = _translationLookup["COMMANDS_GRAVATAR_DESC"]; + Alias = "sg"; + Permission = Permission.User; + RequiresTarget = false; + Arguments = new[] { - Name = Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ARGS_GRAVATAR"], - Required = true - } - }) - { } + new CommandArgument() + { + Name = _translationLookup["COMMANDS_ARGS_GRAVATAR"], + Required = true + } + }; + } public override async Task ExecuteAsync(GameEvent E) { @@ -1289,17 +1535,25 @@ namespace SharedLibraryCore.Commands await metaSvc.AddPersistentMeta("GravatarEmail", gravatarEmail, E.Origin); } - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_SUCCESS_NEW"]); + E.Origin.Tell(_translationLookup["COMMANDS_GRAVATAR_SUCCESS_NEW"]); } } /// /// Retrieves the next map in rotation /// - public class CNextMap : Command + public class NextMapCommand : Command { - public CNextMap() : base("nextmap", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_DESC"], "nm", EFClient.Permission.User, false) { } - public static async Task GetNextMap(Server s) + public NextMapCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + { + Name = "nextmap"; + Description = _translationLookup["COMMANDS_NEXTMAP_DESC"]; + Alias = "nm"; + Permission = EFClient.Permission.User; + RequiresTarget = false; + } + + public static async Task GetNextMap(Server s, ITranslationLookup lookup) { string mapRotation = (await s.GetDvarAsync("sv_mapRotation")).Value?.ToLower() ?? ""; var regexMatches = Regex.Matches(mapRotation, @"((?:gametype|exec) +(?:([a-z]{1,4})(?:.cfg)?))? *map ([a-z|_|\d]+)", RegexOptions.IgnoreCase).ToList(); @@ -1312,13 +1566,13 @@ namespace SharedLibraryCore.Commands // no maprotation at all if (regexMatches.Count() == 0) { - return Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(s.CurrentMap.Alias, Utilities.GetLocalizedGametype(s.Gametype)); + return lookup["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(s.CurrentMap.Alias, Utilities.GetLocalizedGametype(s.Gametype)); } // the current map is not in rotation if (currentMap.Count() == 0) { - return Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_NOT_IN_ROTATION"]; + return lookup["COMMANDS_NEXTMAP_NOT_IN_ROTATION"]; } // there's duplicate maps in rotation @@ -1348,12 +1602,12 @@ namespace SharedLibraryCore.Commands Utilities.GetLocalizedGametype(s.Gametype) : Utilities.GetLocalizedGametype(nextMapMatch.Groups[2].ToString()); - return Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(nextMap.Alias, nextGametype); + return lookup["COMMANDS_NEXTMAP_SUCCESS"].FormatExt(nextMap.Alias, nextGametype); } public override async Task ExecuteAsync(GameEvent E) { - E.Origin.Tell(await GetNextMap(E.Owner)); + E.Origin.Tell(await GetNextMap(E.Owner, _translationLookup)); } } } \ No newline at end of file diff --git a/SharedLibraryCore/Commands/RequestTokenCommand.cs b/SharedLibraryCore/Commands/RequestTokenCommand.cs index 6d0672eaf..62733bb80 100644 --- a/SharedLibraryCore/Commands/RequestTokenCommand.cs +++ b/SharedLibraryCore/Commands/RequestTokenCommand.cs @@ -1,18 +1,28 @@ -using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; using System.Threading.Tasks; namespace SharedLibraryCore.Commands { + /// + /// Generates a token for use in webfront login + /// public class RequestTokenCommand : Command { - public RequestTokenCommand() : - base("requesttoken", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GENERATETOKEN_DESC"], "rt", EFClient.Permission.Trusted, false) - { } + public RequestTokenCommand(CommandConfiguration config, ITranslationLookup lookup) : base(config, lookup) + { + Name = "requesttoken"; + Description = lookup["COMMANDS_GENERATETOKEN_DESC"]; + Alias = "rt"; + Permission = EFClient.Permission.Trusted; + RequiresTarget = false; + } public override Task ExecuteAsync(GameEvent E) { var state = E.Owner.Manager.TokenAuthenticator.GenerateNextToken(E.Origin.NetworkId); - E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GENERATETOKEN_SUCCESS"], state.Token, $"{state.RemainingTime} {Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_MINUTES"]}", E.Origin.ClientId)); + E.Origin.Tell(string.Format(_translationLookup["COMMANDS_GENERATETOKEN_SUCCESS"], state.Token, $"{state.RemainingTime} {_translationLookup["GLOBAL_MINUTES"]}", E.Origin.ClientId)); return Task.CompletedTask; } diff --git a/SharedLibraryCore/Commands/UnlinkClientCommand.cs b/SharedLibraryCore/Commands/UnlinkClientCommand.cs index 326bd0e4d..b81625e67 100644 --- a/SharedLibraryCore/Commands/UnlinkClientCommand.cs +++ b/SharedLibraryCore/Commands/UnlinkClientCommand.cs @@ -1,4 +1,6 @@ -using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Interfaces; using System.Threading.Tasks; namespace SharedLibraryCore.Commands @@ -12,14 +14,19 @@ namespace SharedLibraryCore.Commands /// public class UnlinkClientCommand : Command { - public UnlinkClientCommand() : - base("unlinkclient", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNLINK_CLIENT_DESC"], "uc", EFClient.Permission.Administrator, true) - { } + public UnlinkClientCommand(CommandConfiguration config, ITranslationLookup lookup) : base(config, lookup) + { + Name = "unlinkclient"; + Description = lookup["COMMANDS_UNLINK_CLIENT_DESC"]; + Alias = "uc"; + Permission = EFClient.Permission.Administrator; + RequiresTarget = true; + } public override async Task ExecuteAsync(GameEvent E) { await E.Owner.Manager.GetClientService().UnlinkClient(E.Target.ClientId); - E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNLINK_CLIENT_SUCCESS"].FormatExt(E.Target)); + E.Origin.Tell(_translationLookup["COMMANDS_UNLINK_CLIENT_SUCCESS"].FormatExt(E.Target)); } } } diff --git a/SharedLibraryCore/Configuration/CommandConfiguration.cs b/SharedLibraryCore/Configuration/CommandConfiguration.cs new file mode 100644 index 000000000..f8c5fa5e1 --- /dev/null +++ b/SharedLibraryCore/Configuration/CommandConfiguration.cs @@ -0,0 +1,24 @@ +using SharedLibraryCore.Interfaces; +using System; +using System.Collections.Generic; + +namespace SharedLibraryCore.Configuration +{ + /// + /// Basic command configuration + /// + public class CommandConfiguration : IBaseConfiguration + { + /// + /// Dict of command class names mapped to configurable properties + /// + public Dictionary Commands { get; set; } = new Dictionary(); + + public IBaseConfiguration Generate() + { + throw new NotImplementedException(); + } + + public string Name() => nameof(CommandConfiguration); + } +} diff --git a/SharedLibraryCore/Configuration/CommandProperties.cs b/SharedLibraryCore/Configuration/CommandProperties.cs new file mode 100644 index 000000000..8271a3683 --- /dev/null +++ b/SharedLibraryCore/Configuration/CommandProperties.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json.Converters; +using System.Text.Json.Serialization; +using static SharedLibraryCore.Database.Models.EFClient; + +namespace SharedLibraryCore.Configuration +{ + /// + /// Config driven command properties + /// + public class CommandProperties + { + /// + /// Specifies the command name + /// + public string Name { get; set; } + + /// + /// Alias of this command + /// + public string Alias { get; set; } + + /// + /// Specifies the minimum permission level needed to execute the + /// + [JsonConverter(typeof(StringEnumConverter))] + public Permission MinimumPermission { get; set; } + } +} diff --git a/SharedLibraryCore/Interfaces/IManagerCommand.cs b/SharedLibraryCore/Interfaces/IManagerCommand.cs new file mode 100644 index 000000000..cdf920c14 --- /dev/null +++ b/SharedLibraryCore/Interfaces/IManagerCommand.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using static SharedLibraryCore.Database.Models.EFClient; + +namespace SharedLibraryCore.Interfaces +{ + /// + /// Defines the basic properties of a command + /// + public interface IManagerCommand + { + /// + /// Executes the command + /// + /// event corresponding to the command + /// + Task ExecuteAsync(GameEvent gameEvent); + + /// + /// Name of the command + /// + string Name { get; } + + /// + /// Description of the command + /// + string Description { get; } + + /// + /// Alternative name of the command + /// + string Alias { get; } + + /// + /// Minimum permission required to execute the command + /// + Permission Permission { get; } + } +} diff --git a/SharedLibraryCore/Interfaces/ITranslationLookup.cs b/SharedLibraryCore/Interfaces/ITranslationLookup.cs new file mode 100644 index 000000000..4c3d2f95b --- /dev/null +++ b/SharedLibraryCore/Interfaces/ITranslationLookup.cs @@ -0,0 +1,15 @@ +namespace SharedLibraryCore.Interfaces +{ + /// + /// Defines the translation lookup capabilities for DI + /// + public interface ITranslationLookup + { + /// + /// Allows indexing + /// + /// translation lookup key + /// + string this[string key] { get; } + } +} diff --git a/SharedLibraryCore/Localization/Layout.cs b/SharedLibraryCore/Localization/Layout.cs index ba07bbd8f..fd8460372 100644 --- a/SharedLibraryCore/Localization/Layout.cs +++ b/SharedLibraryCore/Localization/Layout.cs @@ -1,25 +1,23 @@ -using Newtonsoft.Json; -using System; +using SharedLibraryCore.Interfaces; using System.Collections.Generic; -using System.Text; namespace SharedLibraryCore.Localization { public class Layout { public string LocalizationName { get; set; } - public Index LocalizationIndex { get; set; } + public TranslationLookup LocalizationIndex { get; set; } public Layout(Dictionary set) { - LocalizationIndex = new Index() + LocalizationIndex = new TranslationLookup() { Set = set }; } } - public class Index + public class TranslationLookup : ITranslationLookup { public Dictionary Set { get; set; }