using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; namespace ChaosBot.ConfigHelpers { public class Configuration { private readonly IConfiguration _appSettingsWrapper; private static readonly Dictionary ConfigurationFlags = new Dictionary { {"Bot:Name", new ConfigurationDetails("Bot:Name", "ChaosBot", true)}, {"Bot:Version", new ConfigurationDetails("Bot:Version", "1.0.0", true)}, {"WebServer:Port", new ConfigurationDetails("WebServer:Port", 8080, true)}, {"WebServer:Debug", new ConfigurationDetails("WebServer:Debug", false, true)}, {"Discord:Prefix", new ConfigurationDetails("Discord:Prefix", "!", true)}, {"Discord:Token", new ConfigurationDetails("Discord:Token", "SECRET_TOKEN", true)}, {"Discord:BaseUri", new ConfigurationDetails("Discord:BaseUri", "http://localhost:8080/", true)}, {"Discord:ClientId", new ConfigurationDetails("Discord:ClientId", "1234567890", true)}, {"Discord:ClientSecret", new ConfigurationDetails("Discord:ClientSecret", "1234567890_SECRET_TOKEN", true)}, {"Lodestone:ChaosBotApi:ApiToken", new ConfigurationDetails("Lodestone:ChaosBotApi:ApiToken", "SECRET_TOKEN", true)}, {"Lodestone:ChaosBotApi:Url", new ConfigurationDetails("Lodestone:ChaosBotApi:Url", "http://locahost:8000", true)}, {"Database:Host", new ConfigurationDetails("Database:Host", "localhost", true)}, {"Database:Port", new ConfigurationDetails("Database:Port", 3306, true)}, {"Database:User", new ConfigurationDetails("Database:User", "root", true)}, {"Database:Pass", new ConfigurationDetails("Database:Pass", "password", true)}, {"Database:Name", new ConfigurationDetails("Database:Name", "chaosbot", true)}, {"Module:Experience:Enabled", new ConfigurationDetails("Module:Experience:Enabled", true, false)}, {"LevelUp:Channel", new ConfigurationDetails("LevelUp:Channel", null, false)}, {"LevelUp:MentionUser", new ConfigurationDetails("LevelUp:MentionUser", true, false)}, }; public Configuration() { _appSettingsWrapper = GetAppSettingsWrapper(); } public IConfigurationDetails GetByKey(string key) { if (ConfigurationFlags.TryGetValue(key, out IConfigurationDetails details)) { return details; } throw new ArgumentException($"Configuration '{key}' is not available"); } public IConfigurationDetails GetByKey(string key) { IConfigurationDetails configurationDetails = GetByKey(key); if (configurationDetails.Type != typeof(T)) throw new ArgumentException($"Configuration flag '{key}' is not of type '{typeof(T)}'"); return (IConfigurationDetails) configurationDetails; } internal static IConfiguration GetAppSettingsWrapper() { if (Program.AppSettingsHandler == null) throw new NullReferenceException("Program.AppSettingsHandler is unset"); return Program.AppSettingsHandler; } public ImmutableDictionary GetConfigurationFlags() { return ConfigurationFlags.ToImmutableDictionary(); } public IConfigurationSection GetSection(string key) { return _appSettingsWrapper.GetSection(key); } } public interface IConfigurationDetails { string Key { get; } bool Restricted { get; } Type Type { get; } object DefaultValue { get; } string GetStringValue(ulong guildId); void SetValueFromString(string value, ulong guildId); void DeleteValue(ulong guildId); } public interface IConfigurationDetails : IConfigurationDetails { new T DefaultValue { get; } T GetValue(ulong? guildId = null, bool readRestricted = false); T GetValue(T defaultValue, ulong? guildId = null, bool readRestricted = false); void SetValue(T value, ulong guildId); } public class ConfigurationDetails : IConfigurationDetails { public string Key { get; } public bool Restricted { get; } public T DefaultValue { get; } object IConfigurationDetails.DefaultValue => DefaultValue; public Type Type => typeof(T); public ConfigurationDetails(string key, T defaultValue, bool restricted) { Key = key; DefaultValue = defaultValue; Restricted = restricted; } public T GetValue(ulong? guildId = null, bool readRestricted = false) { return GetValue(DefaultValue, guildId, readRestricted); } public T GetValue(T defaultValue, ulong? guildId = null, bool readRestricted = false) { if (!readRestricted && Restricted) throw new UnauthorizedAccessException($"Configuration key '{Key}' is restricted"); if (guildId.HasValue) { return ConfigurationRepository.GetValue(Key, guildId.Value, defaultValue); } return Configuration.GetAppSettingsWrapper().GetValue(Key, defaultValue); } public string GetStringValue(ulong guildId) { return GetValue(guildId: guildId).ToString(); } public void SetValue(T value, ulong guildId) { if (Restricted) throw new UnauthorizedAccessException($"Configuration key '{Key}' is restricted"); ConfigurationRepository.SetValue(Key, value, guildId); } public void SetValueFromString(string value, ulong guildId) { SetValue((T)Convert.ChangeType(value, typeof(T)), guildId); } public void DeleteValue(ulong guildId) { if (Restricted) throw new UnauthorizedAccessException($"Configuration key '{Key}' is restricted"); ConfigurationRepository.DeleteValue(Key, guildId); } } }