3 Commits
1.0.0 ... 1.0.2

Author SHA1 Message Date
2be3a6e0c7 Added Assembly info and versioning
Changelog: added
2022-01-12 15:14:59 +01:00
49bc63aad9 Add CHANGELOG 2022-01-12 13:54:02 +00:00
d120860322 Added CLI configuration
Also halt if no valid channels are connected!

Changelog: added
2022-01-12 14:47:59 +01:00
4 changed files with 68 additions and 18 deletions

1
CHANGELOG Normal file
View File

@ -0,0 +1 @@

View File

@ -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!");
}

View File

@ -6,6 +6,13 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<Version>1.0.2</Version>
<Authors>Michael Chen</Authors>
<Company>$(Authors)</Company>
<RepositoryUrl>https://gitlab.com/chenmichael/mcdiscordbot</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AssemblyVersion>$(VersionPrefix)</AssemblyVersion>
<FileVersion>$(VersionPrefix)</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -16,8 +23,4 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project> </Project>

View 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;