using RegexBot.Modules.ModCommands.Commands; using System.Collections.ObjectModel; using System.Reflection; namespace RegexBot.Modules.ModCommands; class ModuleConfig { public ReadOnlyDictionary Commands { get; } public ModuleConfig(ModCommands instance, JToken conf) { if (conf.Type != JTokenType.Array) throw new ModuleLoadException("Command definitions must be defined as objects in a JSON array."); // Command instance creation var commands = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var def in conf.Children()) { string Label; Label = def[nameof(Label)]?.Value() ?? throw new ModuleLoadException($"'{nameof(Label)}' was not defined in a command definition."); var cmd = CreateCommandInstance(instance, def); if (commands.ContainsKey(cmd.Command)) { throw new ModuleLoadException( $"{Label}: The command name '{cmd.Command}' is already in use by '{commands[cmd.Command].Label}'."); } commands.Add(cmd.Command, cmd); } Commands = new ReadOnlyDictionary(commands); } private static readonly ReadOnlyDictionary _commandTypes = new( new Dictionary(StringComparer.OrdinalIgnoreCase) { { "ban", typeof(Ban) }, { "confreload", typeof(ConfReload) }, { "kick", typeof(Kick) }, { "say", typeof(Say) }, { "unban", typeof(Unban) }, { "note", typeof(Note) }, { "addnote", typeof(Note) }, { "warn", typeof(Warn) }, { "addrole", typeof(RoleAdd) }, { "roleadd", typeof(RoleAdd) }, { "delrole", typeof(RoleDel) }, { "roledel", typeof(RoleDel) } } ); private static CommandConfig CreateCommandInstance(ModCommands instance, JObject def) { var label = def[nameof(CommandConfig.Label)]?.Value()!; var command = def[nameof(CommandConfig.Command)]?.Value(); if (string.IsNullOrWhiteSpace(command)) throw new ModuleLoadException($"{label}: '{nameof(CommandConfig.Command)}' was not specified."); if (command.Contains(' ')) throw new ModuleLoadException($"{label}: '{nameof(CommandConfig.Command)}' must not contain spaces."); string? Type; Type = def[nameof(Type)]?.Value(); if (string.IsNullOrWhiteSpace(Type)) throw new ModuleLoadException($"'{nameof(Type)}' must be specified within definition for '{label}'."); if (!_commandTypes.TryGetValue(Type, out Type? cmdType)) { throw new ModuleLoadException($"{label}: '{nameof(Type)}' does not have a valid value."); } else { try { return (CommandConfig)Activator.CreateInstance(cmdType, instance, def)!; } catch (TargetInvocationException ex) when (ex.InnerException is ModuleLoadException) { throw new ModuleLoadException($"{label}: {ex.InnerException.Message}"); } } } }