Added CLI configuration

Also halt if no valid channels are connected!

Changelog: added
This commit is contained in:
Michael Chen 2022-01-12 14:32:25 +01:00
parent d8c1f81023
commit d120860322
No known key found for this signature in database
GPG Key ID: 1CBC7AA5671437BB
2 changed files with 60 additions and 14 deletions

View File

@ -1,14 +1,46 @@
using Newtonsoft.Json;
using CommandLine;
using Newtonsoft.Json;
using System.Text;
namespace MinecraftDiscordBot;
public class BotConfiguration {
[Verb("config", HelpText = "Manually configure the bot with CLI arguments.")]
public class BotConfiguration : IBotConfiguration, IBotConfigurator {
private const string DEFAULT_PREFIX = "!";
private const int DEFAULT_PORT = 8080;
[JsonProperty("token", Required = Required.Always)]
public string Token { get; set; } = default!;
[JsonProperty("port", Required = Required.Always)]
public int Port { get; set; } = default!;
[Option('t', "token", HelpText = "The Discord bot token", Required = true)]
public string Token { get; init; } = default!;
[JsonProperty("port", Required = Required.DisallowNull)]
[Option('p', "port", Default = DEFAULT_PORT, HelpText = "The websocket server port")]
public int Port { get; init; } = DEFAULT_PORT;
[JsonProperty("channels", Required = Required.Always)]
public IEnumerable<ulong> Channels { get; set; } = default!;
[JsonProperty("prefix", Required = Required.Always)]
public string Prefix { get; set; } = default!;
[Option('c', "channel", HelpText = "The list of whitelisted channels", Required = true, Min = 1)]
public IEnumerable<ulong> Channels { get; init; } = default!;
[JsonProperty("prefix", Required = Required.DisallowNull)]
[Option("prefix", Default = DEFAULT_PREFIX, HelpText = "The Discord bot command prefix")]
public string Prefix { get; init; } = DEFAULT_PREFIX;
[JsonIgnore]
public BotConfiguration Config => this;
}
public interface IBotConfigurator {
BotConfiguration Config { get; }
}
public interface IBotConfiguration {
string Token { get; }
int Port { get; }
IEnumerable<ulong> Channels { get; }
string Prefix { get; }
}
[Verb("file", true, HelpText = "Load a bot configuration file.")]
public class ConfigFile : IBotConfigurator {
private const string DEFAULT_CONFIGPATH = "config.json";
[Option('f', "file", Default = DEFAULT_CONFIGPATH, HelpText = "The path of the configuration file")]
public string ConfigPath { get; set; } = DEFAULT_CONFIGPATH;
public BotConfiguration Config
=> JsonConvert.DeserializeObject<BotConfiguration>(File.ReadAllText(ConfigPath, Encoding.UTF8))
?? throw new InvalidProgramException("Invalid empty config file!");
}

View File

@ -1,3 +1,4 @@
using CommandLine;
using Discord;
using Discord.Commands;
using Discord.Rest;
@ -60,14 +61,19 @@ public class Program : IDisposable {
public static Task<int> Main(string[] args)
=> JsonConvert.DeserializeObject<BotConfiguration>(File.ReadAllText("config.json")) is BotConfiguration config
? new Program(config).RunAsync()
: throw new InvalidProgramException("Configuration file missing!");
=> Parser.Default.ParseArguments<BotConfiguration, ConfigFile>(args)
.MapResult<BotConfiguration, ConfigFile, Task<int>>(
RunWithConfig,
RunWithConfig,
errs => Task.FromResult(1));
private static Task<int> RunWithConfig(IBotConfigurator arg) => new Program(arg.Config).RunAsync();
public async Task<int> RunAsync() {
await _client.LoginAsync(TokenType.Bot, _config.Token);
await _client.StartAsync();
await VerifyTextChannels();
if (!await HasValidChannels())
return 1;
StartWebSocketServer();
// Block this task until the program is closed.
@ -75,11 +81,21 @@ public class Program : IDisposable {
return 0;
}
private async Task<bool> HasValidChannels() {
if (await GetValidChannels(_whitelistedChannels).ToArrayAsync() is not { Length: > 0 } channels) {
await LogError(BotSource, new InvalidOperationException("No valid textchannel was whitelisted!"));
return false;
}
_channels = channels;
return true;
}
private void StartWebSocketServer() => _wssv.Start(socket => {
socket.OnOpen = async () => await SocketOpened(socket);
socket.OnClose = async () => await SocketClosed(socket);
socket.OnMessage = async message => await SocketReceived(socket, message);
});
private async IAsyncEnumerable<ITextChannel> GetValidChannels(IEnumerable<ulong> ids) {
foreach (var channelId in ids) {
var channel = await _client.GetChannelAsync(channelId);
@ -99,8 +115,6 @@ public class Program : IDisposable {
}
}
private async Task VerifyTextChannels() => _channels = await GetValidChannels(_whitelistedChannels).ToArrayAsync();
private async Task SocketReceived(IWebSocketConnection socket, string message) {
if (JsonConvert.DeserializeObject<CapabilityMessage>(message) is not CapabilityMessage capability) return;