Update default example configuration file
This commit is contained in:
parent
8317f09b04
commit
52d3b1b9d4
3 changed files with 92 additions and 18 deletions
|
@ -1,3 +1,45 @@
|
||||||
{
|
{
|
||||||
// To do: Write good example config and decent documentation to go along with it.
|
"$schema": "https://raw.githubusercontent.com/NoiTheCat/RegexBot/main/ServerConfigSchema.json",
|
||||||
|
"Name": "SERVER NAME", // Server name is optional, but useful as a reference
|
||||||
|
"Moderators": [
|
||||||
|
// Users and roles are accepted here.
|
||||||
|
"MODERATOR"
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
The following configuration is provided as a sample for commonly-used features.
|
||||||
|
For a detailed reference which includes all possible configuration settings, see:
|
||||||
|
(TODO put documentation link here)
|
||||||
|
*/
|
||||||
|
"RegexModerator": [
|
||||||
|
{
|
||||||
|
"Label": "No cheese",
|
||||||
|
"Regex": "cheese",
|
||||||
|
"Response": [
|
||||||
|
"say #_ You can't say that, that's illegal",
|
||||||
|
"delete"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "Secret club initiation",
|
||||||
|
"Regex": "my name is .* and I dislike cheese",
|
||||||
|
"Response": [
|
||||||
|
"say @_ We welcome you.",
|
||||||
|
"addrole &00000::Secret Club member"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"AutoResponder": [
|
||||||
|
{
|
||||||
|
"Label": "Infinite no u",
|
||||||
|
"Regex": "no u",
|
||||||
|
"Reply": "no u"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Label": "Acknowledge praise",
|
||||||
|
"Regex": "yes u",
|
||||||
|
"Reply": ":blush:"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
21
ServerConfigSchema.json
Normal file
21
ServerConfigSchema.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"Name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The server's name. The value is unused by the application and is only for user reference."
|
||||||
|
},
|
||||||
|
"Moderators": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "A list of entities which the bot should recognize as moderators.",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* schema still a work in progress */
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"Moderators"
|
||||||
|
]
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ class ModuleStateService : Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshGuildState(SocketGuild arg) {
|
private async Task RefreshGuildState(SocketGuild arg) {
|
||||||
if (await ProcessConfiguration(arg.Id)) Log($"Configuration refreshed for server {arg.Id}.");
|
if (await ProcessConfiguration(arg)) Log($"Configuration refreshed for '{arg.Name}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task RemoveGuildData(SocketGuild arg) {
|
private Task RemoveGuildData(SocketGuild arg) {
|
||||||
|
@ -60,8 +60,8 @@ class ModuleStateService : Service {
|
||||||
/// This takes an all-or-nothing approach. Should there be a single issue in processing
|
/// This takes an all-or-nothing approach. Should there be a single issue in processing
|
||||||
/// configuration, all existing state data is kept.
|
/// configuration, all existing state data is kept.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private async Task<bool> ProcessConfiguration(ulong guildId) {
|
private async Task<bool> ProcessConfiguration(SocketGuild guild) {
|
||||||
var jstr = await LoadConfigFile(guildId);
|
var jstr = await LoadConfigFile(guild);
|
||||||
JObject guildConf;
|
JObject guildConf;
|
||||||
try {
|
try {
|
||||||
var tok = JToken.Parse(jstr);
|
var tok = JToken.Parse(jstr);
|
||||||
|
@ -71,7 +71,7 @@ class ModuleStateService : Service {
|
||||||
throw new InvalidCastException("Configuration is not valid JSON.");
|
throw new InvalidCastException("Configuration is not valid JSON.");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) when (ex is JsonReaderException or InvalidCastException) {
|
} catch (Exception ex) when (ex is JsonReaderException or InvalidCastException) {
|
||||||
Log($"Error loading configuration for server ID {guildId}: {ex.Message}");
|
Log($"Error loading configuration for server ID {guild.Id}: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,40 +83,51 @@ class ModuleStateService : Service {
|
||||||
foreach (var module in BotClient.Modules) {
|
foreach (var module in BotClient.Modules) {
|
||||||
var t = module.GetType();
|
var t = module.GetType();
|
||||||
try {
|
try {
|
||||||
var state = await module.CreateGuildStateAsync(guildId, guildConf[module.Name]!);
|
var state = await module.CreateGuildStateAsync(guild.Id, guildConf[module.Name]!);
|
||||||
newStates.Add(t, state);
|
newStates.Add(t, state);
|
||||||
} catch (ModuleLoadException ex) {
|
} catch (ModuleLoadException ex) {
|
||||||
Log($"{guildId}: Error reading configuration regarding {module.Name}: {ex.Message}");
|
Log($"{guild.Id}: Error reading configuration regarding {module.Name}: {ex.Message}");
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception ex) when (ex is not ModuleLoadException) {
|
} catch (Exception ex) when (ex is not ModuleLoadException) {
|
||||||
Log("Unhandled exception while initializing guild state for module:\n" +
|
Log("Unhandled exception while initializing guild state for module:\n" +
|
||||||
$"Module: {module.Name} | " +
|
$"Module: {module.Name} | " +
|
||||||
$"Guild: {guildId} ({BotClient.DiscordClient.GetGuild(guildId)?.Name ?? "unknown name"})\n" +
|
$"Guild: {guild.Id} ({BotClient.DiscordClient.GetGuild(guild.Id)?.Name ?? "unknown name"})\n" +
|
||||||
$"```\n{ex}\n```");
|
$"```\n{ex}\n```");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock (_storageLock) {
|
lock (_storageLock) {
|
||||||
_moderators[guildId] = mods;
|
_moderators[guild.Id] = mods;
|
||||||
_stateData[guildId] = newStates;
|
_stateData[guild.Id] = newStates;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> LoadConfigFile(ulong guildId) {
|
private async Task<string> LoadConfigFile(SocketGuild guild) {
|
||||||
// Per-guild configuration exists under `config/(guild ID).json`
|
// Per-guild configuration exists under `config/(guild ID).json`
|
||||||
var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly()!.Location) +
|
var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly()!.Location) +
|
||||||
Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar;
|
Path.DirectorySeparatorChar + "config" + Path.DirectorySeparatorChar;
|
||||||
if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath);
|
if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath);
|
||||||
var path = basePath + guildId + ".json";
|
var path = basePath + guild.Id + ".json";
|
||||||
if (File.Exists(path)) {
|
if (File.Exists(path)) {
|
||||||
return await File.ReadAllTextAsync(path);
|
return await File.ReadAllTextAsync(path);
|
||||||
} else {
|
} else { // Write default configuration to new file
|
||||||
// Write default configuration to new file
|
string fileContents;
|
||||||
using var resStream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{nameof(RegexBot)}.DefaultGuildConfig.json");
|
using (var resStream = Assembly.GetExecutingAssembly()
|
||||||
using (var newFile = File.OpenWrite(path)) resStream!.CopyTo(newFile);
|
.GetManifestResourceStream($"{nameof(RegexBot)}.DefaultGuildConfig.json")!) {
|
||||||
Log($"Created initial configuration file in config{Path.DirectorySeparatorChar}{guildId}.json");
|
using var readin = new StreamReader(resStream, encoding: System.Text.Encoding.UTF8);
|
||||||
return await LoadConfigFile(guildId);
|
fileContents = readin.ReadToEnd();
|
||||||
|
}
|
||||||
|
var userex = BotClient.DiscordClient.CurrentUser;
|
||||||
|
fileContents = fileContents.Replace("SERVER NAME", guild.Name).Replace("MODERATOR", $"@{userex.Id}::{userex.Username}");
|
||||||
|
using (var newFile = File.OpenWrite(path)) {
|
||||||
|
var w = new StreamWriter(newFile);
|
||||||
|
w.Write(fileContents);
|
||||||
|
w.Flush();
|
||||||
|
w.Close();
|
||||||
|
}
|
||||||
|
Log($"Created initial configuration file in config{Path.DirectorySeparatorChar}{guild.Id}.json");
|
||||||
|
return await LoadConfigFile(guild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue