From 194d025660a24643fdc816f40470e9dd6f9d8121 Mon Sep 17 00:00:00 2001 From: Daniel-I-Am Date: Fri, 16 Oct 2020 16:43:54 +0200 Subject: [PATCH] Rework configuration through a root level helper --- ChaosBot/Configuration.cs | 65 +++++++++++++++++++ ChaosBot/Discord/DiscordConnect.cs | 5 +- ChaosBot/Discord/Modules/Admin/Config.cs | 2 +- ChaosBot/Discord/Modules/Admin/RankCheck.cs | 7 +- ChaosBot/Discord/Modules/User/Info.cs | 5 +- ChaosBot/Discord/Services/TimerHandler.cs | 3 +- ChaosBot/Models/ChaosbotContext.cs | 29 +++++++-- ChaosBot/Program.cs | 3 +- .../Repositories/ConfigurationRepository.cs | 6 +- ChaosBot/WebServer/App/DiscordController.cs | 8 ++- .../Services/DiscordInviteGenerator.cs | 2 +- ChaosBot/WebServer/Startup.cs | 2 +- ChaosBot/WebServer/WebServer.cs | 5 +- 13 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 ChaosBot/Configuration.cs diff --git a/ChaosBot/Configuration.cs b/ChaosBot/Configuration.cs new file mode 100644 index 0000000..1573f95 --- /dev/null +++ b/ChaosBot/Configuration.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using ChaosBot.Repositories; +using Microsoft.Extensions.Configuration; + +namespace ChaosBot +{ + public class Configuration + { + private readonly IConfiguration _appSettingsWrapper; + + private static readonly Dictionary ConfigurationFlags = new Dictionary + { + {"LevelUp:Enabled", typeof(bool)}, + }; + + public Configuration() + { + _appSettingsWrapper = Program.AppSettingsHandler; + + if (_appSettingsWrapper == null) + throw new NullReferenceException("Program.AppSettingsHandler is unset"); + } + + /** + * Gets the configuration value associated with a key in an optional guild + * Configuration key does not exist + * Configuration key does not have the provided type + * Configuration value + */ + public T GetValue(string key, T defaultValue, ulong? guildId = null) + { + if (!ConfigurationFlags.ContainsKey(key)) + throw new ArgumentException($"Configuration does not contain key '{key}'"); + + if (!(ConfigurationFlags[key] == typeof(T))) + throw new ArgumentException($"Configuration flag '{key}<{ConfigurationFlags[key]}>' does not have type '{typeof(T)}'"); + + if (guildId.HasValue) + return ConfigurationRepository.GetValue(key, guildId.Value, defaultValue); + + return _appSettingsWrapper.GetValue(key, defaultValue); + } + + public T GetValue(string key) + { + return GetValue(key, default); + } + + public IConfigurationSection GetSection(string key) + { + return _appSettingsWrapper.GetSection(key); + } + + /** + * Get the available configuration flags + * Immutable dictionary of config-key/type pairs + */ + public ImmutableDictionary GetConfigurationFlags() + { + return ConfigurationFlags.ToImmutableDictionary(); + } + } +} diff --git a/ChaosBot/Discord/DiscordConnect.cs b/ChaosBot/Discord/DiscordConnect.cs index c94424e..05ee3d3 100644 --- a/ChaosBot/Discord/DiscordConnect.cs +++ b/ChaosBot/Discord/DiscordConnect.cs @@ -28,9 +28,12 @@ namespace ChaosBot.Discord client.Log += Log; client.Ready += ReadyAsync; services.GetRequiredService().Log += Log; + + // Get the configuration handler + Configuration config = new Configuration(); // this is where we get the Token value from the configuration file, and start the bot - await client.LoginAsync(TokenType.Bot, Program.AppSettingsHandler.GetValue("Discord:Token")); + await client.LoginAsync(TokenType.Bot, config.GetValue("Discord:Token")); await client.StartAsync(); // we get the CommandHandler class here and call the InitializeAsync method to start things up for the CommandHandler service diff --git a/ChaosBot/Discord/Modules/Admin/Config.cs b/ChaosBot/Discord/Modules/Admin/Config.cs index c4ba8e7..f305aa4 100644 --- a/ChaosBot/Discord/Modules/Admin/Config.cs +++ b/ChaosBot/Discord/Modules/Admin/Config.cs @@ -83,7 +83,7 @@ namespace ChaosBot.Discord.Modules.Admin { using (ChaosbotContext dbContext = new ChaosbotContext()) { - Configuration cnfSet = new Configuration(); + Models.Configuration cnfSet = new Models.Configuration(); cnfSet.Key = key; cnfSet.DiscordGuildId = Context.Guild.Id; diff --git a/ChaosBot/Discord/Modules/Admin/RankCheck.cs b/ChaosBot/Discord/Modules/Admin/RankCheck.cs index e71bdd6..ca65164 100644 --- a/ChaosBot/Discord/Modules/Admin/RankCheck.cs +++ b/ChaosBot/Discord/Modules/Admin/RankCheck.cs @@ -109,10 +109,9 @@ namespace ChaosBot.Discord.Modules.Admin { using HttpClient client = new HttpClient(); - IConfigurationSection configurationSection = - Program.AppSettingsHandler.GetSection("Lodestone:ChaosBotApi"); - string endpoint = configurationSection.GetValue("Url"); - string apiToken = configurationSection.GetValue("ApiToken"); + Configuration config = new Configuration(); + string endpoint =config.GetValue("Lodestone:ChaosBotApi:Url"); + string apiToken = config.GetValue("Lodestone:ChaosBotApi:ApiToken"); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiToken); HttpResponseMessage result = diff --git a/ChaosBot/Discord/Modules/User/Info.cs b/ChaosBot/Discord/Modules/User/Info.cs index 553d79e..60af2c0 100644 --- a/ChaosBot/Discord/Modules/User/Info.cs +++ b/ChaosBot/Discord/Modules/User/Info.cs @@ -20,10 +20,11 @@ namespace ChaosBot.Discord.Modules.User { var sb = new StringBuilder(); var embed = new EmbedBuilder(); + Configuration config = new Configuration(); embed.WithColor(new Color(255, 255, 0)); - embed.Title = $"Information {Program.AppSettingsHandler.GetValue("Bot:Name")} v{Program.AppSettingsHandler.GetValue("Bot:Version")}"; - sb.AppendLine($"Prefix: {ConfigurationRepository.GetValue("Discord:Prefix", Context.Guild.Id)}"); + embed.Title = $"Information {config.GetValue("Bot:Name")} v{config.GetValue("Bot:Version")}"; + sb.AppendLine($"Prefix: {config.GetValue("Discord:Prefix", default(string), Context.Guild.Id)}"); /* * Add the string to the Embed diff --git a/ChaosBot/Discord/Services/TimerHandler.cs b/ChaosBot/Discord/Services/TimerHandler.cs index fe5850b..480d5ed 100644 --- a/ChaosBot/Discord/Services/TimerHandler.cs +++ b/ChaosBot/Discord/Services/TimerHandler.cs @@ -15,8 +15,9 @@ namespace ChaosBot.Discord.Services public static void Initialize(IServiceProvider services) { _client = services.GetRequiredService(); + Configuration config = new Configuration(); - foreach (IConfigurationSection serverConfig in Program.AppSettingsHandler.GetSection("Servers").GetChildren()) + foreach (IConfigurationSection serverConfig in config.GetSection("Servers").GetChildren()) { long? lodestoneChannelSloganDescriptionId = serverConfig.GetValue("Lodestone:SloganDescription:Channel", null); int refreshMinutes = serverConfig.GetValue("Lodestone:SloganDescription:RefreshMinutes", 60); diff --git a/ChaosBot/Models/ChaosbotContext.cs b/ChaosBot/Models/ChaosbotContext.cs index ced2e6f..b307f66 100644 --- a/ChaosBot/Models/ChaosbotContext.cs +++ b/ChaosBot/Models/ChaosbotContext.cs @@ -19,17 +19,32 @@ namespace ChaosBot.Models { if (!optionsBuilder.IsConfigured) { + string server, user, pass, name; + int port; + if (Program.AppSettingsHandler == null) { - Program.AppSettingsHandler = new ConfigurationBuilder() + IConfiguration config = Program.AppSettingsHandler = new ConfigurationBuilder() .SetBasePath(System.IO.Directory.GetCurrentDirectory()) .AddJsonFile("./appsettings.json", optional: false, reloadOnChange: true).Build(); + + server = config.GetValue("Database:Host"); + port = config.GetValue("Database:Port"); + user = config.GetValue("Database:User"); + pass = config.GetValue("Database:Pass"); + name = config.GetValue("Database:Name"); } - string server = Program.AppSettingsHandler.GetValue("Database:Host"); - int port = Program.AppSettingsHandler.GetValue("Database:Port"); - string user = Program.AppSettingsHandler.GetValue("Database:User"); - string pass = Program.AppSettingsHandler.GetValue("Database:Pass"); - string name = Program.AppSettingsHandler.GetValue("Database:Name"); + else + { + ChaosBot.Configuration config = new ChaosBot.Configuration(); + + server = config.GetValue("Database:Host"); + port = config.GetValue("Database:Port"); + user = config.GetValue("Database:User"); + pass = config.GetValue("Database:Pass"); + name = config.GetValue("Database:Name"); + } + optionsBuilder.UseMySql( $"server={server};port={port};user={user};password={pass};database={name}", x => x.ServerVersion("5.5.64-mariadb")); @@ -54,4 +69,4 @@ namespace ChaosBot.Models .HasKey(x => new {x.DiscordGuildId, x.Command}); } } -} \ No newline at end of file +} diff --git a/ChaosBot/Program.cs b/ChaosBot/Program.cs index 500e4d1..9fe2151 100644 --- a/ChaosBot/Program.cs +++ b/ChaosBot/Program.cs @@ -42,7 +42,8 @@ namespace ChaosBot /* * Initialize the Discord Client and Login */ - _logger.Info($"Starting Up {AppSettingsHandler.GetValue("Bot:Name")} v{AppSettingsHandler.GetValue("Bot:Version")}"); + Configuration config = new Configuration(); + _logger.Info($"Starting Up {config.GetValue("Bot:Name")} v{config.GetValue("Bot:Version")}"); try { diff --git a/ChaosBot/Repositories/ConfigurationRepository.cs b/ChaosBot/Repositories/ConfigurationRepository.cs index e85c9de..ca21996 100644 --- a/ChaosBot/Repositories/ConfigurationRepository.cs +++ b/ChaosBot/Repositories/ConfigurationRepository.cs @@ -17,7 +17,7 @@ namespace ChaosBot.Repositories { using (ChaosbotContext dbContext = new ChaosbotContext()) { - Configuration config = dbContext.Configuration + Models.Configuration config = dbContext.Configuration .SingleOrDefault(c => c.DiscordGuildId == guildId && c.Key == key); if (config == null || string.IsNullOrEmpty(config.SerializedValue)) return GetValueFromAppSettings(key, guildId, defaultValue); @@ -29,7 +29,7 @@ namespace ChaosBot.Repositories { using (ChaosbotContext dbContext = new ChaosbotContext()) { - Configuration config = dbContext.Configuration + Models.Configuration config = dbContext.Configuration .SingleOrDefault(c => c.DiscordGuildId == guildId && c.Key == key); if (config == null) return; dbContext.Remove(config); @@ -42,4 +42,4 @@ namespace ChaosBot.Repositories return Program.AppSettingsHandler.GetValue($"Servers:{guildId}:{key}", Program.AppSettingsHandler.GetValue(key, defaultValue)); } } -} \ No newline at end of file +} diff --git a/ChaosBot/WebServer/App/DiscordController.cs b/ChaosBot/WebServer/App/DiscordController.cs index 48e6247..b568e41 100644 --- a/ChaosBot/WebServer/App/DiscordController.cs +++ b/ChaosBot/WebServer/App/DiscordController.cs @@ -36,9 +36,11 @@ namespace ChaosBot.WebServer.App [HttpGet] public async Task Index(string code = null) { - string redirectUri = $"{Program.AppSettingsHandler.GetValue("Discord:BaseUri")}/api/discord"; - string clientId = Program.AppSettingsHandler.GetValue("Discord:ClientId"); - string clientSecret = Program.AppSettingsHandler.GetValue("Discord:ClientSecret"); + Configuration config = new Configuration(); + + string redirectUri = $"{config.GetValue("Discord:BaseUri")}/api/discord"; + string clientId = config.GetValue("Discord:ClientId"); + string clientSecret = config.GetValue("Discord:ClientSecret"); if (code == null) return Redirect($"https://discord.com/api/oauth2/authorize?client_id={clientId}&redirect_uri={redirectUri}&response_type=code&scope=identify%20guilds"); diff --git a/ChaosBot/WebServer/Services/DiscordInviteGenerator.cs b/ChaosBot/WebServer/Services/DiscordInviteGenerator.cs index 088c616..0c3684a 100644 --- a/ChaosBot/WebServer/Services/DiscordInviteGenerator.cs +++ b/ChaosBot/WebServer/Services/DiscordInviteGenerator.cs @@ -6,7 +6,7 @@ namespace ChaosBot.WebServer.Services { public string Generate() { - string clientId = Program.AppSettingsHandler.GetValue("Discord:ClientId"); + string clientId = new Configuration().GetValue("Discord:ClientId"); const ulong permissions = 0x00000020 + // MANAGE_CHANNELS 0x04000000 + // CHANGE_NICKNAME diff --git a/ChaosBot/WebServer/Startup.cs b/ChaosBot/WebServer/Startup.cs index 90607ff..a35b965 100644 --- a/ChaosBot/WebServer/Startup.cs +++ b/ChaosBot/WebServer/Startup.cs @@ -42,7 +42,7 @@ namespace ChaosBot.WebServer { LoggingFacade.Info("Initializing Kestrel Startup and Configuration"); - if (Program.AppSettingsHandler.GetValue("WebServer:Debug", false)) + if (new Configuration().GetValue("WebServer:Debug", false)) app.UseDeveloperExceptionPage(); app.UseForwardedHeaders(); diff --git a/ChaosBot/WebServer/WebServer.cs b/ChaosBot/WebServer/WebServer.cs index 2d7d8dd..71a3a13 100644 --- a/ChaosBot/WebServer/WebServer.cs +++ b/ChaosBot/WebServer/WebServer.cs @@ -22,12 +22,13 @@ namespace ChaosBot.WebServer { string contentRoot = Directory.GetCurrentDirectory(); string webRoot = Path.Combine(contentRoot, "wwwroot/dist"); + Configuration config = new Configuration(); webBuilder.UseContentRoot(contentRoot); webBuilder.UseWebRoot(webRoot); webBuilder.ConfigureKestrel(serverOptions => { - serverOptions.Listen(IPAddress.Any, Program.AppSettingsHandler.GetValue("WebServer:Port"), + serverOptions.Listen(IPAddress.Any, config.GetValue("WebServer:Port", 80), listenOptions => { listenOptions.UseConnectionLogging(); @@ -37,7 +38,7 @@ namespace ChaosBot.WebServer { logging.ClearProviders(); logging.SetMinimumLevel(LogLevel.Trace); - logging.AddNLog(new NLogLoggingConfiguration(Program.AppSettingsHandler.GetSection("NLog"))); + logging.AddNLog(new NLogLoggingConfiguration(config.GetSection("NLog"))); }) .UseStartup(); });