Removed manual module name setting

Modules will now be named based on their existing class name.
Their respective configuration sections are now also defined by the
same value. Documentation has been updated to reflect this.
This commit is contained in:
Noikoio 2018-03-21 23:27:19 -07:00
parent 8e80e0241b
commit 287bb33d77
21 changed files with 33 additions and 106 deletions

View file

@ -14,7 +14,7 @@ namespace Noikoio.RegexBot
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
private readonly AsyncLogger _logger; private readonly AsyncLogger _logger;
public abstract string Name { get; } public string Name => this.GetType().Name;
protected DiscordSocketClient Client => _client; protected DiscordSocketClient Client => _client;
public BotModule(DiscordSocketClient client) public BotModule(DiscordSocketClient client)
@ -80,25 +80,4 @@ namespace Noikoio.RegexBot
public sealed override int GetHashCode() => base.GetHashCode(); public sealed override int GetHashCode() => base.GetHashCode();
public sealed override string ToString() => base.ToString(); public sealed override string ToString() => base.ToString();
} }
/// <summary>
/// Indicates which section under an individual Discord guild configuration should be passed to the
/// module's <see cref="BotModule.ProcessConfiguration(JToken)"/> method during configuration load.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class ConfigSectionAttribute : Attribute
{
private readonly string _sectionName;
public string SectionName => _sectionName;
public ConfigSectionAttribute(string sectionName)
{
if (string.IsNullOrWhiteSpace(sectionName))
{
throw new ArgumentNullException("Configuration section name cannot be blank.");
}
_sectionName = sectionName;
}
}
} }

View file

@ -162,16 +162,12 @@ namespace Noikoio.RegexBot
Dictionary<BotModule, object> customConfs = new Dictionary<BotModule, object>(); Dictionary<BotModule, object> customConfs = new Dictionary<BotModule, object>();
foreach (var item in _bot.Modules) foreach (var item in _bot.Modules)
{ {
var attr = item.GetType().GetTypeInfo() var confSection = item.Name;
.GetMethod("ProcessConfiguration").GetCustomAttribute<ConfigSectionAttribute>();
if (attr == null) var section = sconf[confSection];
{
await SLog("No additional configuration for " + item.Name);
continue;
}
var section = sconf[attr.SectionName];
if (section == null) if (section == null)
{ {
// Section not in config. Do not call loader method.
await SLog("Additional configuration not defined for " + item.Name); await SLog("Additional configuration not defined for " + item.Name);
continue; continue;
} }
@ -191,8 +187,7 @@ namespace Noikoio.RegexBot
customConfs.Add(item, result); customConfs.Add(item, result);
} }
// Switch to new configuration
// Switch to using new data
List<Tuple<Regex, string[]>> rulesfinal = new List<Tuple<Regex, string[]>>(); List<Tuple<Regex, string[]>> rulesfinal = new List<Tuple<Regex, string[]>>();
newservers.Add(new ServerConfig(sid, mods, new ReadOnlyDictionary<BotModule, object>(customConfs))); newservers.Add(new ServerConfig(sid, mods, new ReadOnlyDictionary<BotModule, object>(customConfs)));
} }

View file

@ -15,8 +15,6 @@ namespace Noikoio.RegexBot.EntityCache
{ {
private readonly DatabaseConfig _db; private readonly DatabaseConfig _db;
public override string Name => nameof(EntityCache);
public Module(DiscordSocketClient client) : base(client) public Module(DiscordSocketClient client) : base(client)
{ {
if (RegexBot.Config.DatabaseAvailable) if (RegexBot.Config.DatabaseAvailable)

View file

@ -16,15 +16,12 @@ namespace Noikoio.RegexBot.Module.AutoMod
/// </remarks> /// </remarks>
class AutoMod : BotModule class AutoMod : BotModule
{ {
public override string Name => "AutoMod";
public AutoMod(DiscordSocketClient client) : base(client) public AutoMod(DiscordSocketClient client) : base(client)
{ {
client.MessageReceived += CMessageReceived; client.MessageReceived += CMessageReceived;
client.MessageUpdated += CMessageUpdated; client.MessageUpdated += CMessageUpdated;
} }
[ConfigSection("automod")]
public override async Task<object> ProcessConfiguration(JToken configSection) public override async Task<object> ProcessConfiguration(JToken configSection)
{ {
List<ConfigItem> rules = new List<ConfigItem>(); List<ConfigItem> rules = new List<ConfigItem>();

View file

@ -22,8 +22,6 @@ namespace Noikoio.RegexBot.Module.AutoRespond
partial class AutoRespond : BotModule partial class AutoRespond : BotModule
{ {
#region BotModule implementation #region BotModule implementation
public override string Name => "AutoRespond";
public AutoRespond(DiscordSocketClient client) : base(client) public AutoRespond(DiscordSocketClient client) : base(client)
{ {
client.MessageReceived += Client_MessageReceived; client.MessageReceived += Client_MessageReceived;
@ -42,7 +40,6 @@ namespace Noikoio.RegexBot.Module.AutoRespond
await Task.Run(async () => await ProcessMessage(arg, def)); await Task.Run(async () => await ProcessMessage(arg, def));
} }
[ConfigSection("autoresponses")]
public override async Task<object> ProcessConfiguration(JToken configSection) public override async Task<object> ProcessConfiguration(JToken configSection)
{ {
var responses = new List<ConfigItem>(); var responses = new List<ConfigItem>();

View file

@ -12,8 +12,6 @@ namespace Noikoio.RegexBot.Module.DMLogger
/// </summary> /// </summary>
class DMLogger : BotModule class DMLogger : BotModule
{ {
public override string Name => nameof(DMLogger);
public DMLogger(DiscordSocketClient client) : base(client) public DMLogger(DiscordSocketClient client) : base(client)
{ {
client.MessageReceived += Client_MessageReceived; client.MessageReceived += Client_MessageReceived;

View file

@ -14,8 +14,6 @@ namespace Noikoio.RegexBot.Module.EntryAutoRole
/// </summary> /// </summary>
class EntryAutoRole : BotModule class EntryAutoRole : BotModule
{ {
public override string Name => "EntryAutoRole";
private List<AutoRoleEntry> _roleWaitlist; private List<AutoRoleEntry> _roleWaitlist;
private object _roleWaitLock = new object(); private object _roleWaitLock = new object();
@ -38,7 +36,6 @@ namespace Noikoio.RegexBot.Module.EntryAutoRole
Task.Factory.StartNew(Worker, _workerCancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); Task.Factory.StartNew(Worker, _workerCancel.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
} }
[ConfigSection("EntryAutoRole")]
public override Task<object> ProcessConfiguration(JToken configSection) public override Task<object> ProcessConfiguration(JToken configSection)
{ {
if (configSection.Type != JTokenType.Object) if (configSection.Type != JTokenType.Object)

View file

@ -25,7 +25,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
// "notifymsg" - Message to send to the target user being acted upon. Default message is used // "notifymsg" - Message to send to the target user being acted upon. Default message is used
// if the value is not specified. If a blank value is given, the feature is disabled. // if the value is not specified. If a blank value is given, the feature is disabled.
// Takes the special values $s for server name and $r for reason text. // Takes the special values $s for server name and $r for reason text.
protected BanKick(CommandListener l, string label, JObject conf, CommandMode mode) : base(l, label, conf) protected BanKick(ModCommands l, string label, JObject conf, CommandMode mode) : base(l, label, conf)
{ {
_mode = mode; _mode = mode;
_forceReason = conf["forcereason"]?.Value<bool>() ?? false; _forceReason = conf["forcereason"]?.Value<bool>() ?? false;
@ -199,13 +199,13 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
class Ban : BanKick class Ban : BanKick
{ {
public Ban(CommandListener l, string label, JObject conf) public Ban(ModCommands l, string label, JObject conf)
: base(l, label, conf, CommandMode.Ban) { } : base(l, label, conf, CommandMode.Ban) { }
} }
class Kick : BanKick class Kick : BanKick
{ {
public Kick(CommandListener l, string label, JObject conf) public Kick(ModCommands l, string label, JObject conf)
: base(l, label, conf, CommandMode.Kick) { } : base(l, label, conf, CommandMode.Kick) { }
} }
} }

View file

@ -7,7 +7,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
class ConfReload : Command class ConfReload : Command
{ {
// No configuration. // No configuration.
public ConfReload(CommandListener l, string label, JObject conf) : base(l, label, conf) { } public ConfReload(ModCommands l, string label, JObject conf) : base(l, label, conf) { }
// Usage: (command) // Usage: (command)
public override async Task Invoke(SocketGuild g, SocketMessage msg) public override async Task Invoke(SocketGuild g, SocketMessage msg)

View file

@ -19,7 +19,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
// "role" - string; The given role that applies to this command. // "role" - string; The given role that applies to this command.
// "successmsg" - string; Messages to display on command success. Overrides default. // "successmsg" - string; Messages to display on command success. Overrides default.
protected RoleManipulation(CommandListener l, string label, JObject conf, CommandMode mode) : base(l, label, conf) protected RoleManipulation(ModCommands l, string label, JObject conf, CommandMode mode) : base(l, label, conf)
{ {
_mode = mode; _mode = mode;
var rolestr = conf["role"]?.Value<string>(); var rolestr = conf["role"]?.Value<string>();
@ -123,11 +123,11 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
class RoleAdd : RoleManipulation class RoleAdd : RoleManipulation
{ {
public RoleAdd(CommandListener l, string label, JObject conf) : base(l, label, conf, CommandMode.Add) { } public RoleAdd(ModCommands l, string label, JObject conf) : base(l, label, conf, CommandMode.Add) { }
} }
class RoleDel : RoleManipulation class RoleDel : RoleManipulation
{ {
public RoleDel(CommandListener l, string label, JObject conf) : base(l, label, conf, CommandMode.Del) { } public RoleDel(ModCommands l, string label, JObject conf) : base(l, label, conf, CommandMode.Del) { }
} }
} }

View file

@ -9,7 +9,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
{ {
// No configuration at the moment. // No configuration at the moment.
// TODO: Whitelist/blacklist - to limit which channels it can "say" into // TODO: Whitelist/blacklist - to limit which channels it can "say" into
public Say(CommandListener l, string label, JObject conf) : base(l, label, conf) { public Say(ModCommands l, string label, JObject conf) : base(l, label, conf) {
DefaultUsageMsg = $"{this.Trigger} [channel] [message]\n" DefaultUsageMsg = $"{this.Trigger} [channel] [message]\n"
+ "Displays the given message exactly as specified to the given channel."; + "Displays the given message exactly as specified to the given channel.";
} }

View file

@ -10,7 +10,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
// No configuration. // No configuration.
// TODO bring in some options from BanKick. Particularly custom success msg. // TODO bring in some options from BanKick. Particularly custom success msg.
// TODO when ModLogs fully implemented, add a reason? // TODO when ModLogs fully implemented, add a reason?
public Unban(CommandListener l, string label, JObject conf) : base(l, label, conf) { public Unban(ModCommands l, string label, JObject conf) : base(l, label, conf) {
DefaultUsageMsg = $"{this.Trigger} [user or user ID]\n" DefaultUsageMsg = $"{this.Trigger} [user or user ID]\n"
+ "Unbans the given user, allowing them to rejoin the server."; + "Unbans the given user, allowing them to rejoin the server.";
} }

View file

@ -16,20 +16,20 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
/// <summary> /// <summary>
/// Base class for a command within the module. /// Base class for a command within the module.
/// After implementing, don't forget to add a reference to /// After implementing, don't forget to add a reference to
/// <see cref="CreateInstance(CommandListener, JProperty)"/>. /// <see cref="CreateInstance(ModCommands, JProperty)"/>.
/// </summary> /// </summary>
[DebuggerDisplay("Command def: {Label}")] [DebuggerDisplay("Command def: {Label}")]
abstract class Command abstract class Command
{ {
private readonly CommandListener _mod; private readonly ModCommands _mod;
private readonly string _label; private readonly string _label;
private readonly string _command; private readonly string _command;
protected CommandListener Module => _mod; protected ModCommands Module => _mod;
public string Label => _label; public string Label => _label;
public string Trigger => _command; public string Trigger => _command;
public Command(CommandListener l, string label, JObject conf) public Command(ModCommands l, string label, JObject conf)
{ {
_mod = l; _mod = l;
_label = label; _label = label;
@ -58,7 +58,7 @@ namespace Noikoio.RegexBot.Module.ModCommands.Commands
{ "delrole", typeof(RoleDel) } { "delrole", typeof(RoleDel) }
}); });
public static Command CreateInstance(CommandListener root, JProperty def) public static Command CreateInstance(ModCommands root, JProperty def)
{ {
string label = def.Name; string label = def.Name;
if (string.IsNullOrWhiteSpace(label)) throw new RuleImportException("Label cannot be blank."); if (string.IsNullOrWhiteSpace(label)) throw new RuleImportException("Label cannot be blank.");

View file

@ -16,7 +16,7 @@ namespace Noikoio.RegexBot.Module.ModCommands
public ReadOnlyDictionary<string, Command> Commands => _cmdInstances; public ReadOnlyDictionary<string, Command> Commands => _cmdInstances;
public ConfigItem(CommandListener instance, JToken inconf) public ConfigItem(ModCommands instance, JToken inconf)
{ {
if (inconf.Type != JTokenType.Object) if (inconf.Type != JTokenType.Object)
{ {

View file

@ -17,11 +17,9 @@ namespace Noikoio.RegexBot.Module.ModCommands
/// done in a way that would easily allow for flexibility and modifications during runtime. /// done in a way that would easily allow for flexibility and modifications during runtime.
/// Thus, reinventing the wheel right here. /// Thus, reinventing the wheel right here.
/// </remarks> /// </remarks>
class CommandListener : BotModule class ModCommands : BotModule
{ {
public override string Name => "ModCommands"; public ModCommands(DiscordSocketClient client) : base(client)
public CommandListener(DiscordSocketClient client) : base(client)
{ {
client.MessageReceived += Client_MessageReceived; client.MessageReceived += Client_MessageReceived;
} }
@ -34,7 +32,6 @@ namespace Noikoio.RegexBot.Module.ModCommands
if (arg.Channel is IGuildChannel) await CommandCheckInvoke(arg); if (arg.Channel is IGuildChannel) await CommandCheckInvoke(arg);
} }
[ConfigSection("ModCommands")]
public override async Task<object> ProcessConfiguration(JToken configSection) public override async Task<object> ProcessConfiguration(JToken configSection)
{ {
// Constructor throws exception on config errors // Constructor throws exception on config errors

View file

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Discord.WebSocket;
using Newtonsoft.Json.Linq;
namespace Noikoio.RegexBot.Module.ModLogs
{
/// <summary>
/// Listens for Discord-based events and writes them to the log (database).
/// Additionally writes certain messages to a designated logging channel if configured.
/// </summary>
class EventListener : BotModule
{
public override string Name => "ModLogs";
public EventListener(DiscordSocketClient client) : base(client)
{
}
[ConfigSection("modlogs")]
public override Task<object> ProcessConfiguration(JToken configSection)
{
throw new NotImplementedException();
}
}
}

View file

@ -11,8 +11,6 @@ namespace Noikoio.RegexBot.Module.ModLogs
/// </summary> /// </summary>
class ModLogs : BotModule class ModLogs : BotModule
{ {
public override string Name => "ModLogs";
private readonly MessageCache _msgCacheInstance; private readonly MessageCache _msgCacheInstance;
public ModLogs(DiscordSocketClient client) : base(client) public ModLogs(DiscordSocketClient client) : base(client)
@ -27,7 +25,6 @@ namespace Noikoio.RegexBot.Module.ModLogs
// TODO add handler for processing the log query command // TODO add handler for processing the log query command
} }
[ConfigSection("ModLogs")]
public override async Task<object> ProcessConfiguration(JToken configSection) public override async Task<object> ProcessConfiguration(JToken configSection)
{ {
if (configSection.Type != JTokenType.Object) if (configSection.Type != JTokenType.Object)

View file

@ -56,7 +56,7 @@ namespace Noikoio.RegexBot
{ {
new Module.DMLogger.DMLogger(_client), new Module.DMLogger.DMLogger(_client),
new Module.AutoMod.AutoMod(_client), new Module.AutoMod.AutoMod(_client),
new Module.ModCommands.CommandListener(_client), new Module.ModCommands.ModCommands(_client),
new Module.AutoRespond.AutoRespond(_client), new Module.AutoRespond.AutoRespond(_client),
new Module.EntryAutoRole.EntryAutoRole(_client), new Module.EntryAutoRole.EntryAutoRole(_client),

View file

@ -6,7 +6,7 @@ AutoMod is set up by defining rules within a JSON object named `automod` within
Sample within a [server definition](serverdef.html): Sample within a [server definition](serverdef.html):
``` ```
"automod": { "AutoMod": {
"Delete bilingual pirates": { "Delete bilingual pirates": {
"regex": [ "pira(te|cy)", "pirat(a|ería)", ], "regex": [ "pira(te|cy)", "pirat(a|ería)", ],
"response": [ "response": [

View file

@ -6,7 +6,7 @@ This may seem like a redundant feature, given that the same can be accomplished
Sample within a [server definition](serverdef.html): Sample within a [server definition](serverdef.html):
``` ```
"autorespond": { "AutoRespond": {
"Help command": { "Help command": {
"regex": "^!help$", "regex": "^!help$",
"reply": "You can't be helped. Try again in 45 minutes.", "reply": "You can't be helped. Try again in 45 minutes.",

View file

@ -26,8 +26,8 @@ The following is a list of accepted members within a server definition.
* id (*integer*) - **Required.** A value containing the server's [unique ID](https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-). * id (*integer*) - **Required.** A value containing the server's [unique ID](https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-).
* name (*string*) - Preferably a readable version of the server's name. Not used for anything other than internal logging. * name (*string*) - Preferably a readable version of the server's name. Not used for anything other than internal logging.
* moderators (*[entity list](entitylist.html)*) - A list of entities to consider as moderators. Actions done by members of this list are able to execute *ModCommands* commands and are exempt from certain *AutoMod* rules. See their respective pages for more details. * moderators (*[entity list](entitylist.html)*) - A list of entities to consider as moderators. Actions done by members of this list are able to execute *ModCommands* commands and are exempt from certain *AutoMod* rules. See their respective pages for more details.
* [automod](automod.html) - See respective page. * [AutoMod](automod.html) - See respective page.
* [autoresponses](autorespond.html) - See respective page. * [AutoRespond](autorespond.html) - See respective page.
* [EntryAutoRole](entryautorole.html) - See respective page. * [EntryAutoRole](entryautorole.html) - See respective page.
* [ModCommands](modcommands.html) - See respective page. * [ModCommands](modcommands.html) - See respective page.
* [ModLogs](modlogs.html) - See respective page. * [ModLogs](modlogs.html) - See respective page.