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;
 | 
					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)]
 | 
					    [JsonProperty("token", Required = Required.Always)]
 | 
				
			||||||
    public string Token { get; set; } = default!;
 | 
					    [Option('t', "token", HelpText = "The Discord bot token", Required = true)]
 | 
				
			||||||
    [JsonProperty("port", Required = Required.Always)]
 | 
					    public string Token { get; init; } = default!;
 | 
				
			||||||
    public int Port { get; set; } = 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)]
 | 
					    [JsonProperty("channels", Required = Required.Always)]
 | 
				
			||||||
    public IEnumerable<ulong> Channels { get; set; } = default!;
 | 
					    [Option('c', "channel", HelpText = "The list of whitelisted channels", Required = true, Min = 1)]
 | 
				
			||||||
    [JsonProperty("prefix", Required = Required.Always)]
 | 
					    public IEnumerable<ulong> Channels { get; init; } = default!;
 | 
				
			||||||
    public string Prefix { get; set; } = 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;
 | 
				
			||||||
using Discord.Commands;
 | 
					using Discord.Commands;
 | 
				
			||||||
using Discord.Rest;
 | 
					using Discord.Rest;
 | 
				
			||||||
@@ -60,14 +61,19 @@ public class Program : IDisposable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Task<int> Main(string[] args)
 | 
					    public static Task<int> Main(string[] args)
 | 
				
			||||||
        => JsonConvert.DeserializeObject<BotConfiguration>(File.ReadAllText("config.json")) is BotConfiguration config
 | 
					        => Parser.Default.ParseArguments<BotConfiguration, ConfigFile>(args)
 | 
				
			||||||
            ? new Program(config).RunAsync()
 | 
					        .MapResult<BotConfiguration, ConfigFile, Task<int>>(
 | 
				
			||||||
            : throw new InvalidProgramException("Configuration file missing!");
 | 
					            RunWithConfig,
 | 
				
			||||||
 | 
					            RunWithConfig,
 | 
				
			||||||
 | 
					            errs => Task.FromResult(1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Task<int> RunWithConfig(IBotConfigurator arg) => new Program(arg.Config).RunAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public async Task<int> RunAsync() {
 | 
					    public async Task<int> RunAsync() {
 | 
				
			||||||
        await _client.LoginAsync(TokenType.Bot, _config.Token);
 | 
					        await _client.LoginAsync(TokenType.Bot, _config.Token);
 | 
				
			||||||
        await _client.StartAsync();
 | 
					        await _client.StartAsync();
 | 
				
			||||||
        await VerifyTextChannels();
 | 
					        if (!await HasValidChannels())
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
        StartWebSocketServer();
 | 
					        StartWebSocketServer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Block this task until the program is closed.
 | 
					        // Block this task until the program is closed.
 | 
				
			||||||
@@ -75,11 +81,21 @@ public class Program : IDisposable {
 | 
				
			|||||||
        return 0;
 | 
					        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 => {
 | 
					    private void StartWebSocketServer() => _wssv.Start(socket => {
 | 
				
			||||||
        socket.OnOpen = async () => await SocketOpened(socket);
 | 
					        socket.OnOpen = async () => await SocketOpened(socket);
 | 
				
			||||||
        socket.OnClose = async () => await SocketClosed(socket);
 | 
					        socket.OnClose = async () => await SocketClosed(socket);
 | 
				
			||||||
        socket.OnMessage = async message => await SocketReceived(socket, message);
 | 
					        socket.OnMessage = async message => await SocketReceived(socket, message);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private async IAsyncEnumerable<ITextChannel> GetValidChannels(IEnumerable<ulong> ids) {
 | 
					    private async IAsyncEnumerable<ITextChannel> GetValidChannels(IEnumerable<ulong> ids) {
 | 
				
			||||||
        foreach (var channelId in ids) {
 | 
					        foreach (var channelId in ids) {
 | 
				
			||||||
            var channel = await _client.GetChannelAsync(channelId);
 | 
					            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) {
 | 
					    private async Task SocketReceived(IWebSocketConnection socket, string message) {
 | 
				
			||||||
        if (JsonConvert.DeserializeObject<CapabilityMessage>(message) is not CapabilityMessage capability) return;
 | 
					        if (JsonConvert.DeserializeObject<CapabilityMessage>(message) is not CapabilityMessage capability) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user