add configurable command and broadcast command prefix for issue #149
This commit is contained in:
parent
6155493181
commit
04a95aa58a
@ -81,7 +81,7 @@ namespace IW4MAdmin.Application
|
||||
ConfigHandler = appConfigHandler;
|
||||
StartTime = DateTime.UtcNow;
|
||||
PageList = new PageList();
|
||||
AdditionalEventParsers = new List<IEventParser>() { new BaseEventParser(parserRegexFactory, logger) };
|
||||
AdditionalEventParsers = new List<IEventParser>() { new BaseEventParser(parserRegexFactory, logger, appConfigHandler.Configuration()) };
|
||||
AdditionalRConParsers = new List<IRConParser>() { new BaseRConParser(parserRegexFactory) };
|
||||
TokenAuthenticator = new TokenAuthentication();
|
||||
_logger = logger;
|
||||
@ -432,6 +432,11 @@ namespace IW4MAdmin.Application
|
||||
commandsToAddToConfig.AddRange(unsavedCommands);
|
||||
}
|
||||
|
||||
// this is because I want to store the command prefix in IW4MAdminSettings, but can't easily
|
||||
// inject it to all the places that need it
|
||||
cmdConfig.CommandPrefix = config.CommandPrefix;
|
||||
cmdConfig.BroadcastCommandPrefix = config.BroadcastCommandPrefix;
|
||||
|
||||
foreach (var cmd in commandsToAddToConfig)
|
||||
{
|
||||
cmdConfig.Commands.Add(cmd.CommandConfigNameForType(),
|
||||
@ -729,7 +734,7 @@ namespace IW4MAdmin.Application
|
||||
|
||||
public IEventParser GenerateDynamicEventParser(string name)
|
||||
{
|
||||
return new DynamicEventParser(_parserRegexFactory, _logger)
|
||||
return new DynamicEventParser(_parserRegexFactory, _logger, ConfigHandler.Configuration())
|
||||
{
|
||||
Name = name
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
@ -12,11 +13,13 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
private readonly Dictionary<string, (string, Func<string, IEventParserConfiguration, GameEvent, GameEvent>)> _customEventRegistrations;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ApplicationConfiguration _appConfig;
|
||||
|
||||
public BaseEventParser(IParserRegexFactory parserRegexFactory, ILogger logger)
|
||||
public BaseEventParser(IParserRegexFactory parserRegexFactory, ILogger logger, ApplicationConfiguration appConfig)
|
||||
{
|
||||
_customEventRegistrations = new Dictionary<string, (string, Func<string, IEventParserConfiguration, GameEvent, GameEvent>)>();
|
||||
_logger = logger;
|
||||
_appConfig = appConfig;
|
||||
|
||||
Configuration = new DynamicEventParserConfiguration(parserRegexFactory)
|
||||
{
|
||||
@ -128,7 +131,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
int clientNumber = int.Parse(matchResult.Values[Configuration.Say.GroupMapping[ParserRegex.GroupType.OriginClientNumber]]);
|
||||
|
||||
// todo: these need to defined outside of here
|
||||
if (message[0] == '!' || message[0] == '@')
|
||||
if (message.StartsWith(_appConfig.CommandPrefix) || message.StartsWith(_appConfig.BroadcastCommandPrefix))
|
||||
{
|
||||
return new GameEvent()
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
|
||||
namespace IW4MAdmin.Application.EventParsers
|
||||
{
|
||||
@ -8,7 +9,7 @@ namespace IW4MAdmin.Application.EventParsers
|
||||
/// </summary>
|
||||
sealed internal class DynamicEventParser : BaseEventParser
|
||||
{
|
||||
public DynamicEventParser(IParserRegexFactory parserRegexFactory, ILogger logger) : base(parserRegexFactory, logger)
|
||||
public DynamicEventParser(IParserRegexFactory parserRegexFactory, ILogger logger, ApplicationConfiguration appConfig) : base(parserRegexFactory, logger, appConfig)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ namespace IW4MAdmin
|
||||
{
|
||||
try
|
||||
{
|
||||
C = await SharedLibraryCore.Commands.CommandProcessing.ValidateCommand(E);
|
||||
C = await SharedLibraryCore.Commands.CommandProcessing.ValidateCommand(E, Manager.GetApplicationSettings().Configuration());
|
||||
}
|
||||
|
||||
catch (CommandException e)
|
||||
|
@ -59,7 +59,7 @@ namespace SharedLibraryCore
|
||||
/// <summary>
|
||||
/// Helper property to provide the syntax of the command
|
||||
/// </summary>
|
||||
public string Syntax => $"{_translationLookup["COMMAND_HELP_SYNTAX"]} !{Alias} {string.Join(" ", Arguments.Select(a => $"<{(a.Required ? "" : _translationLookup["COMMAND_HELP_OPTIONAL"] + " ")}{a.Name}>"))}";
|
||||
public string Syntax => $"{_translationLookup["COMMAND_HELP_SYNTAX"]} {_config.CommandPrefix}{Alias} {string.Join(" ", Arguments.Select(a => $"<{(a.Required ? "" : _translationLookup["COMMAND_HELP_OPTIONAL"] + " ")}{a.Name}>"))}";
|
||||
|
||||
/// <summary>
|
||||
/// Alternate name for this command to be executed by
|
||||
@ -123,5 +123,7 @@ namespace SharedLibraryCore
|
||||
/// indicates if this command allows impersonation (run as)
|
||||
/// </summary>
|
||||
public bool AllowImpersonation { get; set; }
|
||||
|
||||
public bool IsBroadcast { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -10,12 +11,14 @@ namespace SharedLibraryCore.Commands
|
||||
{
|
||||
public class CommandProcessing
|
||||
{
|
||||
public static async Task<Command> ValidateCommand(GameEvent E)
|
||||
public static async Task<Command> ValidateCommand(GameEvent E, ApplicationConfiguration appConfig)
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
var Manager = E.Owner.Manager;
|
||||
bool isBroadcast = E.Data.StartsWith(appConfig.BroadcastCommandPrefix);
|
||||
int prefixLength = isBroadcast ? appConfig.BroadcastCommandPrefix.Length : appConfig.CommandPrefix.Length;
|
||||
|
||||
string CommandString = E.Data.Substring(1, E.Data.Length - 1).Split(' ')[0];
|
||||
string CommandString = E.Data.Substring(prefixLength, E.Data.Length - prefixLength).Split(' ')[0];
|
||||
E.Message = E.Data;
|
||||
|
||||
Command C = null;
|
||||
@ -34,6 +37,8 @@ namespace SharedLibraryCore.Commands
|
||||
throw new CommandException($"{E.Origin} entered unknown command \"{CommandString}\"");
|
||||
}
|
||||
|
||||
C.IsBroadcast = isBroadcast;
|
||||
|
||||
if (!C.AllowImpersonation && E.ImpersonationOrigin != null)
|
||||
{
|
||||
E.ImpersonationOrigin.Tell(loc["COMMANDS_RUN_AS_FAIL"]);
|
||||
|
@ -773,6 +773,8 @@ namespace SharedLibraryCore.Commands
|
||||
/// </summary>
|
||||
public class ListAdminsCommand : Command
|
||||
{
|
||||
private readonly CommandConfiguration _config;
|
||||
|
||||
public ListAdminsCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup)
|
||||
{
|
||||
Name = "admins";
|
||||
@ -780,6 +782,8 @@ namespace SharedLibraryCore.Commands
|
||||
Alias = "a";
|
||||
Permission = Permission.User;
|
||||
RequiresTarget = false;
|
||||
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public static string OnlineAdmins(Server S, ITranslationLookup lookup)
|
||||
@ -798,7 +802,7 @@ namespace SharedLibraryCore.Commands
|
||||
{
|
||||
foreach (string line in OnlineAdmins(E.Owner, _translationLookup).Split(Environment.NewLine))
|
||||
{
|
||||
var _ = E.Message.IsBroadcastCommand() ? E.Owner.Broadcast(line) : E.Origin.Tell(line);
|
||||
var _ = E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix) ? E.Owner.Broadcast(line) : E.Origin.Tell(line);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
@ -903,6 +907,8 @@ namespace SharedLibraryCore.Commands
|
||||
/// </summary>
|
||||
public class ListRulesCommands : Command
|
||||
{
|
||||
private readonly CommandConfiguration _config;
|
||||
|
||||
public ListRulesCommands(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup)
|
||||
{
|
||||
Name = "rules";
|
||||
@ -910,6 +916,8 @@ namespace SharedLibraryCore.Commands
|
||||
Alias = "r";
|
||||
Permission = Permission.User;
|
||||
RequiresTarget = false;
|
||||
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public override Task ExecuteAsync(GameEvent E)
|
||||
@ -917,7 +925,7 @@ namespace SharedLibraryCore.Commands
|
||||
if (E.Owner.Manager.GetApplicationSettings().Configuration().GlobalRules?.Length < 1 &&
|
||||
E.Owner.ServerConfig.Rules?.Length < 1)
|
||||
{
|
||||
var _ = E.Message.IsBroadcastCommand() ?
|
||||
var _ = E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix) ?
|
||||
E.Owner.Broadcast(_translationLookup["COMMANDS_RULES_NONE"]) :
|
||||
E.Origin.Tell(_translationLookup["COMMANDS_RULES_NONE"]);
|
||||
}
|
||||
@ -933,7 +941,7 @@ namespace SharedLibraryCore.Commands
|
||||
|
||||
foreach (string r in rules)
|
||||
{
|
||||
var _ = E.Message.IsBroadcastCommand() ? E.Owner.Broadcast($"- {r}") : E.Origin.Tell($"- {r}");
|
||||
var _ = E.Message.IsBroadcastCommand(_config.BroadcastCommandPrefix) ? E.Owner.Broadcast($"- {r}") : E.Origin.Tell($"- {r}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,12 @@ namespace SharedLibraryCore.Configuration
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_CUSTOM_LOCALE")]
|
||||
public string CustomLocale { get; set; }
|
||||
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_COMMAND_PREFIX")]
|
||||
public string CommandPrefix { get; set; } = "!";
|
||||
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_BROADCAST_COMMAND_PREFIX")]
|
||||
public string BroadcastCommandPrefix { get; set; } = "@";
|
||||
|
||||
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_DB_PROVIDER")]
|
||||
public string DatabaseProvider { get; set; } = "sqlite";
|
||||
[ConfigurationOptional]
|
||||
|
@ -1,6 +1,7 @@
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharedLibraryCore.Configuration
|
||||
{
|
||||
@ -14,6 +15,18 @@ namespace SharedLibraryCore.Configuration
|
||||
/// </summary>
|
||||
public Dictionary<string, CommandProperties> Commands { get; set; } = new Dictionary<string, CommandProperties>();
|
||||
|
||||
/// <summary>
|
||||
/// prefix indicated the chat message is a command
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string CommandPrefix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// prefix indicating that the chat message is a broadcast command
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public string BroadcastCommandPrefix { get; set; }
|
||||
|
||||
public IBaseConfiguration Generate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
@ -64,13 +64,19 @@ namespace SharedLibraryCore.Configuration.Validation
|
||||
RuleFor(_app => _app.GlobalRules)
|
||||
.NotNull();
|
||||
|
||||
RuleForEach(_app => _app.Servers)
|
||||
.NotEmpty()
|
||||
.SetValidator(new ServerConfigurationValidator());
|
||||
|
||||
RuleFor(_app => _app.MasterUrl)
|
||||
.NotNull()
|
||||
.Must(_url => _url != null && _url.Scheme == Uri.UriSchemeHttp);
|
||||
|
||||
RuleFor(_app => _app.CommandPrefix)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(_app => _app.BroadcastCommandPrefix)
|
||||
.NotEmpty();
|
||||
|
||||
RuleForEach(_app => _app.Servers)
|
||||
.NotEmpty()
|
||||
.SetValidator(new ServerConfigurationValidator());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,5 +49,10 @@ namespace SharedLibraryCore.Interfaces
|
||||
/// Indicates if the commands can be run as another client
|
||||
/// </summary>
|
||||
bool AllowImpersonation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the command result should be broadcasted to all clients
|
||||
/// </summary>
|
||||
bool IsBroadcast { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ namespace SharedLibraryCore.Database.Models
|
||||
.DisallowedClientNames
|
||||
?.Any(_name => Regex.IsMatch(Name, _name)) ?? false)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is generic");
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is not allowed");
|
||||
Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
@ -235,9 +235,14 @@ namespace SharedLibraryCore
|
||||
return str;
|
||||
}
|
||||
|
||||
public static bool IsBroadcastCommand(this string str)
|
||||
public static bool IsBroadcastCommand(this string str, string broadcastCommandPrefix)
|
||||
{
|
||||
return str[0] == '@';
|
||||
return str.StartsWith(broadcastCommandPrefix);
|
||||
}
|
||||
|
||||
public static IManagerCommand AsCommand(this GameEvent gameEvent)
|
||||
{
|
||||
return gameEvent.Extra as IManagerCommand;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -22,6 +22,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Files\GameEvent.Command.CustomPrefix.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Files\GameEvents.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using static SharedLibraryCore.GameEvent;
|
||||
@ -18,17 +19,20 @@ namespace ApplicationTests
|
||||
private EventLogTest eventLogData;
|
||||
private IServiceProvider serviceProvider;
|
||||
private ILogger fakeLogger;
|
||||
private ApplicationConfiguration appConfig;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
eventLogData = JsonConvert.DeserializeObject<EventLogTest>(System.IO.File.ReadAllText("Files/GameEvents.json"));
|
||||
appConfig = ConfigurationGenerators.CreateApplicationConfiguration();
|
||||
|
||||
fakeLogger = A.Fake<ILogger>();
|
||||
serviceProvider = new ServiceCollection()
|
||||
.AddSingleton<BaseEventParser>()
|
||||
.AddTransient<IParserPatternMatcher, ParserPatternMatcher>()
|
||||
.AddSingleton<IParserRegexFactory, ParserRegexFactory>()
|
||||
.AddSingleton(appConfig)
|
||||
.AddSingleton(fakeLogger)
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
@ -38,22 +42,6 @@ namespace ApplicationTests
|
||||
{
|
||||
var eventParser = serviceProvider.GetService<BaseEventParser>();
|
||||
|
||||
void AssertMatch(GameEvent src, LogEvent expected)
|
||||
{
|
||||
Assert.AreEqual(expected.ExpectedEventType, src.Type);
|
||||
Assert.AreEqual(expected.ExpectedData, src.Data);
|
||||
Assert.AreEqual(expected.ExpectedMessage, src.Message);
|
||||
Assert.AreEqual(expected.ExpectedTime, src.GameTime);
|
||||
|
||||
//Assert.AreEqual(expected.ExpectedOriginClientName, src.Origin?.Name);
|
||||
Assert.AreEqual(expected.ExpectedOriginClientNumber, src.Origin?.ClientNumber);
|
||||
Assert.AreEqual(expected.ExpectedOriginNetworkId, src.Origin?.NetworkId.ToString("X"));
|
||||
|
||||
//Assert.AreEqual(expected.ExpectedTargetClientName, src.Target?.Name);
|
||||
Assert.AreEqual(expected.ExpectedTargetClientNumber, src.Target?.ClientNumber);
|
||||
Assert.AreEqual(expected.ExpectedTargetNetworkId, src.Target?.NetworkId.ToString("X"));
|
||||
}
|
||||
|
||||
foreach (var e in eventLogData.Events)
|
||||
{
|
||||
var parsedEvent = eventParser.GenerateGameEvent(e.EventLine);
|
||||
@ -109,5 +97,45 @@ namespace ApplicationTests
|
||||
A.CallTo(() => fakeLogger.WriteWarning(A<string>.Ignored))
|
||||
.MustHaveHappenedOnceExactly();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test_CustomCommandPrefix_Parses()
|
||||
{
|
||||
var eventParser = serviceProvider.GetService<BaseEventParser>();
|
||||
var commandData = JsonConvert.DeserializeObject<EventLogTest>(System.IO.File.ReadAllText("Files/GameEvent.Command.CustomPrefix.json"));
|
||||
appConfig.CommandPrefix = "^^";
|
||||
|
||||
var e = commandData.Events[0];
|
||||
var parsedEvent = eventParser.GenerateGameEvent(e.EventLine);
|
||||
AssertMatch(parsedEvent, e);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Test_CustomBroadcastCommandPrefix_Parses()
|
||||
{
|
||||
var eventParser = serviceProvider.GetService<BaseEventParser>();
|
||||
var commandData = JsonConvert.DeserializeObject<EventLogTest>(System.IO.File.ReadAllText("Files/GameEvent.Command.CustomPrefix.json"));
|
||||
appConfig.BroadcastCommandPrefix = "@@";
|
||||
|
||||
var e = commandData.Events[1];
|
||||
var parsedEvent = eventParser.GenerateGameEvent(e.EventLine);
|
||||
AssertMatch(parsedEvent, e);
|
||||
}
|
||||
|
||||
private static void AssertMatch(GameEvent src, LogEvent expected)
|
||||
{
|
||||
Assert.AreEqual(expected.ExpectedEventType, src.Type);
|
||||
Assert.AreEqual(expected.ExpectedData, src.Data);
|
||||
Assert.AreEqual(expected.ExpectedMessage, src.Message);
|
||||
Assert.AreEqual(expected.ExpectedTime, src.GameTime);
|
||||
|
||||
//Assert.AreEqual(expected.ExpectedOriginClientName, src.Origin?.Name);
|
||||
Assert.AreEqual(expected.ExpectedOriginClientNumber, src.Origin?.ClientNumber);
|
||||
Assert.AreEqual(expected.ExpectedOriginNetworkId, src.Origin?.NetworkId.ToString("X"));
|
||||
|
||||
//Assert.AreEqual(expected.ExpectedTargetClientName, src.Target?.Name);
|
||||
Assert.AreEqual(expected.ExpectedTargetClientNumber, src.Target?.ClientNumber);
|
||||
Assert.AreEqual(expected.ExpectedTargetNetworkId, src.Target?.NetworkId.ToString("X"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,8 @@ namespace ApplicationTests
|
||||
.Returns(new Command[]
|
||||
{
|
||||
new ImpersonatableCommand(cmdConfig, transLookup),
|
||||
new NonImpersonatableCommand(cmdConfig, transLookup)
|
||||
new NonImpersonatableCommand(cmdConfig, transLookup),
|
||||
new MockCommand(cmdConfig, transLookup)
|
||||
});
|
||||
|
||||
A.CallTo(() => manager.AddEvent(A<GameEvent>.Ignored))
|
||||
@ -519,5 +520,22 @@ namespace ApplicationTests
|
||||
Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PREFIX_PROCESSING
|
||||
[Test]
|
||||
public async Task Test_CommandProcessing_IsBroadcastCommand()
|
||||
{
|
||||
string broadcastPrefix = "@@";
|
||||
var config = ConfigurationGenerators.CreateApplicationConfiguration();
|
||||
config.BroadcastCommandPrefix = broadcastPrefix;
|
||||
var server = serviceProvider.GetRequiredService<IW4MServer>();
|
||||
|
||||
var cmd = EventGenerators.GenerateEvent(GameEvent.EventType.Command, $"{broadcastPrefix}{nameof(MockCommand)}", server);
|
||||
|
||||
var result = await CommandProcessing.ValidateCommand(cmd, config);
|
||||
Assert.AreEqual(nameof(MockCommand), result.Name);
|
||||
Assert.IsTrue(result.IsBroadcast);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"Events": [
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 12:34 say;AAA;1;Player;^^help",
|
||||
"ExpectedEventType": "Command",
|
||||
"ExpectedData": "^^help",
|
||||
"ExpectedMessage": "^^help",
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Player",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 754
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 12:34 say;AAA;1;Player;@@help",
|
||||
"ExpectedEventType": "Command",
|
||||
"ExpectedData": "@@help",
|
||||
"ExpectedMessage": "@@help",
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Player",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 754
|
||||
}
|
||||
]
|
||||
}
|
159
Tests/ApplicationTests/Files/GameEvents.json
Normal file
159
Tests/ApplicationTests/Files/GameEvents.json
Normal file
@ -0,0 +1,159 @@
|
||||
{
|
||||
"Events": [
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 12:34 say;AAA;1;Player;this is a test message",
|
||||
"ExpectedEventType": "Say",
|
||||
"ExpectedData": "this is a test message",
|
||||
"ExpectedMessage": "this is a test message",
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Player",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 754
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 12:34 sayteam;AAA;1;Player;this is a test team message",
|
||||
"ExpectedEventType": "Say",
|
||||
"ExpectedData": "this is a test team message",
|
||||
"ExpectedMessage": "this is a test team message",
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Player",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 754
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 12:34 say;AAA;1;Player;!help",
|
||||
"ExpectedEventType": "Command",
|
||||
"ExpectedData": "!help",
|
||||
"ExpectedMessage": "!help",
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Player",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 754
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "2824:03 K;BBB;6;axis;Snake;AAA;11;allies;Doctor;sa80_reflex_xmags_mp;55;MOD_HEAD_SHOT;head",
|
||||
"ExpectedEventType": "Kill",
|
||||
"ExpectedData": "K;BBB;6;axis;Snake;AAA;11;allies;Doctor;sa80_reflex_xmags_mp;55;MOD_HEAD_SHOT;head",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 11,
|
||||
"ExpectedOriginClientName": "Doctor",
|
||||
"ExpectedTargetNetworkId": "BBB",
|
||||
"ExpectedTargetClientNumber": 6,
|
||||
"ExpectedTargetClientName": "Snake",
|
||||
"ExpectedTime": 169443
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "6:44 K;AAA;0;allies;Player;;-1;world;;none;100;MOD_FALLING;none",
|
||||
"ExpectedEventType": "Kill",
|
||||
"ExpectedData": "K;AAA;0;allies;Player;;-1;world;;none;100;MOD_FALLING;none",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": "FFFFFFFFFFFFFFFF",
|
||||
"ExpectedOriginClientNumber": -1,
|
||||
"ExpectedOriginClientName": "",
|
||||
"ExpectedTargetNetworkId": "AAA",
|
||||
"ExpectedTargetClientNumber": 0,
|
||||
"ExpectedTargetClientName": "Player",
|
||||
"ExpectedTime": 404
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "2824:03 D;BBB;6;axis;Snake;AAA;11;allies;Doctor;sa80_reflex_xmags_mp;55;MOD_HEAD_SHOT;head",
|
||||
"ExpectedEventType": "Damage",
|
||||
"ExpectedData": "D;BBB;6;axis;Snake;AAA;11;allies;Doctor;sa80_reflex_xmags_mp;55;MOD_HEAD_SHOT;head",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 11,
|
||||
"ExpectedOriginClientName": "Doctor",
|
||||
"ExpectedTargetNetworkId": "BBB",
|
||||
"ExpectedTargetClientNumber": 6,
|
||||
"ExpectedTargetClientName": "Snake",
|
||||
"ExpectedTime": 169443
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "1:43 J;AAA;1;Doctor",
|
||||
"ExpectedEventType": "Preconnect",
|
||||
"ExpectedData": "J;AAA;1;Doctor",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Doctor",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 103
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "1344:54 Q;AAA;1;Cosmic Riptide",
|
||||
"ExpectedEventType": "Predisconnect",
|
||||
"ExpectedData": "Q;AAA;1;Cosmic Riptide",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": "AAA",
|
||||
"ExpectedOriginClientNumber": 1,
|
||||
"ExpectedOriginClientName": "Cosmic Riptide",
|
||||
"ExpectedTargetNetworkId": null,
|
||||
"ExpectedTargetClientNumber": null,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 80694
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": "75:44 ExitLevel: executed",
|
||||
"ExpectedEventType": "MapEnd",
|
||||
"ExpectedData": "ExitLevel: executed",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": 0,
|
||||
"ExpectedOriginClientNumber": -1,
|
||||
"ExpectedOriginClientName": null,
|
||||
"ExpectedTargetNetworkId": 0,
|
||||
"ExpectedTargetClientNumber": -1,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 4544
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 75:44 InitGame",
|
||||
"ExpectedEventType": "MapChange",
|
||||
"ExpectedData": "InitGame",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": 0,
|
||||
"ExpectedOriginClientNumber": -1,
|
||||
"ExpectedOriginClientName": null,
|
||||
"ExpectedTargetNetworkId": 0,
|
||||
"ExpectedTargetClientNumber": -1,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 4544
|
||||
},
|
||||
{
|
||||
"Game": "IW4",
|
||||
"EventLine": " 0:00 CustomLogLine",
|
||||
"ExpectedEventType": "Unknown",
|
||||
"ExpectedData": "CustomLogLine",
|
||||
"ExpectedMessage": null,
|
||||
"ExpectedOriginNetworkId": 0,
|
||||
"ExpectedOriginClientNumber": -1,
|
||||
"ExpectedOriginClientName": null,
|
||||
"ExpectedTargetNetworkId": 0,
|
||||
"ExpectedTargetClientNumber": -1,
|
||||
"ExpectedTargetClientName": null,
|
||||
"ExpectedTime": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
26
Tests/ApplicationTests/Fixtures/EventGenerators.cs
Normal file
26
Tests/ApplicationTests/Fixtures/EventGenerators.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using SharedLibraryCore;
|
||||
using System;
|
||||
|
||||
|
||||
namespace ApplicationTests.Fixtures
|
||||
{
|
||||
static class EventGenerators
|
||||
{
|
||||
public static GameEvent GenerateEvent(GameEvent.EventType type, string data, Server owner)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GameEvent.EventType.Command:
|
||||
return new GameEvent
|
||||
{
|
||||
Origin = ClientGenerators.CreateDatabaseClient(),
|
||||
Data = data,
|
||||
Message = data,
|
||||
Owner = owner
|
||||
};
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ApplicationTests.Mocks
|
||||
@ -33,4 +32,17 @@ namespace ApplicationTests.Mocks
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
class MockCommand : Command
|
||||
{
|
||||
public MockCommand(CommandConfiguration config, ITranslationLookup lookup) : base(config, lookup)
|
||||
{
|
||||
Name = nameof(MockCommand);
|
||||
}
|
||||
|
||||
public override Task ExecuteAsync(GameEvent E)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using IW4MAdmin;
|
||||
using IW4MAdmin.Application;
|
||||
using IW4MAdmin.Application.EventParsers;
|
||||
using NUnit.Framework;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@ -35,7 +36,7 @@ namespace ApplicationTests
|
||||
new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 },
|
||||
A.Fake<ITranslationLookup>(), A.Fake<IRConConnectionFactory>(), A.Fake<IGameLogReaderFactory>());
|
||||
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>());
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>(), A.Fake<ApplicationConfiguration>());
|
||||
parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer;
|
||||
|
||||
var log = System.IO.File.ReadAllLines("Files\\T6MapRotation.log");
|
||||
@ -61,7 +62,7 @@ namespace ApplicationTests
|
||||
new SharedLibraryCore.Configuration.ServerConfiguration() { IPAddress = "127.0.0.1", Port = 28960 },
|
||||
A.Fake<ITranslationLookup>(), A.Fake<IRConConnectionFactory>(), A.Fake<IGameLogReaderFactory>());
|
||||
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>());
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>(), A.Fake<ApplicationConfiguration>());
|
||||
parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer;
|
||||
|
||||
var log = System.IO.File.ReadAllLines("Files\\T6Game.log");
|
||||
|
@ -16,6 +16,7 @@ using ApplicationTests.Fixtures;
|
||||
using System.Threading.Tasks;
|
||||
using Stats.Helpers;
|
||||
using Stats.Dtos;
|
||||
using SharedLibraryCore.Configuration;
|
||||
|
||||
namespace ApplicationTests
|
||||
{
|
||||
@ -73,7 +74,7 @@ namespace ApplicationTests
|
||||
A.Fake<ITranslationLookup>(),
|
||||
A.Fake<IRConConnectionFactory>(), A.Fake<IGameLogReaderFactory>());
|
||||
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>());
|
||||
var parser = new BaseEventParser(A.Fake<IParserRegexFactory>(), A.Fake<ILogger>(), A.Fake<ApplicationConfiguration>());
|
||||
parser.Configuration.GuidNumberStyle = System.Globalization.NumberStyles.Integer;
|
||||
|
||||
var log = System.IO.File.ReadAllLines("Files\\T6GameStats.log");
|
||||
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using WebfrontCore.ViewModels;
|
||||
using static SharedLibraryCore.Database.Models.EFClient;
|
||||
@ -13,9 +14,11 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
public class ActionController : BaseController
|
||||
{
|
||||
private readonly ApplicationConfiguration _appConfig;
|
||||
|
||||
public ActionController(IManager manager) : base(manager)
|
||||
{
|
||||
|
||||
_appConfig = manager.GetApplicationSettings().Configuration();
|
||||
}
|
||||
|
||||
public IActionResult BanForm()
|
||||
@ -80,8 +83,8 @@ namespace WebfrontCore.Controllers
|
||||
}
|
||||
|
||||
string command = Duration == 6 ?
|
||||
$"!ban @{targetId} {Reason}" :
|
||||
$"!tempban @{targetId} {duration} {Reason}";
|
||||
$"{_appConfig.CommandPrefix}ban @{targetId} {Reason}" :
|
||||
$"{_appConfig.CommandPrefix}tempban @{targetId} {duration} {Reason}";
|
||||
|
||||
var server = Manager.GetServers().First();
|
||||
|
||||
@ -120,7 +123,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.EndPoint,
|
||||
command = $"!unban @{targetId} {Reason}"
|
||||
command = $"{_appConfig.CommandPrefix}unban @{targetId} {Reason}"
|
||||
}));
|
||||
}
|
||||
|
||||
@ -189,7 +192,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.EndPoint,
|
||||
command = $"!setlevel @{targetId} {level}"
|
||||
command = $"{_appConfig.CommandPrefix}setlevel @{targetId} {level}"
|
||||
}));
|
||||
}
|
||||
|
||||
@ -256,7 +259,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.EndPoint,
|
||||
command = $"!say {message}"
|
||||
command = $"{_appConfig.CommandPrefix}say {message}"
|
||||
}));
|
||||
}
|
||||
|
||||
@ -294,7 +297,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.EndPoint,
|
||||
command = $"!flag @{targetId} {reason}"
|
||||
command = $"{_appConfig.CommandPrefix}flag @{targetId} {reason}"
|
||||
}));
|
||||
}
|
||||
|
||||
@ -326,7 +329,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = server.EndPoint,
|
||||
command = $"!unflag @{targetId} {reason}"
|
||||
command = $"{_appConfig.CommandPrefix}unflag @{targetId} {reason}"
|
||||
}));
|
||||
}
|
||||
|
||||
@ -369,7 +372,7 @@ namespace WebfrontCore.Controllers
|
||||
return await Task.FromResult(RedirectToAction("ExecuteAsync", "Console", new
|
||||
{
|
||||
serverId = client.CurrentServer.EndPoint,
|
||||
command = $"!kick {client.ClientNumber} {reason}"
|
||||
command = $"{_appConfig.CommandPrefix}kick {client.ClientNumber} {reason}"
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SharedLibraryCore;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -11,9 +11,11 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
public class ConsoleController : BaseController
|
||||
{
|
||||
private readonly ApplicationConfiguration _appconfig;
|
||||
|
||||
public ConsoleController(IManager manager) : base(manager)
|
||||
{
|
||||
|
||||
_appconfig = manager.GetApplicationSettings().Configuration();
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
@ -50,7 +52,8 @@ namespace WebfrontCore.Controllers
|
||||
var remoteEvent = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Command,
|
||||
Data = command,
|
||||
Data = command.StartsWith(_appconfig.CommandPrefix) || command.StartsWith(_appconfig.BroadcastCommandPrefix) ?
|
||||
command : $"{_appconfig.CommandPrefix}{command}",
|
||||
Origin = client,
|
||||
Owner = server,
|
||||
IsRemote = true
|
||||
|
@ -61,6 +61,7 @@ namespace WebfrontCore.Controllers
|
||||
{
|
||||
ViewBag.IsFluid = true;
|
||||
ViewBag.Title = Localization["WEBFRONT_NAV_HELP"];
|
||||
ViewBag.CommandPrefix = Manager.GetApplicationSettings().Configuration().CommandPrefix;
|
||||
|
||||
// we don't need to the name of the shared library assembly
|
||||
var excludedAssembly = typeof(BaseController).Assembly;
|
||||
|
@ -26,7 +26,7 @@
|
||||
<td>@command.Alias</td>
|
||||
<td>@command.Description</td>
|
||||
<td>@command.RequiresTarget</td>
|
||||
<td>!@command.Syntax.Split('!')[1]</td>
|
||||
<td>@ViewBag.CommandPrefix@command.Syntax.Split(@ViewBag.CommandPrefix)[1]</td>
|
||||
<td>@command.Permission.ToLocalizedLevelName()</td>
|
||||
</tr>
|
||||
}
|
||||
@ -62,7 +62,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td scope="row" class="bg-primary">@loc["WEBFRONT_HELP_COMMAND_DESC_SYNTAX"]</td>
|
||||
<td class="bg-dark text-light">!@command.Syntax.Split('!')[1]</td>
|
||||
<td class="bg-dark text-light">@ViewBag.CommandPrefix@command.Syntax.Split(@ViewBag.CommandPrefix)[1]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td scope="row" class="bg-primary" style="border-bottom: #222 1px solid;">@loc["WEBFRONT_HELP_COMMAND_DESC_REQUIRED_LEVEL"]</td>
|
||||
|
@ -6,10 +6,6 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command[0] !== '!') {
|
||||
$('#console_command_response').text(_localization['WEBFRONT_CONSOLE_COMMAND']).addClass('text-danger');
|
||||
return false;
|
||||
}
|
||||
showLoader();
|
||||
$.get('/Console/ExecuteAsync', { serverId: serverId, command: command })
|
||||
.done(function (response) {
|
||||
|
Loading…
Reference in New Issue
Block a user