Added CLI configuration
Also halt if no valid channels are connected! Changelog: added
This commit is contained in:
		@@ -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!");
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user