diff --git a/.vscode/launch.json b/.vscode/launch.json
index 226ef29..f29b948 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/output/Debug/net6.0/RegexBot.dll",
+ "program": "${workspaceFolder}/bin/Debug/net6.0/RegexBot.dll",
"args": [],
- "cwd": "${workspaceFolder}/RegexBot",
+ "cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index d900e19..274a943 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
- "${workspaceFolder}/RegexBot.sln",
+ "${workspaceFolder}/RegexBot.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
- "${workspaceFolder}/RegexBot.sln",
+ "${workspaceFolder}/RegexBot.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
@@ -33,7 +33,7 @@
"watch",
"run",
"--project",
- "${workspaceFolder}/RegexBot.sln"
+ "${workspaceFolder}/RegexBot.csproj"
],
"problemMatcher": "$msCompile"
}
diff --git a/RegexBot/Common/EntityList.cs b/Common/EntityList.cs
similarity index 97%
rename from RegexBot/Common/EntityList.cs
rename to Common/EntityList.cs
index a09f036..02cd86d 100644
--- a/RegexBot/Common/EntityList.cs
+++ b/Common/EntityList.cs
@@ -1,9 +1,6 @@
-using Discord.WebSocket;
-using Newtonsoft.Json.Linq;
-using System.Collections;
+using System.Collections;
namespace RegexBot.Common;
-
///
/// Represents a commonly-used configuration structure: an array of strings consisting of values.
///
@@ -64,6 +61,7 @@ public class EntityList : IEnumerable {
/// Checks if the parameters of the given matches with
/// any entity specified in this list.
///
+ /// The incoming message object with which to scan for a match.
///
/// Specifies if EntityName instances within this list should have their internal ID value
/// updated if found during the matching process.
@@ -122,4 +120,4 @@ public class EntityList : IEnumerable {
public IEnumerator GetEnumerator() => _innerList.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
-}
+}
\ No newline at end of file
diff --git a/RegexBot/Common/EntityName.cs b/Common/EntityName.cs
similarity index 99%
rename from RegexBot/Common/EntityName.cs
rename to Common/EntityName.cs
index 3407f87..dc7a7bc 100644
--- a/RegexBot/Common/EntityName.cs
+++ b/Common/EntityName.cs
@@ -1,7 +1,4 @@
-using Discord.WebSocket;
-
-namespace RegexBot.Common;
-
+namespace RegexBot.Common;
///
/// Helper class that holds an entity's name, ID, or both.
/// Meant to be used during configuration processing in cases where the configuration expects
diff --git a/Common/EntityType.cs b/Common/EntityType.cs
new file mode 100644
index 0000000..43e2352
--- /dev/null
+++ b/Common/EntityType.cs
@@ -0,0 +1,20 @@
+namespace RegexBot.Common;
+///
+/// The type of entity specified in an .
+///
+public enum EntityType {
+ /// Default value. Is never referenced in regular usage.
+ Unspecified,
+ ///
+ /// Userd when the represents a role.
+ ///
+ Role,
+ ///
+ /// Used when the represents a channel.
+ ///
+ Channel,
+ ///
+ /// Used when the represents a user.
+ ///
+ User
+}
diff --git a/RegexBot/Common/FilterList.cs b/Common/FilterList.cs
similarity index 76%
rename from RegexBot/Common/FilterList.cs
rename to Common/FilterList.cs
index 2507117..87e3f8b 100644
--- a/RegexBot/Common/FilterList.cs
+++ b/Common/FilterList.cs
@@ -1,16 +1,37 @@
-using Discord.WebSocket;
-using Newtonsoft.Json.Linq;
-
-namespace RegexBot.Common;
-
+namespace RegexBot.Common;
///
/// Represents commonly-used configuration regarding whitelist/blacklist filtering, including exemptions.
///
public class FilterList {
- public enum FilterMode { None, Whitelist, Blacklist }
+ ///
+ /// The mode at which the 's filter criteria is operating.
+ ///
+ public enum FilterMode {
+ ///
+ /// A setting which does no filtering on the list.
+ ///
+ None,
+ ///
+ /// A setting which excludes only entites not in the list, excluding those exempted.
+ ///
+ Whitelist,
+ ///
+ /// A setting which allows all entities except those in the list, but allowing those exempted.
+ ///
+ Blacklist
+ }
+ ///
+ /// Gets the mode at which the 's filter criteria is operating.
+ ///
public FilterMode Mode { get; }
+ ///
+ /// Gets the inner list that this instance is using for its filtering criteria.
+ ///
public EntityList FilteredList { get; }
+ ///
+ /// Gets the list of entities that may override filtering rules for this instance.
+ ///
public EntityList FilterExemptions { get; }
///
@@ -70,6 +91,9 @@ public class FilterList {
/// Determines if the parameters of the given message match up against the filtering
/// rules described within this instance.
///
+ ///
+ /// The incoming message to be checked.
+ ///
///
/// See equivalent documentation for .
///
diff --git a/Common/Messages.cs b/Common/Messages.cs
new file mode 100644
index 0000000..55a92a5
--- /dev/null
+++ b/Common/Messages.cs
@@ -0,0 +1,10 @@
+namespace RegexBot.Common;
+///
+/// Commonly used strings used throughout the bot and modules.
+///
+public static class Messages {
+ ///
+ /// Gets a string generally appropriate to display in the event of a 403 error.
+ ///
+ public const string ForbiddenGenericError = "Failed to perform the action due to a permissions issue.";
+}
\ No newline at end of file
diff --git a/RegexBot/Common/Utilities.cs b/Common/Utilities.cs
similarity index 83%
rename from RegexBot/Common/Utilities.cs
rename to Common/Utilities.cs
index a1e07fb..55578eb 100644
--- a/RegexBot/Common/Utilities.cs
+++ b/Common/Utilities.cs
@@ -1,6 +1,4 @@
using Discord;
-using Discord.WebSocket;
-using Newtonsoft.Json.Linq;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
@@ -9,9 +7,24 @@ namespace RegexBot.Common;
/// Miscellaneous utility methods useful for the bot and modules.
///
public static class Utilities {
+ ///
+ /// Gets a compiled regex that matches a channel tag and pulls its snowflake value.
+ ///
public static Regex ChannelMention { get; } = new(@"<#(?\d+)>", RegexOptions.Compiled);
+
+ ///
+ /// Gets a compiled regex that matches a custom emoji and pulls its name and ID.
+ ///
public static Regex CustomEmoji { get; } = new(@"<:(?[A-Za-z0-9_]{2,}):(?\d+)>", RegexOptions.Compiled);
+
+ ///
+ /// Gets a compiled regex that matches a fully formed Discord handle, extracting the name and discriminator.
+ ///
public static Regex DiscriminatorSearch { get; } = new(@"(.+)#(\d{4}(?!\d))", RegexOptions.Compiled);
+
+ ///
+ /// Gets a compiled regex that matches a user tag and pulls its snowflake value.
+ ///
public static Regex UserMention { get; } = new(@"<@!?(?\d+)>", RegexOptions.Compiled);
///
diff --git a/RegexBot/Data/BotDatabaseContext.cs b/Data/BotDatabaseContext.cs
similarity index 71%
rename from RegexBot/Data/BotDatabaseContext.cs
rename to Data/BotDatabaseContext.cs
index e6fc0a6..c3e10d7 100644
--- a/RegexBot/Data/BotDatabaseContext.cs
+++ b/Data/BotDatabaseContext.cs
@@ -1,7 +1,9 @@
using Microsoft.EntityFrameworkCore;
namespace RegexBot.Data;
-
+///
+/// Represents a database connection using the settings defined in the bot's global configuration.
+///
public class BotDatabaseContext : DbContext {
private static string? _npgsqlConnectionString;
internal static string PostgresConnectionString {
@@ -17,21 +19,31 @@ public class BotDatabaseContext : DbContext {
set => _npgsqlConnectionString ??= value;
}
- public DbSet GuildLog { get; set; } = null!;
+ ///
+ /// Retrieves the user cache.
+ ///
public DbSet UserCache { get; set; } = null!;
+
+ ///
+ /// Retrieves the guild user cache.
+ ///
public DbSet GuildUserCache { get; set; } = null!;
+
+ ///
+ /// Retrieves the guild message cache.
+ ///
public DbSet GuildMessageCache { get; set; } = null!;
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ ///
+ protected sealed override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql(PostgresConnectionString)
.UseSnakeCaseNamingConvention();
+ ///
protected override void OnModelCreating(ModelBuilder modelBuilder) {
- modelBuilder.Entity(entity => entity.Property(e => e.Timestamp).HasDefaultValueSql("now()"));
modelBuilder.Entity(entity => entity.Property(e => e.Discriminator).HasMaxLength(4).IsFixedLength());
modelBuilder.Entity(entity => {
- entity.Navigation(e => e.User).AutoInclude();
entity.HasKey(e => new { e.UserId, e.GuildId });
entity.Property(e => e.FirstSeenTime).HasDefaultValueSql("now()");
});
diff --git a/Data/CachedGuildMessage.cs b/Data/CachedGuildMessage.cs
new file mode 100644
index 0000000..3dafdaf
--- /dev/null
+++ b/Data/CachedGuildMessage.cs
@@ -0,0 +1,62 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace RegexBot.Data;
+///
+/// Represents an item in the guild message cache.
+///
+[Table("cache_guildmessages")]
+public class CachedGuildMessage {
+ ///
+ /// Gets the message's snowflake ID.
+ ///
+ [Key]
+ [DatabaseGenerated(DatabaseGeneratedOption.None)]
+ public long MessageId { get; set; }
+
+ ///
+ /// Gets the message author's snowflake ID.
+ ///
+ public long AuthorId { get; set; }
+
+ ///
+ /// Gets the associated guild's snowflake ID.
+ ///
+ public long GuildId { get; set; }
+
+ ///
+ /// Gets the corresponding channel's snowflake ID.
+ ///
+ public long ChannelId { get; set; }
+
+ ///
+ /// Gets the timestamp showing when this message was originally created.
+ ///
+ ///
+ /// Though it's possible to draw this from , it is stored in the database
+ /// as a separate field for any possible necessary use via database queries.
+ ///
+ public DateTimeOffset CreatedAt { get; set; }
+
+ ///
+ /// Gets the timestamp, if any, showing when this message was last edited.
+ ///
+ public DateTimeOffset? EditedAt { get; set; }
+
+ ///
+ /// Gets a list of file names thata were attached to this message.
+ ///
+ public List AttachmentNames { get; set; } = null!;
+
+ ///
+ /// Gets this message's content.
+ ///
+ public string Content { get; set; } = null!;
+
+ ///
+ /// If included in the query, references the associated for this entry.
+ ///
+ [ForeignKey(nameof(AuthorId))]
+ [InverseProperty(nameof(CachedUser.GuildMessages))]
+ public CachedUser Author { get; set; } = null!;
+}
diff --git a/Data/CachedGuildUser.cs b/Data/CachedGuildUser.cs
new file mode 100644
index 0000000..3a6f14a
--- /dev/null
+++ b/Data/CachedGuildUser.cs
@@ -0,0 +1,36 @@
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace RegexBot.Data;
+///
+/// Represents an item in the guild user cache.
+///
+[Table("cache_usersinguild")]
+public class CachedGuildUser {
+ ///
+ public long UserId { get; set; }
+
+ ///
+ /// Gets the associated guild's snowflake ID.
+ ///
+ public long GuildId { get; set; }
+
+ ///
+ public DateTimeOffset GULastUpdateTime { get; set; }
+
+ ///
+ /// Gets the timestamp showing when this cache entry was first added into the database.
+ ///
+ public DateTimeOffset FirstSeenTime { get; set; }
+
+ ///
+ /// Gets the user's cached nickname in the guild.
+ ///
+ public string? Nickname { get; set; }
+
+ ///
+ /// If included in the query, references the associated for this entry.
+ ///
+ [ForeignKey(nameof(UserId))]
+ [InverseProperty(nameof(CachedUser.Guilds))]
+ public CachedUser User { get; set; } = null!;
+}
diff --git a/Data/CachedUser.cs b/Data/CachedUser.cs
new file mode 100644
index 0000000..dfdcfae
--- /dev/null
+++ b/Data/CachedUser.cs
@@ -0,0 +1,48 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace RegexBot.Data;
+///
+/// Represents an item in the user cache.
+///
+[Table("cache_users")]
+public class CachedUser {
+ ///
+ /// Gets the user's snowflake ID.
+ ///
+ [Key]
+ [DatabaseGenerated(DatabaseGeneratedOption.None)]
+ public long UserId { get; set; }
+
+ ///
+ /// Gets the timestamp showing when this cache entry was last updated.
+ ///
+ public DateTimeOffset ULastUpdateTime { get; set; }
+
+ ///
+ /// Gets the user's username value, without the discriminator.
+ ///
+ public string Username { get; set; } = null!;
+
+ ///
+ /// Gets the user's discriminator value.
+ ///
+ public string Discriminator { get; set; } = null!;
+
+ ///
+ /// Gets the avatar URL, if any, for the associated user.
+ ///
+ public string? AvatarUrl { get; set; }
+
+ ///
+ /// If included in the query, gets the list of associated entries for this entry.
+ ///
+ [InverseProperty(nameof(CachedGuildUser.User))]
+ public ICollection Guilds { get; set; } = null!;
+
+ ///
+ /// If included in the query, gets the list of associated entries for this entry.
+ ///
+ [InverseProperty(nameof(CachedGuildMessage.Author))]
+ public ICollection GuildMessages { get; set; } = null!;
+}
diff --git a/Data/Migrations/.editorconfig b/Data/Migrations/.editorconfig
new file mode 100644
index 0000000..f7653e7
--- /dev/null
+++ b/Data/Migrations/.editorconfig
@@ -0,0 +1,3 @@
+[*.cs]
+dotnet_analyzer_diagnostic.category-CodeQuality.severity = none
+dotnet_diagnostic.CS1591.severity = none
\ No newline at end of file
diff --git a/RegexBot/Data/Migrations/20220610210059_InitialMigration.Designer.cs b/Data/Migrations/20220610210059_InitialMigration.Designer.cs
similarity index 100%
rename from RegexBot/Data/Migrations/20220610210059_InitialMigration.Designer.cs
rename to Data/Migrations/20220610210059_InitialMigration.Designer.cs
diff --git a/RegexBot/Data/Migrations/20220610210059_InitialMigration.cs b/Data/Migrations/20220610210059_InitialMigration.cs
similarity index 100%
rename from RegexBot/Data/Migrations/20220610210059_InitialMigration.cs
rename to Data/Migrations/20220610210059_InitialMigration.cs
diff --git a/RegexBot/Data/Migrations/BotDatabaseContextModelSnapshot.cs b/Data/Migrations/BotDatabaseContextModelSnapshot.cs
similarity index 100%
rename from RegexBot/Data/Migrations/BotDatabaseContextModelSnapshot.cs
rename to Data/Migrations/BotDatabaseContextModelSnapshot.cs
diff --git a/RegexBot/DefaultGuildConfig.json b/DefaultGuildConfig.json
similarity index 100%
rename from RegexBot/DefaultGuildConfig.json
rename to DefaultGuildConfig.json
diff --git a/RegexBot/InstanceConfig.cs b/InstanceConfig.cs
similarity index 87%
rename from RegexBot/InstanceConfig.cs
rename to InstanceConfig.cs
index e5a4f70..91f37eb 100644
--- a/RegexBot/InstanceConfig.cs
+++ b/InstanceConfig.cs
@@ -1,5 +1,4 @@
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using RegexBot.Data;
using System.Reflection;
@@ -30,14 +29,9 @@ class InstanceConfig {
///
/// Sets up instance configuration object from file and command line parameters.
///
- internal InstanceConfig(string[] cmdline) {
- var opts = Options.ParseOptions(cmdline);
-
- var path = opts.ConfigFile;
- if (path == null) { // default: config.json in working directory
- path = Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)
- + "." + Path.DirectorySeparatorChar + "config.json";
- }
+ internal InstanceConfig() {
+ var path = Path.GetDirectoryName(Assembly.GetEntryAssembly()!.Location)
+ + "." + Path.DirectorySeparatorChar + "config.json";
JObject conf;
try {
diff --git a/RegexBot/ModuleLoadException.cs b/ModuleLoadException.cs
similarity index 66%
rename from RegexBot/ModuleLoadException.cs
rename to ModuleLoadException.cs
index 34a4e0d..41f6bef 100644
--- a/RegexBot/ModuleLoadException.cs
+++ b/ModuleLoadException.cs
@@ -1,7 +1,8 @@
namespace RegexBot;
///
-/// Represents errors that occur when a module attempts to create a new guild state object.
+/// Represents an error occurring when a module attempts to create a new guild state object
+/// (that is, read or refresh its configuration).
///
public class ModuleLoadException : Exception {
///
diff --git a/RegexBot/ModuleLoader.cs b/ModuleLoader.cs
similarity index 88%
rename from RegexBot/ModuleLoader.cs
rename to ModuleLoader.cs
index 03e59ea..3069abe 100644
--- a/RegexBot/ModuleLoader.cs
+++ b/ModuleLoader.cs
@@ -3,7 +3,6 @@ using System.Reflection;
using System.Text;
namespace RegexBot;
-
static class ModuleLoader {
///
/// Given the instance configuration, loads all appropriate types from file specified in it.
@@ -36,21 +35,21 @@ static class ModuleLoader {
return modules.AsReadOnly();
}
- static IEnumerable LoadModulesFromAssembly(Assembly asm, RegexbotClient k) {
+ static IEnumerable LoadModulesFromAssembly(Assembly asm, RegexbotClient rb) {
var eligibleTypes = from type in asm.GetTypes()
where !type.IsAssignableFrom(typeof(RegexbotModule))
where type.GetCustomAttribute() != null
select type;
- k._svcLogging.DoLog(false, nameof(ModuleLoader), $"Scanning {asm.GetName().Name}");
+ rb._svcLogging.DoLog(false, nameof(ModuleLoader), $"Scanning {asm.GetName().Name}");
var newreport = new StringBuilder("---> Found module(s):");
var newmods = new List();
foreach (var t in eligibleTypes) {
- var mod = Activator.CreateInstance(t, k)!;
+ var mod = Activator.CreateInstance(t, rb)!;
newreport.Append($" {t.Name}");
newmods.Add((RegexbotModule)mod);
}
- k._svcLogging.DoLog(false, nameof(ModuleLoader), newreport.ToString());
+ rb._svcLogging.DoLog(false, nameof(ModuleLoader), newreport.ToString());
return newmods;
}
}
diff --git a/RegexBot-Modules/AutoResponder/AutoResponder.cs b/Modules/AutoResponder/AutoResponder.cs
similarity index 100%
rename from RegexBot-Modules/AutoResponder/AutoResponder.cs
rename to Modules/AutoResponder/AutoResponder.cs
diff --git a/RegexBot-Modules/AutoResponder/Definition.cs b/Modules/AutoResponder/Definition.cs
similarity index 100%
rename from RegexBot-Modules/AutoResponder/Definition.cs
rename to Modules/AutoResponder/Definition.cs
diff --git a/RegexBot-Modules/EntryRole/EntryRole.cs b/Modules/EntryRole/EntryRole.cs
similarity index 100%
rename from RegexBot-Modules/EntryRole/EntryRole.cs
rename to Modules/EntryRole/EntryRole.cs
diff --git a/RegexBot-Modules/EntryRole/GuildData.cs b/Modules/EntryRole/GuildData.cs
similarity index 100%
rename from RegexBot-Modules/EntryRole/GuildData.cs
rename to Modules/EntryRole/GuildData.cs
diff --git a/RegexBot-Modules/ModCommands/Commands/BanKick.cs b/Modules/ModCommands/Commands/BanKick.cs
similarity index 97%
rename from RegexBot-Modules/ModCommands/Commands/BanKick.cs
rename to Modules/ModCommands/Commands/BanKick.cs
index e8a126f..a518834 100644
--- a/RegexBot-Modules/ModCommands/Commands/BanKick.cs
+++ b/Modules/ModCommands/Commands/BanKick.cs
@@ -1,4 +1,5 @@
-using RegexBot.Data;
+using RegexBot.Common;
+using RegexBot.Data;
namespace RegexBot.Modules.ModCommands.Commands;
// Ban and kick commands are highly similar in implementation, and thus are handled in a single class.
@@ -132,7 +133,7 @@ abstract class BanKick : CommandConfig {
await ContinueInvoke(g, msg, reason, targetId, targetQuery, targetUser);
} catch (Discord.Net.HttpException ex) {
if (ex.HttpCode == System.Net.HttpStatusCode.Forbidden) {
- await msg.Channel.SendMessageAsync(":x: " + Strings.ForbiddenGenericError);
+ await msg.Channel.SendMessageAsync(":x: " + Messages.ForbiddenGenericError);
} else if (ex.HttpCode == System.Net.HttpStatusCode.NotFound) {
await msg.Channel.SendMessageAsync(":x: Encountered a 404 error when processing the request.");
}
diff --git a/RegexBot-Modules/ModCommands/Commands/CommandConfig.cs b/Modules/ModCommands/Commands/CommandConfig.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/Commands/CommandConfig.cs
rename to Modules/ModCommands/Commands/CommandConfig.cs
diff --git a/RegexBot-Modules/ModCommands/Commands/ConfReload.cs b/Modules/ModCommands/Commands/ConfReload.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/Commands/ConfReload.cs
rename to Modules/ModCommands/Commands/ConfReload.cs
diff --git a/RegexBot-Modules/ModCommands/Commands/RoleManipulation.cs b/Modules/ModCommands/Commands/RoleManipulation.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/Commands/RoleManipulation.cs
rename to Modules/ModCommands/Commands/RoleManipulation.cs
diff --git a/RegexBot-Modules/ModCommands/Commands/Say.cs b/Modules/ModCommands/Commands/Say.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/Commands/Say.cs
rename to Modules/ModCommands/Commands/Say.cs
diff --git a/RegexBot-Modules/ModCommands/Commands/Unban.cs b/Modules/ModCommands/Commands/Unban.cs
similarity index 95%
rename from RegexBot-Modules/ModCommands/Commands/Unban.cs
rename to Modules/ModCommands/Commands/Unban.cs
index 5fa2568..609ff1d 100644
--- a/RegexBot-Modules/ModCommands/Commands/Unban.cs
+++ b/Modules/ModCommands/Commands/Unban.cs
@@ -1,4 +1,6 @@
-namespace RegexBot.Modules.ModCommands.Commands;
+using RegexBot.Common;
+
+namespace RegexBot.Modules.ModCommands.Commands;
class Unban : CommandConfig {
private readonly string _usage;
@@ -43,7 +45,7 @@ class Unban : CommandConfig {
} catch (Discord.Net.HttpException ex) {
const string FailPrefix = ":x: **Could not unban:** ";
if (ex.HttpCode == System.Net.HttpStatusCode.Forbidden)
- await msg.Channel.SendMessageAsync(FailPrefix + Strings.ForbiddenGenericError);
+ await msg.Channel.SendMessageAsync(FailPrefix + Messages.ForbiddenGenericError);
else if (ex.HttpCode == System.Net.HttpStatusCode.NotFound)
await msg.Channel.SendMessageAsync(FailPrefix + "The specified user does not exist or is not in the ban list.");
else throw;
diff --git a/RegexBot-Modules/ModCommands/ModCommands.cs b/Modules/ModCommands/ModCommands.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/ModCommands.cs
rename to Modules/ModCommands/ModCommands.cs
diff --git a/RegexBot-Modules/ModCommands/ModuleConfig.cs b/Modules/ModCommands/ModuleConfig.cs
similarity index 100%
rename from RegexBot-Modules/ModCommands/ModuleConfig.cs
rename to Modules/ModCommands/ModuleConfig.cs
diff --git a/RegexBot-Modules/ModLogs/ModLogs.cs b/Modules/ModLogs/ModLogs.cs
similarity index 100%
rename from RegexBot-Modules/ModLogs/ModLogs.cs
rename to Modules/ModLogs/ModLogs.cs
diff --git a/RegexBot-Modules/ModLogs/ModLogs_Messages.cs b/Modules/ModLogs/ModLogs_Messages.cs
similarity index 100%
rename from RegexBot-Modules/ModLogs/ModLogs_Messages.cs
rename to Modules/ModLogs/ModLogs_Messages.cs
diff --git a/RegexBot-Modules/ModLogs/ModuleConfig.cs b/Modules/ModLogs/ModuleConfig.cs
similarity index 100%
rename from RegexBot-Modules/ModLogs/ModuleConfig.cs
rename to Modules/ModLogs/ModuleConfig.cs
diff --git a/RegexBot-Modules/PendingOutRole/ModuleConfig.cs b/Modules/PendingOutRole/ModuleConfig.cs
similarity index 100%
rename from RegexBot-Modules/PendingOutRole/ModuleConfig.cs
rename to Modules/PendingOutRole/ModuleConfig.cs
diff --git a/RegexBot-Modules/PendingOutRole/PendingOutRole.cs b/Modules/PendingOutRole/PendingOutRole.cs
similarity index 100%
rename from RegexBot-Modules/PendingOutRole/PendingOutRole.cs
rename to Modules/PendingOutRole/PendingOutRole.cs
diff --git a/RegexBot-Modules/RateLimit.cs b/Modules/RateLimit.cs
similarity index 100%
rename from RegexBot-Modules/RateLimit.cs
rename to Modules/RateLimit.cs
diff --git a/RegexBot-Modules/RegexModerator/ConfDefinition.cs b/Modules/RegexModerator/ConfDefinition.cs
similarity index 100%
rename from RegexBot-Modules/RegexModerator/ConfDefinition.cs
rename to Modules/RegexModerator/ConfDefinition.cs
diff --git a/RegexBot-Modules/RegexModerator/RegexModerator.cs b/Modules/RegexModerator/RegexModerator.cs
similarity index 100%
rename from RegexBot-Modules/RegexModerator/RegexModerator.cs
rename to Modules/RegexModerator/RegexModerator.cs
diff --git a/RegexBot-Modules/RegexModerator/ResponseExecutor.cs b/Modules/RegexModerator/ResponseExecutor.cs
similarity index 98%
rename from RegexBot-Modules/RegexModerator/ResponseExecutor.cs
rename to Modules/RegexModerator/ResponseExecutor.cs
index 60dd26e..6aa6ea2 100644
--- a/RegexBot-Modules/RegexModerator/ResponseExecutor.cs
+++ b/Modules/RegexModerator/ResponseExecutor.cs
@@ -67,7 +67,7 @@ class ResponseExecutor {
var result = await runLine(param);
_reports.Add((cmd, result));
} catch (Discord.Net.HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden) {
- _reports.Add((cmd, FromError(Strings.ForbiddenGenericError)));
+ _reports.Add((cmd, FromError(Messages.ForbiddenGenericError)));
}
}
@@ -141,7 +141,7 @@ class ResponseExecutor {
result = await _bot.KickAsync(_guild, $"Rule '{_rule.Label}'", _user.Id,
parameter, _rule.NotifyUserOfRemoval);
}
- if (result.ErrorForbidden) return FromError(Strings.ForbiddenGenericError);
+ if (result.ErrorForbidden) return FromError(Messages.ForbiddenGenericError);
if (result.ErrorNotFound) return FromError("The target user is no longer in the server.");
if (_rule.NotifyChannelOfRemoval) await _msg.Channel.SendMessageAsync(result.GetResultString(_bot));
return FromSuccess(result.MessageSendSuccess ? null : "Unable to send notification DM.");
diff --git a/RegexBot-Modules/VoiceRoleSync/ModuleConfig.cs b/Modules/VoiceRoleSync/ModuleConfig.cs
similarity index 100%
rename from RegexBot-Modules/VoiceRoleSync/ModuleConfig.cs
rename to Modules/VoiceRoleSync/ModuleConfig.cs
diff --git a/RegexBot-Modules/VoiceRoleSync/VoiceRoleSync.cs b/Modules/VoiceRoleSync/VoiceRoleSync.cs
similarity index 100%
rename from RegexBot-Modules/VoiceRoleSync/VoiceRoleSync.cs
rename to Modules/VoiceRoleSync/VoiceRoleSync.cs
diff --git a/RegexBot/Program.cs b/Program.cs
similarity index 90%
rename from RegexBot/Program.cs
rename to Program.cs
index 662fe61..dbcf907 100644
--- a/RegexBot/Program.cs
+++ b/Program.cs
@@ -1,5 +1,6 @@
-using Discord;
-using Discord.WebSocket;
+global using Discord.WebSocket;
+global using Newtonsoft.Json.Linq;
+using Discord;
namespace RegexBot;
class Program {
@@ -10,13 +11,13 @@ class Program {
static RegexbotClient _main = null!;
- static async Task Main(string[] args) {
+ static async Task Main() {
StartTime = DateTimeOffset.UtcNow;
Console.WriteLine("Bot start time: " + StartTime.ToString("u"));
InstanceConfig cfg;
try {
- cfg = new InstanceConfig(args); // Program may exit within here.
+ cfg = new InstanceConfig(); // Program may exit within here.
} catch (Exception ex) {
Console.WriteLine(ex.Message);
Environment.ExitCode = 1;
@@ -33,7 +34,6 @@ class Program {
AlwaysDownloadUsers = true
});
- // Kerobot class initialization - will set up services and modules
_main = new RegexbotClient(cfg, client);
// Set up application close handler
diff --git a/Readme.md b/Readme.md
index 60bfc15..1588bd1 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,26 +1,14 @@
# RegexBot
-**This branch is still a major work in progress, and is highly incomplete. See the legacy branch for the current working version.**
+[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/J3J65TW2E)
RegexBot is a Discord moderation bot framework of sorts, inspired by the terrible state of Discord moderation tools a few years ago
combined with my tendency to overengineer things until they into pseudo-libraries of their own right.
-### Features:
-* Provides a sort of in-between interface to Discord.Net that allows modules to be written for it, its benefits being:
- * Putting together disparate bot features under a common interface.
- * Reducing duplicate code potentially leading to an inconsistent user experience.
-* Versatile JSON-based configuration.
-* High detail logging and record-keeping prevents gaps in moderation that might occur with large public bots.
+This bot includes a number of features which assist in handling the tedious details in a busy server with the goal of minimizing
+the occurrence of hidden details, arbitrary restrictions, or annoyingly unmodifiable behavior. Its configuration allows for a very high
+level of flexibility, ensuring that the bot behaves in accordance to the exact needs of your server without compromise.
-This repository also contains...
-
-# RegexBot-Modules
-An optional set of features to add to RegexBot, some of them inspired by Reddit's Automoderator.
-
-This module provides a number of features to assist in watching over the tedious details in a busy server with no hidden details,
-arbitrary restrictions, or unmodifiable behavior. Its configuration allows for a very high level of flexibility, ensuring that the bot
-behaves in accordance to the exact needs of your server.
-
-### Features:
+### Features
* Create rules based on regular expression patterns
* Follow up with custom responses ranging from sending a DM to disciplinary action
* Create pattern-based triggers to provide information and fun to your users
@@ -29,6 +17,14 @@ behaves in accordance to the exact needs of your server.
* Make things interesting by setting triggers that only activate at random
* Individual rules and triggers can be whitelisted or blacklisted per-user, per-channel, or per-role
* Exemptions to these filters can be applied for additional flexibility
+* High detail logging and record-keeping prevents gaps in moderation that might occur with large public bots.
-## Documentation
+### Modules
+As mentioned above, this bot also serves as a framework of sorts, allowing others to write their own modules and expand
+the bot's feature set ever further. Its benefits are:
+* Putting together disparate bot features under a common, consistent interface.
+* Reducing duplicate code potentially leading to an inconsistent user experience.
+* Versatile JSON-based configuration.
+
+## User documentation
Coming soon?
diff --git a/RegexBot-Modules/Include.cs b/RegexBot-Modules/Include.cs
deleted file mode 100644
index db2e62a..0000000
--- a/RegexBot-Modules/Include.cs
+++ /dev/null
@@ -1,2 +0,0 @@
-global using Discord.WebSocket;
-global using Newtonsoft.Json.Linq;
\ No newline at end of file
diff --git a/RegexBot-Modules/RegexBot-Modules.csproj b/RegexBot-Modules/RegexBot-Modules.csproj
deleted file mode 100644
index 50200f0..0000000
--- a/RegexBot-Modules/RegexBot-Modules.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- net6.0
- RegexBot.Modules
- enable
- enable
- NoiTheCat
- A set of standard modules for use with RegexBot.
- $(SolutionDir)\output
- true
- embedded
-
-
-
-
-
-
-
diff --git a/RegexBot/RegexBot.csproj b/RegexBot.csproj
similarity index 71%
rename from RegexBot/RegexBot.csproj
rename to RegexBot.csproj
index a4a35bc..ce34adb 100644
--- a/RegexBot/RegexBot.csproj
+++ b/RegexBot.csproj
@@ -6,10 +6,9 @@
NoiTheCat
Advanced and flexible Discord moderation bot.
0.0.1
- enable
- enable
- True
- $(SolutionDir)\output
+ enable
+ enable
+ True
@@ -21,18 +20,17 @@
-
-
+
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
diff --git a/RegexBot.sln b/RegexBot.sln
deleted file mode 100644
index ac74113..0000000
--- a/RegexBot.sln
+++ /dev/null
@@ -1,28 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegexBot", "RegexBot\RegexBot.csproj", "{F7CDACE1-C74E-451E-A9C2-ED717BF72C1C}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegexBot-Modules", "RegexBot-Modules\RegexBot-Modules.csproj", "{347A1912-4F7D-419B-A159-6671791568CC}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F7CDACE1-C74E-451E-A9C2-ED717BF72C1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F7CDACE1-C74E-451E-A9C2-ED717BF72C1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F7CDACE1-C74E-451E-A9C2-ED717BF72C1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F7CDACE1-C74E-451E-A9C2-ED717BF72C1C}.Release|Any CPU.Build.0 = Release|Any CPU
- {347A1912-4F7D-419B-A159-6671791568CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {347A1912-4F7D-419B-A159-6671791568CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {347A1912-4F7D-419B-A159-6671791568CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {347A1912-4F7D-419B-A159-6671791568CC}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
-EndGlobal
diff --git a/RegexBot/Common/EntityType.cs b/RegexBot/Common/EntityType.cs
deleted file mode 100644
index d8a76b8..0000000
--- a/RegexBot/Common/EntityType.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace RegexBot.Common;
-
-///
-/// The type of entity specified in an .
-///
-public enum EntityType {
- /// Default value. Is never referenced in regular usage.
- Unspecified,
- Role,
- Channel,
- User
-}
diff --git a/RegexBot/Common/Strings.cs b/RegexBot/Common/Strings.cs
deleted file mode 100644
index 453b60a..0000000
--- a/RegexBot/Common/Strings.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-///
-/// Commonly used strings used throughout the program and modules.
-///
-public static class Strings {
- public const string ForbiddenGenericError = "Failed to perform the action due to a permissions issue.";
-}
\ No newline at end of file
diff --git a/RegexBot/Data/CachedGuildMessage.cs b/RegexBot/Data/CachedGuildMessage.cs
deleted file mode 100644
index 91b5831..0000000
--- a/RegexBot/Data/CachedGuildMessage.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace RegexBot.Data;
-[Table("cache_messages")]
-public class CachedGuildMessage {
- [Key]
- [DatabaseGenerated(DatabaseGeneratedOption.None)]
- public long MessageId { get; set; }
-
- public long AuthorId { get; set; }
-
- public long GuildId { get; set; }
-
- public long ChannelId { get; set; }
-
- public DateTimeOffset CreatedAt { get; set; }
-
- public DateTimeOffset? EditedAt { get; set; }
-
- public List AttachmentNames { get; set; } = null!;
-
- public string Content { get; set; } = null!;
-
- [ForeignKey(nameof(AuthorId))]
- [InverseProperty(nameof(CachedUser.GuildMessages))]
- public CachedUser Author { get; set; } = null!;
-
- internal new CachedGuildMessage MemberwiseClone() => (CachedGuildMessage)base.MemberwiseClone();
-}
diff --git a/RegexBot/Data/CachedGuildUser.cs b/RegexBot/Data/CachedGuildUser.cs
deleted file mode 100644
index 8b372fc..0000000
--- a/RegexBot/Data/CachedGuildUser.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace RegexBot.Data;
-
-[Table("cache_userguild")]
-public class CachedGuildUser {
- public long UserId { get; set; }
- public long GuildId { get; set; }
- public DateTimeOffset GULastUpdateTime { get; set; }
- public DateTimeOffset FirstSeenTime { get; set; }
- public string? Nickname { get; set; }
-
- [ForeignKey(nameof(UserId))]
- [InverseProperty(nameof(CachedUser.Guilds))]
- public CachedUser User { get; set; } = null!;
-}
diff --git a/RegexBot/Data/CachedUser.cs b/RegexBot/Data/CachedUser.cs
deleted file mode 100644
index 1b350f4..0000000
--- a/RegexBot/Data/CachedUser.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace RegexBot.Data;
-
-[Table("cache_user")]
-public class CachedUser {
- [Key]
- [DatabaseGenerated(DatabaseGeneratedOption.None)]
- public long UserId { get; set; }
- public DateTimeOffset ULastUpdateTime { get; set; }
- public string Username { get; set; } = null!;
- public string Discriminator { get; set; } = null!;
- public string? AvatarUrl { get; set; }
-
- [InverseProperty(nameof(CachedGuildUser.User))]
- public ICollection Guilds { get; set; } = null!;
-
- [InverseProperty(nameof(CachedGuildMessage.Author))]
- public ICollection GuildMessages { get; set; } = null!;
-}
diff --git a/RegexBot/Data/GuildLogLine.cs b/RegexBot/Data/GuildLogLine.cs
deleted file mode 100644
index 00a40b5..0000000
--- a/RegexBot/Data/GuildLogLine.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace RegexBot.Data;
-
-[Table("guild_log")]
-[Index(nameof(GuildId))]
-public class GuildLogLine {
- public int Id { get; set; }
- public long GuildId { get; set; }
- public DateTimeOffset Timestamp { get; set; }
- public string Source { get; set; } = null!;
- public string Message { get; set; } = null!;
-}
diff --git a/RegexBot/Options.cs b/RegexBot/Options.cs
deleted file mode 100644
index 73c2106..0000000
--- a/RegexBot/Options.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using CommandLine;
-using CommandLine.Text;
-
-namespace RegexBot;
-
-///
-/// Command line options
-///
-class Options {
- [Option('c', "config", Default = null,
- HelpText = "Custom path to instance configuration. Defaults to config.json in bot directory.")]
- public string ConfigFile { get; set; } = null!;
-
- ///
- /// Command line arguments parsed here. Depending on inputs, the program can exit here.
- ///
- public static Options ParseOptions(string[] args) {
- // Parser will not write out to console by itself
- var parser = new Parser(config => config.HelpWriter = null);
- Options? opts = null;
-
- var result = parser.ParseArguments(args);
- result.WithParsed(p => opts = p);
- result.WithNotParsed(p => {
- // Taking some extra steps to modify the header to make it resemble our welcome message.
- var ht = HelpText.AutoBuild(result);
- ht.Heading += " - https://github.com/NoiTheCat/RegexBot";
- Console.WriteLine(ht.ToString());
- Environment.Exit(1);
- });
- return opts!;
- }
-}
diff --git a/RegexBot/RegexbotModuleAttribute.cs b/RegexBot/RegexbotModuleAttribute.cs
deleted file mode 100644
index d38cf0c..0000000
--- a/RegexBot/RegexbotModuleAttribute.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace RegexBot;
-
-///
-/// Specifies to the Kerobot module loader that the target class should be treated as a module instance.
-/// When the program scans an assembly which has been specified in its instance configuration to be loaded,
-/// the program searches for classes implementing that also contain this attribute.
-///
-[AttributeUsage(AttributeTargets.Class, Inherited = false)]
-public class RegexbotModuleAttribute : Attribute { }
diff --git a/RegexBot/RegexbotClient.cs b/RegexbotClient.cs
similarity index 96%
rename from RegexBot/RegexbotClient.cs
rename to RegexbotClient.cs
index b5c1a76..9128873 100644
--- a/RegexBot/RegexbotClient.cs
+++ b/RegexbotClient.cs
@@ -1,8 +1,6 @@
-using Discord.WebSocket;
-using System.Reflection;
+using System.Reflection;
namespace RegexBot;
-
///
/// The RegexBot client instance.
///
diff --git a/RegexBot/RegexbotModule.cs b/RegexbotModule.cs
similarity index 98%
rename from RegexBot/RegexbotModule.cs
rename to RegexbotModule.cs
index bf4ccb2..4ebe99d 100644
--- a/RegexBot/RegexbotModule.cs
+++ b/RegexbotModule.cs
@@ -1,6 +1,4 @@
-using Discord.WebSocket;
-using Newtonsoft.Json.Linq;
-using RegexBot.Common;
+using RegexBot.Common;
using System.Diagnostics;
namespace RegexBot;
diff --git a/RegexbotModuleAttribute.cs b/RegexbotModuleAttribute.cs
new file mode 100644
index 0000000..d6c9c0d
--- /dev/null
+++ b/RegexbotModuleAttribute.cs
@@ -0,0 +1,8 @@
+namespace RegexBot;
+
+///
+/// Provides a hint to the module loader that the class it is applied to should be treated as a module instance.
+/// When the program scans an assembly, it is scanned for classes which implement and have this attribute.
+///
+[AttributeUsage(AttributeTargets.Class, Inherited = false)]
+public class RegexbotModuleAttribute : Attribute { }
diff --git a/RegexBot/Services/CommonFunctions/BanKickResult.cs b/Services/CommonFunctions/BanKickResult.cs
similarity index 97%
rename from RegexBot/Services/CommonFunctions/BanKickResult.cs
rename to Services/CommonFunctions/BanKickResult.cs
index 4ecf41d..9d5bcc3 100644
--- a/RegexBot/Services/CommonFunctions/BanKickResult.cs
+++ b/Services/CommonFunctions/BanKickResult.cs
@@ -1,4 +1,5 @@
using Discord.Net;
+using RegexBot.Common;
// Instances of this class are created by CommonFunctionService and are meant to be sent to modules,
// therefore we put this in the root RegexBot namespace despite being specific to this service.
@@ -104,7 +105,7 @@ public class BanKickResult {
if (!MessageSendSuccess) msg += "\n(User was unable to receive notification message.)";
} else {
if (ErrorNotFound) msg += ": The specified user could not be found.";
- else if (ErrorForbidden) msg += ": " + Strings.ForbiddenGenericError;
+ else if (ErrorForbidden) msg += ": " + Messages.ForbiddenGenericError;
}
return msg;
diff --git a/RegexBot/Services/CommonFunctions/CommonFunctionsService.cs b/Services/CommonFunctions/CommonFunctionsService.cs
similarity index 93%
rename from RegexBot/Services/CommonFunctions/CommonFunctionsService.cs
rename to Services/CommonFunctions/CommonFunctionsService.cs
index 0ab4b9b..4acae85 100644
--- a/RegexBot/Services/CommonFunctions/CommonFunctionsService.cs
+++ b/Services/CommonFunctions/CommonFunctionsService.cs
@@ -1,15 +1,10 @@
using Discord.Net;
-using Discord.WebSocket;
namespace RegexBot.Services.CommonFunctions;
-
///
/// Implements certain common actions that modules may want to perform. Using this service to perform those
/// functions may help enforce a sense of consistency across modules when performing common actions, and may
/// inform services which provide any additional features the ability to respond to those actions ahead of time.
-///
-/// This is currently an experimental section. If it turns out to not be necessary, this service will be removed and
-/// modules may resume executing common actions on their own.
///
internal class CommonFunctionsService : Service {
public CommonFunctionsService(RegexbotClient bot) : base(bot) { }
diff --git a/RegexBot/Services/CommonFunctions/Hooks.cs b/Services/CommonFunctions/Hooks.cs
similarity index 75%
rename from RegexBot/Services/CommonFunctions/Hooks.cs
rename to Services/CommonFunctions/Hooks.cs
index 277f241..c6b61ef 100644
--- a/RegexBot/Services/CommonFunctions/Hooks.cs
+++ b/Services/CommonFunctions/Hooks.cs
@@ -1,5 +1,4 @@
-using Discord.WebSocket;
-using RegexBot.Services.CommonFunctions;
+using RegexBot.Services.CommonFunctions;
namespace RegexBot;
partial class RegexbotClient {
@@ -29,7 +28,12 @@ partial class RegexbotClient {
/// Similar to , but making use of an
/// EntityCache lookup to determine the target.
///
- /// The EntityCache search string.
+ /// The guild in which to attempt the ban.
+ /// The user, module, or service which is requesting this action to be taken.
+ /// The user which to perform the action to (as a query to the entity cache).
+ /// Number of days of prior post history to delete on ban. Must be between 0-7.
+ /// Reason for the action. Sent to the Audit Log and user (if specified).
+ /// Specify whether to send a direct message to the target user informing them of the action.
public async Task BanAsync(SocketGuild guild,
string source,
string targetSearch,
@@ -54,10 +58,7 @@ partial class RegexbotClient {
/// Reason for the action. Sent to the guild's audit log and, if
/// is , the target.
///
- ///
- /// Specify whether to send a direct message to the target user informing them of the action
- /// (that is, a ban/kick message).
- ///
+ /// Specify whether to send a direct message to the target user informing them of the action.
public Task KickAsync(SocketGuild guild,
string source,
ulong targetUser,
@@ -69,7 +70,14 @@ partial class RegexbotClient {
/// Similar to , but making use of an
/// EntityCache lookup to determine the target.
///
- /// The EntityCache search string.
+ /// The guild in which to attempt the kick.
+ /// The user, module, or service which is requesting this action to be taken.
+ /// The user which to perform the action towards (processed as a query to the entity cache).
+ ///
+ /// Reason for the action. Sent to the guild's audit log and, if
+ /// is , the target.
+ ///
+ /// Specify whether to send a direct message to the target user informing them of the action.
public async Task KickAsync(SocketGuild guild,
string source,
string targetSearch,
diff --git a/RegexBot/Services/CommonFunctions/RemovalType.cs b/Services/CommonFunctions/RemovalType.cs
similarity index 74%
rename from RegexBot/Services/CommonFunctions/RemovalType.cs
rename to Services/CommonFunctions/RemovalType.cs
index 2a2ee86..750054c 100644
--- a/RegexBot/Services/CommonFunctions/RemovalType.cs
+++ b/Services/CommonFunctions/RemovalType.cs
@@ -1,9 +1,10 @@
-// Despite specific to CommonFunctionsService, this enum is meant to be visible by modules too,
-// thus it is placed within the root namespace.
-namespace RegexBot;
+namespace RegexBot;
///
/// Specifies possible outcomes for the removal of a user from a guild.
///
+// Despite specific to CommonFunctionsService, this enum is meant to be visible by modules too,
+// thus it is placed within the root namespace.
+// TODO Tends to be unused except internally. Look into removing.
public enum RemovalType {
///
/// Default value. Not used in any actual circumstances.
diff --git a/RegexBot/Services/EntityCache/EntityCacheService.cs b/Services/EntityCache/EntityCacheService.cs
similarity index 77%
rename from RegexBot/Services/EntityCache/EntityCacheService.cs
rename to Services/EntityCache/EntityCacheService.cs
index 6a3f646..ddafc27 100644
--- a/RegexBot/Services/EntityCache/EntityCacheService.cs
+++ b/Services/EntityCache/EntityCacheService.cs
@@ -2,9 +2,7 @@
namespace RegexBot.Services.EntityCache;
///
-/// Provides and maintains a database-backed cache of entities. Portions of information collected by this
-/// service may be used by modules, while other portions are useful only for external applications which may
-/// require this information, such as an external web interface.
+/// Provides and maintains a database-backed cache of entities.
///
class EntityCacheService : Service {
private readonly UserCachingSubservice _uc;
diff --git a/RegexBot/Services/EntityCache/Hooks.cs b/Services/EntityCache/Hooks.cs
similarity index 98%
rename from RegexBot/Services/EntityCache/Hooks.cs
rename to Services/EntityCache/Hooks.cs
index 834009c..019756a 100644
--- a/RegexBot/Services/EntityCache/Hooks.cs
+++ b/Services/EntityCache/Hooks.cs
@@ -1,5 +1,4 @@
-using Discord.WebSocket;
-using RegexBot.Data;
+using RegexBot.Data;
using RegexBot.Services.EntityCache;
namespace RegexBot;
diff --git a/RegexBot/Services/EntityCache/MessageCachingSubservice.cs b/Services/EntityCache/MessageCachingSubservice.cs
similarity index 99%
rename from RegexBot/Services/EntityCache/MessageCachingSubservice.cs
rename to Services/EntityCache/MessageCachingSubservice.cs
index dbea345..32c4ede 100644
--- a/RegexBot/Services/EntityCache/MessageCachingSubservice.cs
+++ b/Services/EntityCache/MessageCachingSubservice.cs
@@ -1,5 +1,4 @@
using Discord;
-using Discord.WebSocket;
using RegexBot.Data;
using static RegexBot.RegexbotClient;
diff --git a/RegexBot/Services/EntityCache/UserCachingSubservice.cs b/Services/EntityCache/UserCachingSubservice.cs
similarity index 97%
rename from RegexBot/Services/EntityCache/UserCachingSubservice.cs
rename to Services/EntityCache/UserCachingSubservice.cs
index ee5fc48..e69b189 100644
--- a/RegexBot/Services/EntityCache/UserCachingSubservice.cs
+++ b/Services/EntityCache/UserCachingSubservice.cs
@@ -1,4 +1,4 @@
-using Discord.WebSocket;
+using Microsoft.EntityFrameworkCore;
using RegexBot.Common;
using RegexBot.Data;
@@ -101,8 +101,7 @@ class UserCachingSubservice {
internal CachedGuildUser? DoGuildUserQuery(ulong guildId, string search) {
static CachedGuildUser? innerQuery(ulong guildId, ulong? sID, (string name, string? disc)? nameSearch) {
var db = new BotDatabaseContext();
-
- var query = db.GuildUserCache.Where(c => c.GuildId == (long)guildId);
+ var query = db.GuildUserCache.Include(gu => gu.User).Where(c => c.GuildId == (long)guildId);
if (sID.HasValue)
query = query.Where(c => c.UserId == (long)sID.Value);
if (nameSearch != null) {
diff --git a/RegexBot/Services/Logging/Hooks.cs b/Services/Logging/Hooks.cs
similarity index 99%
rename from RegexBot/Services/Logging/Hooks.cs
rename to Services/Logging/Hooks.cs
index c6e7aae..8f2aa1a 100644
--- a/RegexBot/Services/Logging/Hooks.cs
+++ b/Services/Logging/Hooks.cs
@@ -1,7 +1,6 @@
using RegexBot.Services.Logging;
namespace RegexBot;
-
partial class RegexbotClient {
// Access set to internal for ModuleBase and Service base class
internal readonly LoggingService _svcLogging;
diff --git a/RegexBot/Services/Logging/LoggingService.cs b/Services/Logging/LoggingService.cs
similarity index 100%
rename from RegexBot/Services/Logging/LoggingService.cs
rename to Services/Logging/LoggingService.cs
diff --git a/RegexBot/Services/ModuleState/Hooks.cs b/Services/ModuleState/Hooks.cs
similarity index 99%
rename from RegexBot/Services/ModuleState/Hooks.cs
rename to Services/ModuleState/Hooks.cs
index e9b5bbf..1907c26 100644
--- a/RegexBot/Services/ModuleState/Hooks.cs
+++ b/Services/ModuleState/Hooks.cs
@@ -1,7 +1,6 @@
using RegexBot.Services.ModuleState;
namespace RegexBot;
-
partial class RegexbotClient {
// Access set to internal for ModuleBase
internal readonly ModuleStateService _svcGuildState;
diff --git a/RegexBot/Services/ModuleState/ModuleStateService.cs b/Services/ModuleState/ModuleStateService.cs
similarity index 97%
rename from RegexBot/Services/ModuleState/ModuleStateService.cs
rename to Services/ModuleState/ModuleStateService.cs
index d6aa513..ccaa13b 100644
--- a/RegexBot/Services/ModuleState/ModuleStateService.cs
+++ b/Services/ModuleState/ModuleStateService.cs
@@ -1,11 +1,8 @@
-using Discord.WebSocket;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
using RegexBot.Common;
using System.Reflection;
namespace RegexBot.Services.ModuleState;
-
///
/// Implements per-module storage and retrieval of guild-specific state data, most typically but not limited to configuration data.
/// To that end, this service handles loading and validation of per-guild configuration files.
@@ -15,8 +12,6 @@ class ModuleStateService : Service {
private readonly Dictionary _moderators;
private readonly Dictionary> _stateData;
- const string GuildLogSource = "Configuration loader";
-
public ModuleStateService(RegexbotClient bot) : base(bot) {
_moderators = new();
_stateData = new();
diff --git a/RegexBot/Services/Service.cs b/Services/Service.cs
similarity index 99%
rename from RegexBot/Services/Service.cs
rename to Services/Service.cs
index bdec16b..f5ee3b2 100644
--- a/RegexBot/Services/Service.cs
+++ b/Services/Service.cs
@@ -1,5 +1,4 @@
namespace RegexBot.Services;
-
///
/// Base class for services.
///