From 256624838ea26aa613b3c1f846f0282d6c340427 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Tue, 2 Aug 2022 16:03:20 +0200 Subject: [PATCH 01/10] Add SetCustomConfigurationCommand with test configuration items. --- .../ConfigurationsCommand.cs | 2 +- .../SetCustomConfigurationCommand.cs | 46 +++++++++++++++++++ .../Controllers/ConfigurationsController.cs | 2 +- .../TestItems/TestBoolItem.cs | 12 +++++ .../TestItems/TestChannelMentionItem.cs | 12 +++++ .../TestItems/TestDecimalItem.cs | 12 +++++ .../TestItems/TestDoubleItem.cs | 12 +++++ .../TestItems/TestFloatItem.cs | 12 +++++ .../TestItems/TestIntItem.cs | 12 +++++ .../TestItems/TestTextItem.cs | 12 +++++ .../TestItems/TestTextListItem.cs | 14 ++++++ .../TestItems/TestTimeItem.cs | 14 ++++++ .../TestItems/TestUlongItem.cs | 12 +++++ .../TestItems/TestUserMentionItem.cs | 12 +++++ 14 files changed, 184 insertions(+), 2 deletions(-) rename Watchman.Discord/Areas/Configurations/{IBotCommands => BotCommands}/ConfigurationsCommand.cs (85%) create mode 100644 Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestBoolItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestChannelMentionItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDecimalItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDoubleItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestFloatItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestIntItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextListItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUlongItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUserMentionItem.cs diff --git a/Watchman.Discord/Areas/Configurations/IBotCommands/ConfigurationsCommand.cs b/Watchman.Discord/Areas/Configurations/BotCommands/ConfigurationsCommand.cs similarity index 85% rename from Watchman.Discord/Areas/Configurations/IBotCommands/ConfigurationsCommand.cs rename to Watchman.Discord/Areas/Configurations/BotCommands/ConfigurationsCommand.cs index 30bdbc5e8..7b4a2ea96 100644 --- a/Watchman.Discord/Areas/Configurations/IBotCommands/ConfigurationsCommand.cs +++ b/Watchman.Discord/Areas/Configurations/BotCommands/ConfigurationsCommand.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading.Tasks; -namespace Watchman.Discord.Areas.Configurations.IBotCommands +namespace Watchman.Discord.Areas.Configurations.BotCommands { public class ConfigurationsCommand : IBotCommand { diff --git a/Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs b/Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs new file mode 100644 index 000000000..00f1c9ccb --- /dev/null +++ b/Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs @@ -0,0 +1,46 @@ +using Devscord.DiscordFramework.Commands; +using Devscord.DiscordFramework.Commands.PropertyAttributes; +using System; +using System.Collections.Generic; + +namespace Watchman.Discord.Areas.Configurations.BotCommands +{ + // TODO: add option for list of each type not only string + public class SetCustomConfigurationCommand : IBotCommand + { + [SingleWord] + public string Name { get; set; } + + [Optional] + [Text] + public string TextValue { get; set; } + + [Optional] + [Number] + public double? NumberValue { get; set; } + + [Optional] + [Number] + public decimal? DecimalValue { get; set; } + + [Optional] + [Time] + public DateTime? TimeValue { get; set; } + + [Optional] + [UserMention] + public ulong? UserValue { get; set; } + + [Optional] + [ChannelMention] + public ulong? ChannelValue { get; set; } + + [Optional] + [Text] + public string BoolValue { get; set; } + + [Optional] + [List] + public List ListValue { get; set; } + } +} diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index b34ef2a1e..29ae5df11 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; using Watchman.Cqrs; -using Watchman.Discord.Areas.Configurations.IBotCommands; +using Watchman.Discord.Areas.Configurations.BotCommands; using Watchman.DomainModel.Configuration; using Watchman.DomainModel.Configuration.Queries; using Watchman.DomainModel.Configuration.Services; diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestBoolItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestBoolItem.cs new file mode 100644 index 000000000..6add56f11 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestBoolItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestBoolItem : MappedConfiguration + { + public override bool Value { get; set; } = true; + public override string Group { get; set; } = "TestItems"; + + public TestBoolItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestChannelMentionItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestChannelMentionItem.cs new file mode 100644 index 000000000..16d641a3b --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestChannelMentionItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestChannelMentionItem : MappedConfiguration + { + public override ulong Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestChannelMentionItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDecimalItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDecimalItem.cs new file mode 100644 index 000000000..90102463e --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDecimalItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestDecimalItem : MappedConfiguration + { + public override decimal Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestDecimalItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDoubleItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDoubleItem.cs new file mode 100644 index 000000000..c2d5753ca --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestDoubleItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestDoubleItem : MappedConfiguration + { + public override double Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestDoubleItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestFloatItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestFloatItem.cs new file mode 100644 index 000000000..f3c87b27f --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestFloatItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestFloatItem : MappedConfiguration + { + public override float Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestFloatItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestIntItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestIntItem.cs new file mode 100644 index 000000000..e52d19ffc --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestIntItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestIntItem : MappedConfiguration + { + public override int Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestIntItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextItem.cs new file mode 100644 index 000000000..d2fa9d2bb --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestTextItem : MappedConfiguration + { + public override string Value { get; set; } = "default"; + public override string Group { get; set; } = "TestItems"; + + public TestTextItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextListItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextListItem.cs new file mode 100644 index 000000000..9eebf180b --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTextListItem.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestTextListItem : MappedConfiguration> + { + public override List Value { get; set; } = null; + public override string Group { get; set; } = "TestItems"; + + public TestTextListItem(ulong serverId) : base(serverId) + { + } + } +} \ No newline at end of file diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs new file mode 100644 index 000000000..39bde7eb1 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs @@ -0,0 +1,14 @@ +using System; + +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestTimeItem : MappedConfiguration + { + public override DateTime Value { get; set; } = default; + public override string Group { get; set; } = "TestItems"; + + public TestTimeItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUlongItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUlongItem.cs new file mode 100644 index 000000000..e65047ce2 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUlongItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestUlongItem : MappedConfiguration + { + public override ulong Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestUlongItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUserMentionItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUserMentionItem.cs new file mode 100644 index 000000000..560cd20c1 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestUserMentionItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestUserMentionItem : MappedConfiguration + { + public override ulong Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestUserMentionItem(ulong serverId) : base(serverId) + { + } + } +} From 7068e3f6f0516fc35639742783cd69bf24cc67aa Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Tue, 2 Aug 2022 23:53:52 +0200 Subject: [PATCH 02/10] Add SetCustomConfiguration to ConfigurationsController and fix related bugs. --- .../Services/BotCommandsParsingService.cs | 8 +- .../BotCommandsPropertyConversionService.cs | 10 ++- ...nCommand.cs => SetConfigurationCommand.cs} | 8 +- .../Controllers/ConfigurationsController.cs | 78 +++++++++++++++++-- .../ConfigurationsResponsesManager.cs | 32 ++++++++ .../TestItems/TestTimeItem.cs | 4 +- .../Services/ConfigurationMapperService.cs | 8 +- .../Services/ConfigurationService.cs | 7 +- .../Services/IConfigurationService.cs | 2 +- .../ConfigurationsDefaultResponses.json | 23 ++++++ .../Responses/ResponsesGetterService.cs | 1 + .../Watchman.DomainModel.csproj | 3 + 12 files changed, 154 insertions(+), 30 deletions(-) rename Watchman.Discord/Areas/Configurations/BotCommands/{SetCustomConfigurationCommand.cs => SetConfigurationCommand.cs} (82%) create mode 100644 Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs create mode 100644 Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json diff --git a/Devscord.DiscordFramework/Commands/Services/BotCommandsParsingService.cs b/Devscord.DiscordFramework/Commands/Services/BotCommandsParsingService.cs index 52862bb57..962f7377b 100644 --- a/Devscord.DiscordFramework/Commands/Services/BotCommandsParsingService.cs +++ b/Devscord.DiscordFramework/Commands/Services/BotCommandsParsingService.cs @@ -42,8 +42,8 @@ private IBotCommand GetFilledInstance(Type commandType, BotCommandTemplate templ var instance = Activator.CreateInstance(commandType); foreach (var property in commandType.GetProperties()) { - var propertyType = template.Properties.First(x => x.Name == property.Name).Type; - var isList = propertyType == BotCommandPropertyType.List; + var propertyCommandType = template.Properties.First(x => x.Name == property.Name).Type; + var isList = propertyCommandType == BotCommandPropertyType.List; var value = getValueByName.Invoke(property.Name, isList); if (string.IsNullOrWhiteSpace(value as string) && !isList) { @@ -62,8 +62,8 @@ private IBotCommand GetFilledInstance(Type commandType, BotCommandTemplate templ } if (value is string valueString) { - var convertedType = this._botCommandPropertyConversionService.ConvertType(valueString, propertyType); - property.SetValue(instance, convertedType); + var convertedValue = this._botCommandPropertyConversionService.ConvertType(valueString, propertyCommandType, property.PropertyType); + property.SetValue(instance, convertedValue); } } return (IBotCommand)instance; diff --git a/Devscord.DiscordFramework/Commands/Services/BotCommandsPropertyConversionService.cs b/Devscord.DiscordFramework/Commands/Services/BotCommandsPropertyConversionService.cs index 6293fb604..f6df63101 100644 --- a/Devscord.DiscordFramework/Commands/Services/BotCommandsPropertyConversionService.cs +++ b/Devscord.DiscordFramework/Commands/Services/BotCommandsPropertyConversionService.cs @@ -11,7 +11,7 @@ namespace Devscord.DiscordFramework.Commands.Services { public interface IBotCommandsPropertyConversionService { - object ConvertType(string value, BotCommandPropertyType type); + object ConvertType(string value, BotCommandPropertyType commandType, Type propertyType); } public class BotCommandsPropertyConversionService : IBotCommandsPropertyConversionService @@ -19,9 +19,9 @@ public class BotCommandsPropertyConversionService : IBotCommandsPropertyConversi private readonly Regex _exTime = new Regex(@"(?\d+)(?(ms|d|h|m|s))", RegexOptions.IgnoreCase | RegexOptions.Compiled); private readonly Regex _exMention = new Regex(@"\d+", RegexOptions.Compiled); - public object ConvertType(string value, BotCommandPropertyType type) + public object ConvertType(string value, BotCommandPropertyType commandType, Type propertyType) { - return type switch + object convertedValue = commandType switch { BotCommandPropertyType.Time => this.ToTimeSpan(value), BotCommandPropertyType.Number => int.Parse(value), @@ -30,6 +30,10 @@ public object ConvertType(string value, BotCommandPropertyType type) BotCommandPropertyType.ChannelMention => ulong.Parse(_exMention.Match(value).Value), _ => value }; + + var underlyingType = Nullable.GetUnderlyingType(propertyType) ?? propertyType; + var result = Convert.ChangeType(convertedValue, underlyingType); + return result; } private TimeSpan ToTimeSpan(string value) diff --git a/Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs b/Watchman.Discord/Areas/Configurations/BotCommands/SetConfigurationCommand.cs similarity index 82% rename from Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs rename to Watchman.Discord/Areas/Configurations/BotCommands/SetConfigurationCommand.cs index 00f1c9ccb..d35feecd1 100644 --- a/Watchman.Discord/Areas/Configurations/BotCommands/SetCustomConfigurationCommand.cs +++ b/Watchman.Discord/Areas/Configurations/BotCommands/SetConfigurationCommand.cs @@ -6,7 +6,7 @@ namespace Watchman.Discord.Areas.Configurations.BotCommands { // TODO: add option for list of each type not only string - public class SetCustomConfigurationCommand : IBotCommand + public class SetConfigurationCommand : IBotCommand { [SingleWord] public string Name { get; set; } @@ -19,13 +19,9 @@ public class SetCustomConfigurationCommand : IBotCommand [Number] public double? NumberValue { get; set; } - [Optional] - [Number] - public decimal? DecimalValue { get; set; } - [Optional] [Time] - public DateTime? TimeValue { get; set; } + public TimeSpan? TimeValue { get; set; } [Optional] [UserMention] diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index 29ae5df11..6061e152d 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -11,24 +11,28 @@ using Watchman.DomainModel.Configuration; using Watchman.DomainModel.Configuration.Queries; using Watchman.DomainModel.Configuration.Services; +using Watchman.Discord.ResponsesManagers; +using Devscord.DiscordFramework.Commons.Exceptions; namespace Watchman.Discord.Areas.Configurations.Controllers { public class ConfigurationsController : IController { - private readonly IMessagesServiceFactory messagesServiceFactory; - private readonly IConfigurationService configurationService; + private readonly IMessagesServiceFactory _messagesServiceFactory; + private readonly IConfigurationService _configurationService; + private readonly IConfigurationMapperService _configurationMapperService; - public ConfigurationsController(IQueryBus queryBus, IMessagesServiceFactory messagesServiceFactory, IConfigurationService configurationService) + public ConfigurationsController(IMessagesServiceFactory messagesServiceFactory, IConfigurationService configurationService, IConfigurationMapperService configurationMapperService) { - this.messagesServiceFactory = messagesServiceFactory; - this.configurationService = configurationService; + this._messagesServiceFactory = messagesServiceFactory; + this._configurationService = configurationService; + this._configurationMapperService = configurationMapperService; } //todo tests public async Task GetConfigurations(ConfigurationsCommand command, Contexts contexts) { - var configurations = this.configurationService.GetConfigurationItems(contexts.Server.Id); + var configurations = this._configurationService.GetConfigurationItems(contexts.Server.Id); if(command.Group != null) { configurations = configurations.Where(x => x.Group.ToLower() == command.Group.ToLower()); @@ -36,8 +40,68 @@ public async Task GetConfigurations(ConfigurationsCommand command, Contexts cont var groupped = configurations.GroupBy(x => x.Group).OrderBy(x => x.Key); var mapped = groupped.Select(x => new KeyValuePair(x.Key, $"```\n{string.Join("\n", x.Select(item => item.Name))}```")); //todo from responses - var messagesService = this.messagesServiceFactory.Create(contexts); + var messagesService = this._messagesServiceFactory.Create(contexts); await messagesService.SendEmbedMessage("Konfiguracja", "Poniżej znajdziesz liste elementów konfiguracji", mapped); } + + // TODO: Add tests and refactor + public async Task SetCustomConfiguration(SetConfigurationCommand command, Contexts contexts) + { + var mappedConfiguration = this._configurationService.GetConfigurationItems(contexts.Server.Id) + .FirstOrDefault(item => item.Name.ToLowerInvariant() == command.Name.ToLowerInvariant()); + var messageService = this._messagesServiceFactory.Create(contexts); + + if (mappedConfiguration == null) + { + await messageService.SendResponse(x => x.ConfigurationItemNotFound(command.Name)); + return; + } + + var valueProperties = command.GetType().GetProperties().Where(x => x.Name.EndsWith("Value")); + + if (valueProperties.Count(x => x.GetValue(command) != null) > 1) + { + await messageService.SendResponse(x => x.TooManyValueArgumentsForSetConfiguration()); + return; + } + + var configurationItem = this._configurationMapperService.MapIntoBaseFormat(mappedConfiguration, newServerId: contexts.Server.Id); + + if (valueProperties.All(x => x.GetValue(command) == null)) + { + var type = configurationItem.Value.GetType(); + var defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null; + configurationItem.SetValue(defaultValue); + await this._configurationService.SaveNewConfiguration(configurationItem); + await messageService.SendResponse(x => x.ConfigurationValueHasBeenSetAsDefaultOfType(contexts, command.Name)); + return; + } + + if (command.NumberValue != null) + { + if (!double.TryParse(configurationItem.Value.ToString(), out var _)) + { + throw new InvalidArgumentsException(); + } + var convertedValue = Convert.ChangeType(command.NumberValue, configurationItem.Value.GetType()); + configurationItem.SetValue(convertedValue); + } + else if (command.BoolValue != null) + { + if (!bool.TryParse(command.BoolValue, out var result)) + { + throw new InvalidArgumentsException(); + } + configurationItem.SetValue(result); + } + else + { + var value = valueProperties.Select(x => x.GetValue(command)).First(x => x != null); + configurationItem.SetValue(value); + } + + await this._configurationService.SaveNewConfiguration(configurationItem); + await messageService.SendResponse(x => x.CustomConfigurationHasBeenSet(contexts, command.Name)); + } } } diff --git a/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs b/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs new file mode 100644 index 000000000..6bdb4b743 --- /dev/null +++ b/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs @@ -0,0 +1,32 @@ +using Devscord.DiscordFramework.Commands.Responses; +using Devscord.DiscordFramework.Middlewares.Contexts; +using System.Collections.Generic; + +namespace Watchman.Discord.ResponsesManagers +{ + public static class ConfigurationsResponsesManager + { + public static string ConfigurationItemNotFound(this IResponsesService responsesService, string name) + { + return responsesService.ProcessResponse("ConfigurationItemNotFound", + new KeyValuePair(nameof(name), name)); + } + + public static string TooManyValueArgumentsForSetConfiguration(this IResponsesService responsesService) + { + return responsesService.ProcessResponse("TooManyValueArgumentsForSetConfiguration"); + } + + public static string CustomConfigurationHasBeenSet(this IResponsesService responsesService, Contexts contexts, string name) + { + return responsesService.ProcessResponse("CustomConfigurationHasBeenSet", contexts, + new KeyValuePair(nameof(name), name)); + } + + public static string ConfigurationValueHasBeenSetAsDefaultOfType(this IResponsesService responsesService, Contexts contexts, string name) + { + return responsesService.ProcessResponse("ConfigurationValueHasBeenSetAsDefaultOfType", contexts, + new KeyValuePair(nameof(name), name)); + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs index 39bde7eb1..b1d8a675a 100644 --- a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestTimeItem.cs @@ -2,9 +2,9 @@ namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems { - public class TestTimeItem : MappedConfiguration + public class TestTimeItem : MappedConfiguration { - public override DateTime Value { get; set; } = default; + public override TimeSpan Value { get; set; } = default; public override string Group { get; set; } = "TestItems"; public TestTimeItem(ulong serverId) : base(serverId) diff --git a/Watchman.DomainModel/Configuration/Services/ConfigurationMapperService.cs b/Watchman.DomainModel/Configuration/Services/ConfigurationMapperService.cs index da7967b4e..548fd681f 100644 --- a/Watchman.DomainModel/Configuration/Services/ConfigurationMapperService.cs +++ b/Watchman.DomainModel/Configuration/Services/ConfigurationMapperService.cs @@ -8,7 +8,7 @@ namespace Watchman.DomainModel.Configuration.Services public interface IConfigurationMapperService { Dictionary> GetMappedConfigurations(IEnumerable configurationItems); - ConfigurationItem MapIntoBaseFormat(IMappedConfiguration mappedConfiguration); + ConfigurationItem MapIntoBaseFormat(IMappedConfiguration mappedConfiguration, ulong? newServerId = null); } public class ConfigurationMapperService : IConfigurationMapperService @@ -26,9 +26,11 @@ public Dictionary> GetMappedConfig return groupedByTypes.Select(this.MakeServersDictionary).ToDictionary(x => x.Values.First().GetType(), x => x); } - public ConfigurationItem MapIntoBaseFormat(IMappedConfiguration mappedConfiguration) + public ConfigurationItem MapIntoBaseFormat(IMappedConfiguration mappedConfiguration, ulong? newServerId = null) { - return new ConfigurationItem(((dynamic)mappedConfiguration).Value, mappedConfiguration.ServerId, mappedConfiguration.Name, mappedConfiguration.Group, mappedConfiguration.SubGroup); + var value = ((dynamic)mappedConfiguration).Value; + var serverId = newServerId ?? mappedConfiguration.ServerId; + return new ConfigurationItem(value, serverId, mappedConfiguration.Name, mappedConfiguration.Group, mappedConfiguration.SubGroup); } private Dictionary MakeServersDictionary(IEnumerable configurationItems) diff --git a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs index be142178f..5a38f7f1d 100644 --- a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs @@ -44,19 +44,18 @@ public IEnumerable GetConfigurationItems(ulong serverId) return _cachedConfigurationItem.Select(x => x.Value.GetValueOrDefault(serverId) ?? x.Value[DEFAULT_SERVER_ID]); } - public async Task SaveNewConfiguration(IMappedConfiguration changedConfiguration) // todo: saving new configuration not tested + public async Task SaveNewConfiguration(ConfigurationItem changedConfiguration) // todo: saving new configuration not tested { using var session = this._sessionFactory.CreateMongo(); var existingConfiguration = session.Get() .FirstOrDefault(x => x.ServerId == changedConfiguration.ServerId && x.Name == changedConfiguration.Name); - var baseFormatConfigurationItem = this._configurationMapperService.MapIntoBaseFormat(changedConfiguration); if (existingConfiguration == null) { - await session.AddAsync(baseFormatConfigurationItem); + await session.AddAsync(changedConfiguration); } else { - existingConfiguration.SetValue(baseFormatConfigurationItem.Value); + existingConfiguration.SetValue(changedConfiguration.Value); await session.AddOrUpdateAsync(existingConfiguration); } this.Refresh(); diff --git a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs index 833a84ff6..fa7934db5 100644 --- a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs @@ -7,7 +7,7 @@ public interface IConfigurationService { T GetConfigurationItem(ulong serverId) where T : IMappedConfiguration; IEnumerable GetConfigurationItems(ulong serverId); - Task SaveNewConfiguration(IMappedConfiguration changedConfiguration); + Task SaveNewConfiguration(ConfigurationItem changedConfiguration); Task InitDefaultConfigurations(); } } diff --git a/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json b/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json new file mode 100644 index 000000000..e4f341d31 --- /dev/null +++ b/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json @@ -0,0 +1,23 @@ +[ + { + "OnEvent": "ConfigurationItemNotFound", + "Value": "Item konfiguracji **{{name}}** nie został odnaleziony.", + "Variables": [ "name" ] + }, + { + "OnEvent": "TooManyValueArgumentsForSetConfiguration", + "Value": "Podano za dużo wartości. Podaj tylko jedną wartość dla tego itemu konfiguracji" + }, + { + "OnEvent": "CustomConfigurationHasBeenSet", + "Value": "Itemowi konfiguracji **{{name}}** ustawiono niestandardową wartość dla serwera **{{context_server}}**.", + "Variables": [ "name" ], + "RequireContext": true + }, + { + "OnEvent": "ConfigurationValueHasBeenSetAsDefaultOfType", + "Value": "Itemowi konfiguracji **{{name}}** ustawiono **domyślną** wartość jego typu dla serwera **{{context_server}}**.", + "Variables": [ "name" ], + "RequireContext": true + } +] diff --git a/Watchman.DomainModel/Responses/ResponsesGetterService.cs b/Watchman.DomainModel/Responses/ResponsesGetterService.cs index 22d3a47b2..6382c6439 100644 --- a/Watchman.DomainModel/Responses/ResponsesGetterService.cs +++ b/Watchman.DomainModel/Responses/ResponsesGetterService.cs @@ -22,6 +22,7 @@ public class ResponsesGetterService : IResponsesGetterService "HelpInformations", "Administration", "AntiSpam", + "Configurations", "Help", "Muting", "Responses", diff --git a/Watchman.DomainModel/Watchman.DomainModel.csproj b/Watchman.DomainModel/Watchman.DomainModel.csproj index 5acf03c5a..c1e9560da 100644 --- a/Watchman.DomainModel/Watchman.DomainModel.csproj +++ b/Watchman.DomainModel/Watchman.DomainModel.csproj @@ -43,6 +43,9 @@ Always + + Always + From 4a2b58835207e84496de8899a345dea142433ce4 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 19:05:38 +0200 Subject: [PATCH 03/10] Add ConfigurationValueSetter and add ValueType to MappedConfiguration. --- .../Controllers/ConfigurationsController.cs | 49 +++------ .../Services/ConfigurationValueSetter.cs | 99 +++++++++++++++++++ .../TestItems/TestNullableBoolItem.cs | 12 +++ .../TestItems/TestNullableFloatItem.cs | 12 +++ .../TestItems/TestNullableTimeItem.cs | 15 +++ .../Configuration/MappedConfiguration.cs | 1 + .../Services/ConfigurationService.cs | 5 + .../Services/IConfigurationService.cs | 4 +- 8 files changed, 160 insertions(+), 37 deletions(-) create mode 100644 Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableBoolItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableFloatItem.cs create mode 100644 Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index 6061e152d..01aa355f2 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -13,6 +13,7 @@ using Watchman.DomainModel.Configuration.Services; using Watchman.Discord.ResponsesManagers; using Devscord.DiscordFramework.Commons.Exceptions; +using Watchman.Discord.Areas.Configurations.Services; namespace Watchman.Discord.Areas.Configurations.Controllers { @@ -21,12 +22,14 @@ public class ConfigurationsController : IController private readonly IMessagesServiceFactory _messagesServiceFactory; private readonly IConfigurationService _configurationService; private readonly IConfigurationMapperService _configurationMapperService; + private readonly IConfigurationValueSetter _configurationValueSetter; - public ConfigurationsController(IMessagesServiceFactory messagesServiceFactory, IConfigurationService configurationService, IConfigurationMapperService configurationMapperService) + public ConfigurationsController(IMessagesServiceFactory messagesServiceFactory, IConfigurationService configurationService, IConfigurationMapperService configurationMapperService, IConfigurationValueSetter configurationValueSetter) { this._messagesServiceFactory = messagesServiceFactory; this._configurationService = configurationService; this._configurationMapperService = configurationMapperService; + this._configurationValueSetter = configurationValueSetter; } //todo tests @@ -44,7 +47,7 @@ public async Task GetConfigurations(ConfigurationsCommand command, Contexts cont await messagesService.SendEmbedMessage("Konfiguracja", "Poniżej znajdziesz liste elementów konfiguracji", mapped); } - // TODO: Add tests and refactor + // TODO: Add tests public async Task SetCustomConfiguration(SetConfigurationCommand command, Contexts contexts) { var mappedConfiguration = this._configurationService.GetConfigurationItems(contexts.Server.Id) @@ -57,50 +60,24 @@ public async Task SetCustomConfiguration(SetConfigurationCommand command, Contex return; } - var valueProperties = command.GetType().GetProperties().Where(x => x.Name.EndsWith("Value")); - - if (valueProperties.Count(x => x.GetValue(command) != null) > 1) + var propertiesValues = command.GetType().GetProperties().Where(x => x.Name.EndsWith("Value")).Select(x => x.GetValue(command)); + var countOfPropertiesWithValue = propertiesValues.Count(x => x != null); + if (countOfPropertiesWithValue > 1) { await messageService.SendResponse(x => x.TooManyValueArgumentsForSetConfiguration()); return; } - var configurationItem = this._configurationMapperService.MapIntoBaseFormat(mappedConfiguration, newServerId: contexts.Server.Id); - - if (valueProperties.All(x => x.GetValue(command) == null)) + var configurationItem = this._configurationMapperService.MapIntoBaseFormat(mappedConfiguration, contexts.Server.Id); + var configurationValueType = this._configurationService.GetConfigurationValueType(mappedConfiguration); + if (countOfPropertiesWithValue == 0) { - var type = configurationItem.Value.GetType(); - var defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null; - configurationItem.SetValue(defaultValue); - await this._configurationService.SaveNewConfiguration(configurationItem); + await this._configurationValueSetter.SetDefaultValueForConfiguration(configurationItem, configurationValueType); await messageService.SendResponse(x => x.ConfigurationValueHasBeenSetAsDefaultOfType(contexts, command.Name)); return; } - if (command.NumberValue != null) - { - if (!double.TryParse(configurationItem.Value.ToString(), out var _)) - { - throw new InvalidArgumentsException(); - } - var convertedValue = Convert.ChangeType(command.NumberValue, configurationItem.Value.GetType()); - configurationItem.SetValue(convertedValue); - } - else if (command.BoolValue != null) - { - if (!bool.TryParse(command.BoolValue, out var result)) - { - throw new InvalidArgumentsException(); - } - configurationItem.SetValue(result); - } - else - { - var value = valueProperties.Select(x => x.GetValue(command)).First(x => x != null); - configurationItem.SetValue(value); - } - - await this._configurationService.SaveNewConfiguration(configurationItem); + await this._configurationValueSetter.SetConfigurationValueFromCommand(command, configurationItem, propertiesValues, configurationValueType); await messageService.SendResponse(x => x.CustomConfigurationHasBeenSet(contexts, command.Name)); } } diff --git a/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs b/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs new file mode 100644 index 000000000..34d6093b6 --- /dev/null +++ b/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs @@ -0,0 +1,99 @@ +using Devscord.DiscordFramework.Commons.Exceptions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Watchman.Discord.Areas.Configurations.BotCommands; +using Watchman.DomainModel.Configuration; +using Watchman.DomainModel.Configuration.Services; + +namespace Watchman.Discord.Areas.Configurations.Services +{ + public interface IConfigurationValueSetter + { + Task SetDefaultValueForConfiguration(ConfigurationItem configurationItem, Type valueType); + Task SetConfigurationValueFromCommand(SetConfigurationCommand command, ConfigurationItem configurationItem, IEnumerable propertiesValues, Type configurationValueType); + } + + // TODO: Add tests + public class ConfigurationValueSetter : IConfigurationValueSetter + { + private readonly IConfigurationService _configurationService; + + public ConfigurationValueSetter(IConfigurationService configurationService) + { + _configurationService = configurationService; + } + + public async Task SetDefaultValueForConfiguration(ConfigurationItem configurationItem, Type valueType) + { + var defaultTypeValue = valueType.IsValueType ? Activator.CreateInstance(valueType) : null; + await this.SetNewConfiguration(configurationItem, defaultTypeValue); + } + + public async Task SetConfigurationValueFromCommand(SetConfigurationCommand command, ConfigurationItem configurationItem, IEnumerable propertiesValues, Type configurationValueType) + { + var valueToSet = command switch + { + SetConfigurationCommand com when com.NumberValue != null + => this.GetNumberValue(command.NumberValue, configurationValueType), + + SetConfigurationCommand com when com.BoolValue != null + => this.GetBoolValue(command.BoolValue, configurationValueType), + + _ => this.GetCustomValue(propertiesValues, configurationValueType) + }; + await this.SetNewConfiguration(configurationItem, valueToSet); + } + + private object GetNumberValue(double? numberValue, Type configurationValueType) + { + var underlyingValueType = this.GetUnderlyingType(configurationValueType); + var doesItemAcceptNumbers = underlyingValueType.IsValueType + ? Activator.CreateInstance(underlyingValueType).ToString() == "0" + : false; + + if (!doesItemAcceptNumbers) + { + throw new InvalidArgumentsException(); + } + return Convert.ChangeType(numberValue, configurationValueType); + } + + private bool GetBoolValue(string valueInText, Type configurationValueType) + { + var isValueConvertibleToBool = bool.TryParse(valueInText, out var convertedValue); + var doesItemAcceptBool = configurationValueType == typeof(bool) || configurationValueType == typeof(bool?); + + if (!isValueConvertibleToBool || !doesItemAcceptBool) + { + throw new InvalidArgumentsException(); + } + return convertedValue; + } + + private object GetCustomValue(IEnumerable propertiesValues, Type configurationValueType) + { + var providedValue = propertiesValues.First(x => x != null); + + var underlyingTypeOfProvidedValue = this.GetUnderlyingType(providedValue.GetType()); + var underlyingConfigurationType = this.GetUnderlyingType(configurationValueType); + + if (underlyingTypeOfProvidedValue != underlyingConfigurationType) + { + throw new InvalidArgumentsException(); + } + return providedValue; + } + + private Type GetUnderlyingType(Type type) + => Nullable.GetUnderlyingType(type) ?? type; + + private async Task SetNewConfiguration(ConfigurationItem configurationItem, object valueToSet) + { + configurationItem.SetValue(valueToSet); + await this._configurationService.SaveNewConfiguration(configurationItem); + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableBoolItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableBoolItem.cs new file mode 100644 index 000000000..0784a6162 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableBoolItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestNullableBoolItem : MappedConfiguration + { + public override bool? Value { get; set; } = true; + public override string Group { get; set; } = "TestItems"; + + public TestNullableBoolItem(ulong serverId) : base(serverId) + { + } + } +} \ No newline at end of file diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableFloatItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableFloatItem.cs new file mode 100644 index 000000000..f5f814152 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableFloatItem.cs @@ -0,0 +1,12 @@ +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestNullableFloatItem : MappedConfiguration + { + public override float? Value { get; set; } = 0; + public override string Group { get; set; } = "TestItems"; + + public TestNullableFloatItem(ulong serverId) : base(serverId) + { + } + } +} diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs new file mode 100644 index 000000000..4dde67097 --- /dev/null +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs @@ -0,0 +1,15 @@ +using System; + +namespace Watchman.DomainModel.Configuration.ConfigurationItems.TestItems +{ + public class TestNullableTimeItem : MappedConfiguration + { + public override TimeSpan? Value { get; set; } = TimeSpan.FromDays(1); + public override string Group { get; set; } = "TestItems"; + + public TestNullableTimeItem(ulong serverId) : base(serverId) + { + } + } +} + diff --git a/Watchman.DomainModel/Configuration/MappedConfiguration.cs b/Watchman.DomainModel/Configuration/MappedConfiguration.cs index 942fdc20b..fa6c13934 100644 --- a/Watchman.DomainModel/Configuration/MappedConfiguration.cs +++ b/Watchman.DomainModel/Configuration/MappedConfiguration.cs @@ -6,6 +6,7 @@ namespace Watchman.DomainModel.Configuration public abstract class MappedConfiguration : IMappedConfiguration { public abstract T Value { get; set; } + public Type ValueType { get; } = typeof(T); public ulong ServerId { get; } public string Name { get; } public abstract string Group { get; set; } diff --git a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs index 5a38f7f1d..188f50f70 100644 --- a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs @@ -113,6 +113,11 @@ public void Refresh() //todo refactor _cachedConfigurationItem = mappedConfigurations; } + public Type GetConfigurationValueType(IMappedConfiguration mappedConfiguration) + { + return ((dynamic)mappedConfiguration).ValueType; + } + //todo refactor private IConfigurationChangesHandler GetConfigurationChangesHandler(IMappedConfiguration newMappedConfiguration) { diff --git a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs index fa7934db5..f576622db 100644 --- a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Watchman.DomainModel.Configuration.Services @@ -9,5 +10,6 @@ public interface IConfigurationService IEnumerable GetConfigurationItems(ulong serverId); Task SaveNewConfiguration(ConfigurationItem changedConfiguration); Task InitDefaultConfigurations(); + Type GetConfigurationValueType(IMappedConfiguration mappedConfiguration); } } From 8db872c72d6831f1bbb8ff97b1a81f04779da156 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 20:41:05 +0200 Subject: [PATCH 04/10] Add removing custom command feature. --- .../BotCommands/RemoveConfigurationCommand.cs | 16 +++++++++++++++ .../Controllers/ConfigurationsController.cs | 18 +++++++++++++++++ .../ConfigurationsResponsesManager.cs | 20 +++++++++++++++---- .../Services/ConfigurationService.cs | 16 +++++++++++++++ .../Services/IConfigurationService.cs | 1 + .../ConfigurationsDefaultResponses.json | 12 +++++++++++ 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 Watchman.Discord/Areas/Configurations/BotCommands/RemoveConfigurationCommand.cs diff --git a/Watchman.Discord/Areas/Configurations/BotCommands/RemoveConfigurationCommand.cs b/Watchman.Discord/Areas/Configurations/BotCommands/RemoveConfigurationCommand.cs new file mode 100644 index 000000000..b19e5e632 --- /dev/null +++ b/Watchman.Discord/Areas/Configurations/BotCommands/RemoveConfigurationCommand.cs @@ -0,0 +1,16 @@ +using Devscord.DiscordFramework.Commands; +using Devscord.DiscordFramework.Commands.PropertyAttributes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Watchman.Discord.Areas.Configurations.BotCommands +{ + public class RemoveConfigurationCommand : IBotCommand + { + [SingleWord] + public string Name { get; set; } + } +} diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index 01aa355f2..1c8ad4fb7 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -14,6 +14,7 @@ using Watchman.Discord.ResponsesManagers; using Devscord.DiscordFramework.Commons.Exceptions; using Watchman.Discord.Areas.Configurations.Services; +using Watchman.DomainModel.Responses; namespace Watchman.Discord.Areas.Configurations.Controllers { @@ -80,5 +81,22 @@ public async Task SetCustomConfiguration(SetConfigurationCommand command, Contex await this._configurationValueSetter.SetConfigurationValueFromCommand(command, configurationItem, propertiesValues, configurationValueType); await messageService.SendResponse(x => x.CustomConfigurationHasBeenSet(contexts, command.Name)); } + + // TODO: Add tests + public async Task RemoveCustomConfiguration(RemoveConfigurationCommand command, Contexts contexts) + { + var mappedConfiguration = this._configurationService.GetConfigurationItems(contexts.Server.Id) + .FirstOrDefault(item => item.Name.ToLowerInvariant() == command.Name.ToLowerInvariant()); + var messageService = this._messagesServiceFactory.Create(contexts); + + if (mappedConfiguration == null || mappedConfiguration.ServerId == Response.DEFAULT_SERVER_ID) + { + await messageService.SendResponse(x => x.ServerDoesntHaveCustomValueForConfiguration(contexts, command.Name)); + return; + } + + await this._configurationService.RemoveCustomConfiguration(mappedConfiguration); + await messageService.SendResponse(x => x.CustomConfigurationHasBeenRemoved(contexts, command.Name)); + } } } diff --git a/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs b/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs index 6bdb4b743..d7e75ef0e 100644 --- a/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs +++ b/Watchman.Discord/ResponsesManagers/ConfigurationsResponsesManager.cs @@ -8,24 +8,36 @@ public static class ConfigurationsResponsesManager { public static string ConfigurationItemNotFound(this IResponsesService responsesService, string name) { - return responsesService.ProcessResponse("ConfigurationItemNotFound", + return responsesService.ProcessResponse(nameof(ConfigurationItemNotFound), new KeyValuePair(nameof(name), name)); } public static string TooManyValueArgumentsForSetConfiguration(this IResponsesService responsesService) { - return responsesService.ProcessResponse("TooManyValueArgumentsForSetConfiguration"); + return responsesService.ProcessResponse(nameof(TooManyValueArgumentsForSetConfiguration)); } public static string CustomConfigurationHasBeenSet(this IResponsesService responsesService, Contexts contexts, string name) { - return responsesService.ProcessResponse("CustomConfigurationHasBeenSet", contexts, + return responsesService.ProcessResponse(nameof(CustomConfigurationHasBeenSet), contexts, new KeyValuePair(nameof(name), name)); } public static string ConfigurationValueHasBeenSetAsDefaultOfType(this IResponsesService responsesService, Contexts contexts, string name) { - return responsesService.ProcessResponse("ConfigurationValueHasBeenSetAsDefaultOfType", contexts, + return responsesService.ProcessResponse(nameof(ConfigurationValueHasBeenSetAsDefaultOfType), contexts, + new KeyValuePair(nameof(name), name)); + } + + public static string CustomConfigurationHasBeenRemoved(this IResponsesService responsesService, Contexts contexts, string name) + { + return responsesService.ProcessResponse(nameof(CustomConfigurationHasBeenRemoved), contexts, + new KeyValuePair(nameof(name), name)); + } + + public static string ServerDoesntHaveCustomValueForConfiguration(this IResponsesService responsesService, Contexts contexts, string name) + { + return responsesService.ProcessResponse(nameof(ServerDoesntHaveCustomValueForConfiguration), contexts, new KeyValuePair(nameof(name), name)); } } diff --git a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs index 188f50f70..3231b708c 100644 --- a/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/ConfigurationService.cs @@ -113,6 +113,22 @@ public void Refresh() //todo refactor _cachedConfigurationItem = mappedConfigurations; } + public async Task RemoveCustomConfiguration(IMappedConfiguration configurationToDelete) + { + using var session = this._sessionFactory.CreateMongo(); + var existingConfiguration = session.Get() + .FirstOrDefault(x => x.ServerId == configurationToDelete.ServerId && x.Name == configurationToDelete.Name); + + if (existingConfiguration == null) + { + Log.Warning("Server with id {ServerId} just doesn't have custom configuration with name {ConfigurationName}", configurationToDelete.ServerId, configurationToDelete.Name); + return; + } + + await session.DeleteAsync(existingConfiguration); + this.Refresh(); + } + public Type GetConfigurationValueType(IMappedConfiguration mappedConfiguration) { return ((dynamic)mappedConfiguration).ValueType; diff --git a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs index f576622db..ef1bbeaeb 100644 --- a/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs +++ b/Watchman.DomainModel/Configuration/Services/IConfigurationService.cs @@ -10,6 +10,7 @@ public interface IConfigurationService IEnumerable GetConfigurationItems(ulong serverId); Task SaveNewConfiguration(ConfigurationItem changedConfiguration); Task InitDefaultConfigurations(); + Task RemoveCustomConfiguration(IMappedConfiguration configurationToDelete); Type GetConfigurationValueType(IMappedConfiguration mappedConfiguration); } } diff --git a/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json b/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json index e4f341d31..02fac292c 100644 --- a/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json +++ b/Watchman.DomainModel/Responses/Resources/ConfigurationsDefaultResponses.json @@ -19,5 +19,17 @@ "Value": "Itemowi konfiguracji **{{name}}** ustawiono **domyślną** wartość jego typu dla serwera **{{context_server}}**.", "Variables": [ "name" ], "RequireContext": true + }, + { + "OnEvent": "CustomConfigurationHasBeenRemoved", + "Value": "Niestandardowa konfiguracja **{{name}}** została usunięta dla serwera **{{context_server}}**.", + "Variables": [ "name" ], + "RequireContext": true + }, + { + "OnEvent": "ServerDoesntHaveCustomValueForConfiguration", + "Value": "Serwer **{{context_server}}** nie ma niestandardowej wartości dla konfiguracji **{{name}}**.", + "Variables": [ "name" ], + "RequireContext": true } ] From 4d30c9f15c26c818d7f424c183939957c58553d8 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 20:43:53 +0200 Subject: [PATCH 05/10] Keep default value for number types in const variable in ConfigurationValueSetter. --- .../Areas/Configurations/Services/ConfigurationValueSetter.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs b/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs index 34d6093b6..dab571106 100644 --- a/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs +++ b/Watchman.Discord/Areas/Configurations/Services/ConfigurationValueSetter.cs @@ -49,9 +49,10 @@ public async Task SetConfigurationValueFromCommand(SetConfigurationCommand comma private object GetNumberValue(double? numberValue, Type configurationValueType) { + const string defaultValueForNumberTypes = "0"; var underlyingValueType = this.GetUnderlyingType(configurationValueType); var doesItemAcceptNumbers = underlyingValueType.IsValueType - ? Activator.CreateInstance(underlyingValueType).ToString() == "0" + ? Activator.CreateInstance(underlyingValueType).ToString() == defaultValueForNumberTypes : false; if (!doesItemAcceptNumbers) From 47064d9402568fd0e6c5d6dafefd3b9f051ad174 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 20:49:43 +0200 Subject: [PATCH 06/10] Add descriptions to configuration commands. --- .../ResponsesManagers/HelpInformationsResponsesManager.cs | 6 ++++++ .../Resources/HelpInformationsDefaultResponses.json | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/Watchman.Discord/ResponsesManagers/HelpInformationsResponsesManager.cs b/Watchman.Discord/ResponsesManagers/HelpInformationsResponsesManager.cs index fd8c9afae..cfda1cc9d 100644 --- a/Watchman.Discord/ResponsesManagers/HelpInformationsResponsesManager.cs +++ b/Watchman.Discord/ResponsesManagers/HelpInformationsResponsesManager.cs @@ -81,5 +81,11 @@ public static string PL_untrust_description(this IResponsesService responsesServ public static string PL_trustedroles_description(this IResponsesService responsesService) => responsesService.ProcessResponse("PL_trustedroles_description"); + + public static string PL_setconfiguration_description(this IResponsesService responsesService) + => responsesService.ProcessResponse(nameof(PL_setconfiguration_description)); + + public static string PL_removeconfiguration_description(this IResponsesService responsesService) + => responsesService.ProcessResponse(nameof(PL_removeconfiguration_description)); } } diff --git a/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json b/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json index 74c0c998f..c89573d59 100644 --- a/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json +++ b/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json @@ -102,5 +102,13 @@ { "OnEvent": "PL_trustedroles_description", "Value": "Wyświetla listę ról dla zaufanych użytkowników.\n(każdy z taką rolą jest automatycznie zaufanym użytkownikiem)" + }, + { + "OnEvent": "PL_setconfiguration_description", + "Value": "Ustawia niestandardową wartość itemowi konfiguracji dla serwera" + }, + { + "OnEvent": "PL_removeconfiguration_description", + "Value": "Usuwa niestandardową wartość itemowi konfiguracji dla serwera" } ] From a8196219b5d07892e4fdd70790b01e50c7c9d465 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 20:54:25 +0200 Subject: [PATCH 07/10] Add period to configuration descriptions. --- .../Responses/Resources/HelpInformationsDefaultResponses.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json b/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json index c89573d59..eacff220c 100644 --- a/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json +++ b/Watchman.DomainModel/Responses/Resources/HelpInformationsDefaultResponses.json @@ -105,10 +105,10 @@ }, { "OnEvent": "PL_setconfiguration_description", - "Value": "Ustawia niestandardową wartość itemowi konfiguracji dla serwera" + "Value": "Ustawia niestandardową wartość itemowi konfiguracji dla serwera." }, { "OnEvent": "PL_removeconfiguration_description", - "Value": "Usuwa niestandardową wartość itemowi konfiguracji dla serwera" + "Value": "Usuwa niestandardową wartość itemowi konfiguracji dla serwera." } ] From 95ca7a74877b2bc36fa05b4e437ffb26c3389fa0 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 6 Aug 2022 20:59:57 +0200 Subject: [PATCH 08/10] Remove the end blank lines from file. --- .../ConfigurationItems/TestItems/TestNullableTimeItem.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs index 4dde67097..369b143c1 100644 --- a/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs +++ b/Watchman.DomainModel/Configuration/ConfigurationItems/TestItems/TestNullableTimeItem.cs @@ -11,5 +11,4 @@ public TestNullableTimeItem(ulong serverId) : base(serverId) { } } -} - +} \ No newline at end of file From 789cec3235787371e16b18ff76f76c1a33b9f272 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 13 Aug 2022 23:24:50 +0200 Subject: [PATCH 09/10] Add tests to SetCustomConfiguration. --- .../ConfigurationsControllerTests.cs | 192 ++++++++++++++++++ ...MessagesServiceMockWithResponsesFactory.cs | 22 ++ .../Controllers/ConfigurationsController.cs | 1 - 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs create mode 100644 Watchman.Discord.UnitTests/TestObjectFactories/MessagesServiceMockWithResponsesFactory.cs diff --git a/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs b/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs new file mode 100644 index 000000000..46ec2a450 --- /dev/null +++ b/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs @@ -0,0 +1,192 @@ +using AutoFixture; +using AutoFixture.NUnit3; +using Devscord.DiscordFramework.Commands.Responses; +using Devscord.DiscordFramework.Middlewares.Contexts; +using Devscord.DiscordFramework.Services.Factories; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Watchman.Discord.Areas.Configurations.BotCommands; +using Watchman.Discord.Areas.Configurations.Controllers; +using Watchman.Discord.Areas.Configurations.Services; +using Watchman.Discord.UnitTests.TestObjectFactories; +using Watchman.DomainModel.Configuration; +using Watchman.DomainModel.Configuration.Services; + +namespace Watchman.Discord.UnitTests.Configurations +{ + [TestFixture] + internal class ConfigurationsControllerTests + { + private readonly TestContextsFactory _testContextsFactory = new(); + private readonly MessagesServiceMockWithResponsesFactory _messagesServiceMockFactory = new(); + + private static readonly object[] _providedValues = new[] + { + new object[] { "asa", null, null, null, null, null, null }, + new object[] { null, "true", null, null, null, null, null }, + new object[] { null, null, 0ul, null, null, null, null }, + new object[] { null, null, null, new List { string.Empty }, null, null, null }, + new object[] { null, null, null, null, 0.0, null, null }, + new object[] { null, null, null, null, null, TimeSpan.Zero, null }, + new object[] { null, null, null, null, null, null, 0ul } + }; + + [Test, AutoData] + public async Task SetCustomConfiguration_ShouldSendResponseConfigurationItemNotFound(SetConfigurationCommand command) + { + // Arrange + var contexts = this._testContextsFactory.CreateContexts(1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var configurationServiceMock = new Mock(); + var configurationValueSetterMock = new Mock(); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, null, configurationValueSetterMock.Object); + + // Act + await controller.SetCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("ConfigurationItemNotFound", It.IsAny[]>()), Times.Once); + configurationValueSetterMock.Verify(x => x.SetDefaultValueForConfiguration(It.IsAny(), It.IsAny()), Times.Never); + configurationValueSetterMock + .Verify(x => x.SetConfigurationValueFromCommand(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()), Times.Never); + } + + [Test, AutoData] + public async Task SetCustomConfiguration_ShouldSendResponseTooManyValueArgumentsForSetConfiguration_WhenUserProvidedMoreThanOneValue(SetConfigurationCommand command) + { + // Arrange + var contexts = this._testContextsFactory.CreateContexts(1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var testMappedConfigurationMock = new Mock(); + testMappedConfigurationMock.SetupGet(x => x.Name) + .Returns(command.Name); + var configurationServiceMock = new Mock(); + configurationServiceMock.Setup(x => x.GetConfigurationItems(It.IsAny())) + .Returns(new List { testMappedConfigurationMock.Object }); + + var configurationValueSetterMock = new Mock(); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, null, configurationValueSetterMock.Object); + + // Act + await controller.SetCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("TooManyValueArgumentsForSetConfiguration"), Times.Once); + configurationValueSetterMock.Verify(x => x.SetDefaultValueForConfiguration(It.IsAny(), It.IsAny()), Times.Never); + configurationValueSetterMock + .Verify(x => x.SetConfigurationValueFromCommand(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()), Times.Never); + } + + [Test, AutoData] + public async Task SetCustomConfiguration_ShouldSetDefaultTypeValue_WhenUserDidNotProvideAnyValue(string commandName, ConfigurationItem configurationItem) + { + // Arrange + var command = new SetConfigurationCommand + { + Name = commandName + }; + var contexts = this._testContextsFactory.CreateContexts(1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var testMappedConfigurationMock = new Mock(); + testMappedConfigurationMock.SetupGet(x => x.Name) + .Returns(commandName); + var configurationServiceMock = new Mock(); + configurationServiceMock.Setup(x => x.GetConfigurationItems(It.IsAny())) + .Returns(new List { testMappedConfigurationMock.Object }); + + var configurationMapperServiceMock = new Mock(); + configurationMapperServiceMock.Setup(x => x.MapIntoBaseFormat(It.IsAny(), It.IsAny())) + .Returns(configurationItem); + + var configurationValueSetterMock = new Mock(); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, configurationMapperServiceMock.Object, configurationValueSetterMock.Object); + + // Act + await controller.SetCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("ConfigurationValueHasBeenSetAsDefaultOfType", It.IsAny(), It.IsAny[]>()), Times.Once); + configurationValueSetterMock.Verify(x => x.SetDefaultValueForConfiguration(It.IsAny(), It.IsAny()), Times.Once); + configurationValueSetterMock + .Verify(x => x.SetConfigurationValueFromCommand(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()), Times.Never); + } + + [Test] + [TestCaseSource(nameof(_providedValues))] + public async Task SetCustomConfiguration_ShouldSetCustomValue_WhenUserProvidedOnlyOneValue(string textValue, string boolValue, ulong? channelValue, List listValue, double? numberValue, TimeSpan? timeValue, ulong? userValue) + { + // Arrange + var fixture = new Fixture(); + var command = new SetConfigurationCommand + { + Name = fixture.Create(), + TextValue = textValue, + BoolValue = boolValue, + ChannelValue = channelValue, + ListValue = listValue, + NumberValue = numberValue, + TimeValue = timeValue, + UserValue = userValue, + }; + var contexts = this._testContextsFactory.CreateContexts(1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var testMappedConfigurationMock = new Mock(); + testMappedConfigurationMock.SetupGet(x => x.Name) + .Returns(command.Name); + var configurationServiceMock = new Mock(); + configurationServiceMock.Setup(x => x.GetConfigurationItems(It.IsAny())) + .Returns(new List { testMappedConfigurationMock.Object }); + + var configurationMapperServiceMock = new Mock(); + configurationMapperServiceMock.Setup(x => x.MapIntoBaseFormat(It.IsAny(), It.IsAny())) + .Returns(fixture.Create()); + + var configurationValueSetterMock = new Mock(); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, configurationMapperServiceMock.Object, configurationValueSetterMock.Object); + + // Act + await controller.SetCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("CustomConfigurationHasBeenSet", It.IsAny(), It.IsAny[]>()), Times.Once); + configurationValueSetterMock.Verify(x => x.SetDefaultValueForConfiguration(It.IsAny(), It.IsAny()), Times.Never); + configurationValueSetterMock + .Verify(x => x.SetConfigurationValueFromCommand(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); + } + } +} diff --git a/Watchman.Discord.UnitTests/TestObjectFactories/MessagesServiceMockWithResponsesFactory.cs b/Watchman.Discord.UnitTests/TestObjectFactories/MessagesServiceMockWithResponsesFactory.cs new file mode 100644 index 000000000..c0651fea7 --- /dev/null +++ b/Watchman.Discord.UnitTests/TestObjectFactories/MessagesServiceMockWithResponsesFactory.cs @@ -0,0 +1,22 @@ +using Devscord.DiscordFramework.Commands.Responses; +using Devscord.DiscordFramework.Services; +using Moq; +using System; +using System.Threading.Tasks; + +namespace Watchman.Discord.UnitTests.TestObjectFactories +{ + // TODO: Use this anywhere it's needed. + internal class MessagesServiceMockWithResponsesFactory + { + public Mock Create(Mock responsesServiceMock) + { + var messagesServiceMock = new Mock(); + messagesServiceMock.Setup(x => x.SendResponse(It.IsAny>())) + .Callback>(x => x.Invoke(responsesServiceMock.Object)) + .Returns(Task.CompletedTask); + + return messagesServiceMock; + } + } +} diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index 1c8ad4fb7..28de3f072 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -48,7 +48,6 @@ public async Task GetConfigurations(ConfigurationsCommand command, Contexts cont await messagesService.SendEmbedMessage("Konfiguracja", "Poniżej znajdziesz liste elementów konfiguracji", mapped); } - // TODO: Add tests public async Task SetCustomConfiguration(SetConfigurationCommand command, Contexts contexts) { var mappedConfiguration = this._configurationService.GetConfigurationItems(contexts.Server.Id) From 35d6095095e3ad2f8555c58f8a1d5b122313dbd4 Mon Sep 17 00:00:00 2001 From: DavidPL-coder Date: Sat, 13 Aug 2022 23:56:19 +0200 Subject: [PATCH 10/10] Add tests to RemoveCustomConfiguration. --- .../ConfigurationsControllerTests.cs | 92 +++++++++++++++++++ .../Controllers/ConfigurationsController.cs | 1 - 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs b/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs index 46ec2a450..8c7275da8 100644 --- a/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs +++ b/Watchman.Discord.UnitTests/Configurations/ConfigurationsControllerTests.cs @@ -14,6 +14,7 @@ using Watchman.Discord.UnitTests.TestObjectFactories; using Watchman.DomainModel.Configuration; using Watchman.DomainModel.Configuration.Services; +using DomainReponses = Watchman.DomainModel.Responses; namespace Watchman.Discord.UnitTests.Configurations { @@ -188,5 +189,96 @@ public async Task SetCustomConfiguration_ShouldSetCustomValue_WhenUserProvidedOn configurationValueSetterMock .Verify(x => x.SetConfigurationValueFromCommand(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny()), Times.Once); } + + [Test, AutoData] + public async Task RemoveCustomConfiguration_SendResponseServerDoesntHaveCustomValueForConfiguration_WhenProvidedConfigurationWillBeNotFound(RemoveConfigurationCommand command) + { + // Arrange + var contexts = this._testContextsFactory.CreateContexts(1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var configurationServiceMock = new Mock(); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, null, null); + + // Act + await controller.RemoveCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("ServerDoesntHaveCustomValueForConfiguration", It.IsAny(), It.IsAny[]>()), Times.Once); + configurationServiceMock.Verify(x => x.RemoveCustomConfiguration(It.IsAny()), Times.Never); + } + + [Test, AutoData] + public async Task RemoveCustomConfiguration_SendResponseServerDoesntHaveCustomValueForConfiguration_WhenProvidedConfigurationWillBeFoundAsDefault(RemoveConfigurationCommand command) + { + // Arrange + var contexts = this._testContextsFactory.CreateContexts(serverId: 1, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var testMappedConfigurationMock = new Mock(); + testMappedConfigurationMock.SetupGet(x => x.Name) + .Returns(command.Name); + testMappedConfigurationMock.SetupGet(x => x.ServerId) + .Returns(DomainReponses.Response.DEFAULT_SERVER_ID); + + var configurationServiceMock = new Mock(); + configurationServiceMock.Setup(x => x.GetConfigurationItems(It.IsAny())) + .Returns(new List { testMappedConfigurationMock.Object }); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, null, null); + + // Act + await controller.RemoveCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("ServerDoesntHaveCustomValueForConfiguration", It.IsAny(), It.IsAny[]>()), Times.Once); + configurationServiceMock.Verify(x => x.RemoveCustomConfiguration(It.IsAny()), Times.Never); + } + + [Test, AutoData] + public async Task RemoveCustomConfiguration_RemoveCustomConfigurationForServer(RemoveConfigurationCommand command, ulong serverId) + { + // Arrange + var contexts = this._testContextsFactory.CreateContexts(serverId, 1, 1); + + var responsesServiceMock = new Mock(); + var messagesServiceMock = this._messagesServiceMockFactory.Create(responsesServiceMock); + var messagesServiceFactoryMock = new Mock(); + messagesServiceFactoryMock.Setup(x => x.Create(It.IsAny())) + .Returns(messagesServiceMock.Object); + + var testMappedConfigurationMock = new Mock(); + testMappedConfigurationMock.SetupGet(x => x.Name) + .Returns(command.Name); + testMappedConfigurationMock.SetupGet(x => x.ServerId) + .Returns(serverId); + + var configurationServiceMock = new Mock(); + configurationServiceMock.Setup(x => x.GetConfigurationItems(It.IsAny())) + .Returns(new List { testMappedConfigurationMock.Object }); + + var controller = new ConfigurationsController(messagesServiceFactoryMock.Object, configurationServiceMock.Object, null, null); + + // Act + await controller.RemoveCustomConfiguration(command, contexts); + + // Assert + messagesServiceMock.Verify(x => x.SendResponse(It.IsAny>()), Times.Once); + responsesServiceMock.Verify(x => x.ProcessResponse("CustomConfigurationHasBeenRemoved", It.IsAny(), It.IsAny[]>()), Times.Once); + configurationServiceMock.Verify(x => x.RemoveCustomConfiguration(It.IsAny()), Times.Once); + } } } diff --git a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs index 28de3f072..12e8b9434 100644 --- a/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs +++ b/Watchman.Discord/Areas/Configurations/Controllers/ConfigurationsController.cs @@ -81,7 +81,6 @@ public async Task SetCustomConfiguration(SetConfigurationCommand command, Contex await messageService.SendResponse(x => x.CustomConfigurationHasBeenSet(contexts, command.Name)); } - // TODO: Add tests public async Task RemoveCustomConfiguration(RemoveConfigurationCommand command, Contexts contexts) { var mappedConfiguration = this._configurationService.GetConfigurationItems(contexts.Server.Id)