diff --git a/Module/ModTools/ConfigItem.cs b/Module/ModTools/ConfigItem.cs
new file mode 100644
index 0000000..a135a3f
--- /dev/null
+++ b/Module/ModTools/ConfigItem.cs
@@ -0,0 +1,75 @@
+using Newtonsoft.Json.Linq;
+using Noikoio.RegexBot.ConfigItem;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Noikoio.RegexBot.Module.ModTools
+{
+ ///
+ /// Represents ModTools configuration within one server.
+ ///
+ class ConfigItem
+ {
+ private EntityName? _petitionReportCh;
+ private readonly ReadOnlyDictionary _cmdInstances;
+
+ public EntityName? PetitionReportingChannel => _petitionReportCh;
+ public ReadOnlyDictionary Commands => _cmdInstances;
+
+ public ConfigItem(ModTools instance, JToken inconf)
+ {
+ if (inconf.Type != JTokenType.Object)
+ {
+ throw new RuleImportException("Configuration for this section is invalid.");
+ }
+ var config = (JObject)inconf;
+
+ // Ban petition reporting channel
+ var petitionstr = config["PetitionRelay"]?.Value();
+ if (string.IsNullOrEmpty(petitionstr)) _petitionReportCh = null;
+ else if (petitionstr.Length > 1 && petitionstr[0] != '#')
+ {
+ // Not a channel.
+ throw new RuleImportException("PetitionRelay value must be set to a channel.");
+ }
+ else
+ {
+ _petitionReportCh = new EntityName(petitionstr.Substring(1), EntityType.Channel);
+ }
+
+ // Command instances
+ var commands = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ var commandconf = config["Commands"];
+ if (commandconf != null)
+ {
+ if (commandconf.Type != JTokenType.Object)
+ {
+ throw new RuleImportException("CommandDefs is not properly defined.");
+ }
+
+ foreach (var def in commandconf.Children())
+ {
+ string label = def.Name;
+ var cmd = CommandBase.CreateInstance(instance, def);
+ if (commands.ContainsKey(cmd.Command))
+ throw new RuleImportException(
+ $"{label}: 'command' value must not be equal to that of another definition. " +
+ $"Given value is being used for {commands[cmd.Command].Label}.");
+
+ commands.Add(cmd.Command, cmd);
+ }
+ }
+ _cmdInstances = new ReadOnlyDictionary(commands);
+ }
+
+ public void UpdatePetitionChannel(ulong id)
+ {
+ if (!PetitionReportingChannel.HasValue) return;
+ if (PetitionReportingChannel.Value.Id.HasValue) return; // nothing to update
+
+ // For lack of a better option - create a new EntityName with ID already provided
+ _petitionReportCh = new EntityName($"{id}::{PetitionReportingChannel.Value.Name}", EntityType.Channel);
+ }
+ }
+}
diff --git a/Module/ModTools/ModTools.cs b/Module/ModTools/ModTools.cs
index a9d4632..0c505b8 100644
--- a/Module/ModTools/ModTools.cs
+++ b/Module/ModTools/ModTools.cs
@@ -4,7 +4,6 @@ using Newtonsoft.Json.Linq;
using Noikoio.RegexBot.ConfigItem;
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@@ -28,71 +27,23 @@ namespace Noikoio.RegexBot.Module.ModTools
if (arg.Channel is IDMChannel) await PetitionRelayCheck(arg);
else if (arg.Channel is IGuildChannel) await CommandCheckInvoke(arg);
}
-
- #region Config
+
[ConfigSection("modtools")]
public override async Task