Re-added chat relaying
Fixed async naming scheme Added webhook for every channel Added colorful logging
This commit is contained in:
parent
e7b056342f
commit
f912b9db8f
@ -79,6 +79,13 @@ local function getResponse(parsed)
|
|||||||
local pos = getPeripheral("playerDetector").getPlayerPos(parsed.params.username)
|
local pos = getPeripheral("playerDetector").getPlayerPos(parsed.params.username)
|
||||||
if not pos then return "null" end
|
if not pos then return "null" end
|
||||||
return textutils.serializeJSON(pos)
|
return textutils.serializeJSON(pos)
|
||||||
|
elseif parsed.method == "send" then
|
||||||
|
if not parsed.params.username then
|
||||||
|
getPeripheral("chatBox").sendMessage(parsed.params.message, parsed.params.prefix)
|
||||||
|
else
|
||||||
|
getPeripheral("chatBox").sendMessageToPlayer(parsed.params.message, parsed.params.username, parsed.params.prefix)
|
||||||
|
end
|
||||||
|
return "true"
|
||||||
end
|
end
|
||||||
|
|
||||||
error({message = "No message handler for method: "..parsed.method.."!"})
|
error({message = "No message handler for method: "..parsed.method.."!"})
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.Rest;
|
using Discord.Rest;
|
||||||
|
using Discord.Webhook;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Fleck;
|
using Fleck;
|
||||||
using MinecraftDiscordBot.Commands;
|
using MinecraftDiscordBot.Commands;
|
||||||
|
using MinecraftDiscordBot.Models;
|
||||||
using MinecraftDiscordBot.Services;
|
using MinecraftDiscordBot.Services;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -26,12 +28,14 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
private readonly HashSet<ulong> _whitelistedChannels;
|
private readonly HashSet<ulong> _whitelistedChannels;
|
||||||
private readonly ConcurrentDictionary<Guid, RootCommandService> _connections = new();
|
private readonly ConcurrentDictionary<Guid, RootCommandService> _connections = new();
|
||||||
private static readonly char[] WhiteSpace = new char[] { '\t', '\n', ' ', '\r' };
|
private static readonly char[] WhiteSpace = new char[] { '\t', '\n', ' ', '\r' };
|
||||||
public ITextChannel[] _channels = Array.Empty<ITextChannel>();
|
public IEnumerable<ActiveChannel> Channels => _channels ?? throw new InvalidProgramException("Channels used before verification!");
|
||||||
|
public ActiveChannel[]? _channels;
|
||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
private readonly RootCommandService _computer;
|
private readonly RootCommandService _computer;
|
||||||
|
|
||||||
public static bool OnlineNotifications => true;
|
public static bool OnlineNotifications => true;
|
||||||
private const string ClientScriptName = "MinecraftDiscordBot.ClientScript.lua";
|
private const string ClientScriptName = "MinecraftDiscordBot.ClientScript.lua";
|
||||||
|
private const string WebhookName = "minecraftbot";
|
||||||
public readonly string ClientScript;
|
public readonly string ClientScript;
|
||||||
private readonly ITokenProvider _tokenProvider = new TimeoutTokenProvider(InstanceId, 10);
|
private readonly ITokenProvider _tokenProvider = new TimeoutTokenProvider(InstanceId, 10);
|
||||||
private static readonly int InstanceId = new Random().Next();
|
private static readonly int InstanceId = new Random().Next();
|
||||||
@ -47,10 +51,12 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
.Replace("$HOST", $"ws://{config.SocketHost}:{config.Port}");
|
.Replace("$HOST", $"ws://{config.SocketHost}:{config.Port}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Broadcast(Func<ITextChannel, Task<IUserMessage>> message) => _ = await Task.WhenAll(_channels.Select(message));
|
private Task Broadcast(Func<ITextChannel, Task<IUserMessage>> message)
|
||||||
|
=> Task.WhenAll(Channels.Select(i => message(i.Channel)));
|
||||||
public Program(BotConfiguration config) {
|
public Program(BotConfiguration config) {
|
||||||
_config = config;
|
_config = config;
|
||||||
_computer = new(this);
|
_computer = new(this);
|
||||||
|
_computer.ChatMessageReceived += MinecraftMessageReceived;
|
||||||
_administrators = config.Administrators.ToHashSet();
|
_administrators = config.Administrators.ToHashSet();
|
||||||
ClientScript = GetClientScript(config);
|
ClientScript = GetClientScript(config);
|
||||||
_client.Log += LogAsync;
|
_client.Log += LogAsync;
|
||||||
@ -63,6 +69,9 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
_whitelistedChannels = config.Channels.ToHashSet();
|
_whitelistedChannels = config.Channels.ToHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MinecraftMessageReceived(object? sender, ChatEvent e)
|
||||||
|
=> Task.Run(() => WebhookBroadcast(i => i.SendMessageAsync(e.Message, username: e.Username, avatarUrl: $"https://crafatar.com/renders/head/{e.UUID}")));
|
||||||
|
private Task<T[]> WebhookBroadcast<T>(Func<DiscordWebhookClient, Task<T>> apply) => Task.WhenAll(Channels.Select(i => apply(new DiscordWebhookClient(i.Webhook))));
|
||||||
private void LogWebSocket(LogLevel level, string message, Exception exception) => Log(new(level switch {
|
private void LogWebSocket(LogLevel level, string message, Exception exception) => Log(new(level switch {
|
||||||
LogLevel.Debug => LogSeverity.Debug,
|
LogLevel.Debug => LogSeverity.Debug,
|
||||||
LogLevel.Info => LogSeverity.Info,
|
LogLevel.Info => LogSeverity.Info,
|
||||||
@ -98,7 +107,11 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
await LogErrorAsync(BotSource, new InvalidOperationException("No valid textchannel was whitelisted!"));
|
await LogErrorAsync(BotSource, new InvalidOperationException("No valid textchannel was whitelisted!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_channels = channels;
|
_channels = await Task.WhenAll(channels.Select(async i => new ActiveChannel(i, await GetOrCreateWebhook(i))));
|
||||||
|
static async Task<IWebhook> GetOrCreateWebhook(ITextChannel i) {
|
||||||
|
var hooks = (await i.GetWebhooksAsync()).Where(i => i.Name == WebhookName).FirstOrDefault();
|
||||||
|
return hooks ?? await i.CreateWebhookAsync(WebhookName);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +205,7 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
await LogInfoAsync("Discord", $"[{arg.Author.Username}] {arg.Content}");
|
await LogInfoAsync("Discord", $"[{arg.Author.Username}] {arg.Content}");
|
||||||
// TODO: Relay Message to Chat Receiver
|
_ = Task.Run(() => _computer.Chat.SendMessageAsync(arg.Content, arg.Author.Username, cts.Token));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task SendResponse(SocketUserMessage message, ResponseType response) => response switch {
|
private Task SendResponse(SocketUserMessage message, ResponseType response) => response switch {
|
||||||
@ -261,8 +274,22 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(LogMessage msg) {
|
public static void Log(LogMessage msg) {
|
||||||
|
var oldColor = Console.ForegroundColor;
|
||||||
|
try {
|
||||||
|
Console.ForegroundColor = msg.Severity switch {
|
||||||
|
LogSeverity.Critical => ConsoleColor.Magenta,
|
||||||
|
LogSeverity.Error => ConsoleColor.Red,
|
||||||
|
LogSeverity.Warning => ConsoleColor.Yellow,
|
||||||
|
LogSeverity.Info => ConsoleColor.White,
|
||||||
|
LogSeverity.Verbose => ConsoleColor.Blue,
|
||||||
|
LogSeverity.Debug => ConsoleColor.DarkBlue,
|
||||||
|
_ => ConsoleColor.Cyan,
|
||||||
|
};
|
||||||
lock (LogLock)
|
lock (LogLock)
|
||||||
Console.WriteLine(msg.ToString());
|
Console.WriteLine(msg.ToString());
|
||||||
|
} finally {
|
||||||
|
Console.ForegroundColor = oldColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing) {
|
protected virtual void Dispose(bool disposing) {
|
||||||
@ -298,6 +325,16 @@ public class Program : IDisposable, ICommandHandler<ResponseType>, IUserRoleMana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ActiveChannel {
|
||||||
|
public ActiveChannel(ITextChannel channel, IWebhook webhook) {
|
||||||
|
Channel = channel;
|
||||||
|
Webhook = webhook;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWebhook Webhook { get; }
|
||||||
|
public ITextChannel Channel { get; }
|
||||||
|
}
|
||||||
|
|
||||||
public abstract class ResponseType {
|
public abstract class ResponseType {
|
||||||
private static string DefaultDisplay<T>(T obj) => obj?.ToString() ?? throw new InvalidProgramException("ToString did not yield anything!");
|
private static string DefaultDisplay<T>(T obj) => obj?.ToString() ?? throw new InvalidProgramException("ToString did not yield anything!");
|
||||||
public static ResponseType AsString(string message) => new StringResponse(message);
|
public static ResponseType AsString(string message) => new StringResponse(message);
|
||||||
|
26
MinecraftDiscordBot/Services/ChatBoxService.cs
Normal file
26
MinecraftDiscordBot/Services/ChatBoxService.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Discord.WebSocket;
|
||||||
|
using MinecraftDiscordBot.Commands;
|
||||||
|
|
||||||
|
namespace MinecraftDiscordBot.Services;
|
||||||
|
|
||||||
|
public class ChatBoxService : CommandRouter {
|
||||||
|
private readonly ITaskWaitSource _taskSource;
|
||||||
|
public ChatBoxService(ITaskWaitSource taskSource) => _taskSource = taskSource;
|
||||||
|
|
||||||
|
public override string HelpTextPrefix => "!chat ";
|
||||||
|
public override Task<ResponseType> FallbackHandler(SocketUserMessage message, string method, string[] parameters, CancellationToken ct)
|
||||||
|
=> throw new ReplyException($"The chat box cannot do '{method}'!");
|
||||||
|
|
||||||
|
private Task<T> Method<T>(string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters = null)
|
||||||
|
=> RootCommandService.Method(_taskSource, methodName, parser, ct, parameters);
|
||||||
|
|
||||||
|
public Task<bool> SendMessageAsync(string message, string prefix, CancellationToken ct) => Method("send", RootCommandService.Deserialize<bool>(), ct, new() {
|
||||||
|
["message"] = message,
|
||||||
|
["prefix"] = prefix
|
||||||
|
});
|
||||||
|
public Task<bool> SendMessageToPlayerAsync(string message, string username, string prefix, CancellationToken ct) => Method("send", RootCommandService.Deserialize<bool>(), ct, new() {
|
||||||
|
["message"] = message,
|
||||||
|
["username"] = username,
|
||||||
|
["prefix"] = prefix
|
||||||
|
});
|
||||||
|
}
|
@ -5,7 +5,7 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace MinecraftDiscordBot.Services;
|
namespace MinecraftDiscordBot.Services;
|
||||||
|
|
||||||
internal class PlayerDetectorService : CommandRouter {
|
public class PlayerDetectorService : CommandRouter {
|
||||||
private readonly ITaskWaitSource _taskSource;
|
private readonly ITaskWaitSource _taskSource;
|
||||||
public PlayerDetectorService(ITaskWaitSource taskSource) => _taskSource = taskSource;
|
public PlayerDetectorService(ITaskWaitSource taskSource) => _taskSource = taskSource;
|
||||||
|
|
||||||
@ -16,21 +16,21 @@ internal class PlayerDetectorService : CommandRouter {
|
|||||||
private Task<T> Method<T>(string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters = null)
|
private Task<T> Method<T>(string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters = null)
|
||||||
=> RootCommandService.Method(_taskSource, methodName, parser, ct, parameters);
|
=> RootCommandService.Method(_taskSource, methodName, parser, ct, parameters);
|
||||||
|
|
||||||
public Task<string[]> GetOnlinePlayers(CancellationToken ct) => Method("getonline", RootCommandService.Deserialize<string[]>(), ct);
|
public Task<string[]> GetOnlinePlayersAsync(CancellationToken ct) => Method("getonline", RootCommandService.Deserialize<string[]>(), ct);
|
||||||
public async Task<PlayerPosition> GetPlayerPosition(string username, CancellationToken ct)
|
public async Task<PlayerPosition> GetPlayerPosition(string username, CancellationToken ct)
|
||||||
=> (await FindPlayer(username, ct)) ?? throw new ReplyException($"User '{username}' is not online!");
|
=> (await FindPlayerAsync(username, ct)) ?? throw new ReplyException($"User '{username}' is not online!");
|
||||||
private Task<PlayerPosition?> FindPlayer(string username, CancellationToken ct) => Method("whereis", i => JsonConvert.DeserializeObject<PlayerPosition?>(i), ct, new() {
|
private Task<PlayerPosition?> FindPlayerAsync(string username, CancellationToken ct) => Method("whereis", i => JsonConvert.DeserializeObject<PlayerPosition?>(i), ct, new() {
|
||||||
["username"] = username
|
["username"] = username
|
||||||
});
|
});
|
||||||
|
|
||||||
[CommandHandler("getonline", HelpText ="Get a list of online players.")]
|
[CommandHandler("getonline", HelpText = "Get a list of online players.")]
|
||||||
public async Task<ResponseType> HandleOnlinePlayers(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
public async Task<ResponseType> HandleOnlinePlayers(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
||||||
=> ResponseType.AsString($"The following players are currently online:\n{string.Join("\n", await GetOnlinePlayers(ct))}");
|
=> ResponseType.AsString($"The following players are currently online:\n{string.Join("\n", await GetOnlinePlayersAsync(ct))}");
|
||||||
[CommandHandler("whereis", HelpText = "Find a player in the world.")]
|
[CommandHandler("whereis", HelpText = "Find a player in the world.")]
|
||||||
public async Task<ResponseType> HandleFindPlayers(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
public async Task<ResponseType> HandleFindPlayers(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
||||||
if (parameters is not { Length: 1 }) throw new ReplyException($"Give me only one username!");
|
if (parameters is not { Length: 1 }) throw new ReplyException($"Give me only one username!");
|
||||||
var username = parameters[0];
|
var username = parameters[0];
|
||||||
var player = await FindPlayer(username, ct);
|
var player = await FindPlayerAsync(username, ct);
|
||||||
if (player is null) throw new ReplyException($"{username} is currently offline!");
|
if (player is null) throw new ReplyException($"{username} is currently offline!");
|
||||||
return ResponseType.AsString($"{username} is at coordinates {player.X} {player.Y} {player.Z} in dimension {player.Dimension}.");
|
return ResponseType.AsString($"{username} is at coordinates {player.X} {player.Y} {player.Z} in dimension {player.Dimension}.");
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
=> throw new ReplyException($"The RS system has no command '{method}'!");
|
=> throw new ReplyException($"The RS system has no command '{method}'!");
|
||||||
|
|
||||||
private Task<T> Method<T>(string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters = null)
|
private Task<T> Method<T>(string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters = null)
|
||||||
=> RootCommandService.Method<T>(_taskSource, methodName, parser, ct, parameters);
|
=> RootCommandService.Method(_taskSource, methodName, parser, ct, parameters);
|
||||||
|
|
||||||
private const string CmdEnergyUsage = "energyusage";
|
private const string CmdEnergyUsage = "energyusage";
|
||||||
private const string CmdEnergyStorage = "energystorage";
|
private const string CmdEnergyStorage = "energystorage";
|
||||||
@ -34,17 +34,17 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
public async Task<int> GetEnergyStorageAsync(CancellationToken ct) => await Method(CmdEnergyStorage, int.Parse, ct);
|
public async Task<int> GetEnergyStorageAsync(CancellationToken ct) => await Method(CmdEnergyStorage, int.Parse, ct);
|
||||||
public async Task<IEnumerable<Item>> ListItemsAsync(CancellationToken ct) => await Method(CmdListItems, RootCommandService.Deserialize<IEnumerable<Item>>(), ct);
|
public async Task<IEnumerable<Item>> ListItemsAsync(CancellationToken ct) => await Method(CmdListItems, RootCommandService.Deserialize<IEnumerable<Item>>(), ct);
|
||||||
public async Task<IEnumerable<Fluid>> ListFluidsAsync(CancellationToken ct) => await Method(CmdListFluids, RootCommandService.Deserialize<IEnumerable<Fluid>>(), ct);
|
public async Task<IEnumerable<Fluid>> ListFluidsAsync(CancellationToken ct) => await Method(CmdListFluids, RootCommandService.Deserialize<IEnumerable<Fluid>>(), ct);
|
||||||
public async Task<Item> GetItemData(string itemid, CancellationToken ct) => await Method(CmdGetItem, RootCommandService.Deserialize<Item>(), ct, new() {
|
public async Task<Item> GetItemDataAsync(string itemid, CancellationToken ct) => await Method(CmdGetItem, RootCommandService.Deserialize<Item>(), ct, new() {
|
||||||
["name"] = itemid
|
["name"] = itemid
|
||||||
});
|
});
|
||||||
public async Task<Item> GetItemData(Md5Hash fingerprint, CancellationToken ct) => await Method(CmdGetItem, RootCommandService.Deserialize<Item>(), ct, new() {
|
public async Task<Item> GetItemDataAsync(Md5Hash fingerprint, CancellationToken ct) => await Method(CmdGetItem, RootCommandService.Deserialize<Item>(), ct, new() {
|
||||||
["fingerprint"] = fingerprint.ToString()
|
["fingerprint"] = fingerprint.ToString()
|
||||||
});
|
});
|
||||||
public async Task<bool> CraftItem(string itemid, int amount, CancellationToken ct) => await Method(CmdCraftItem, RootCommandService.Deserialize<bool>(), ct, new() {
|
public async Task<bool> CraftItemAsync(string itemid, int amount, CancellationToken ct) => await Method(CmdCraftItem, RootCommandService.Deserialize<bool>(), ct, new() {
|
||||||
["name"] = itemid,
|
["name"] = itemid,
|
||||||
["count"] = amount
|
["count"] = amount
|
||||||
});
|
});
|
||||||
public async Task<LuaPackedArray> RawCommand(string command, CancellationToken ct) => await Method(CmdCommand, LuaPackedArray.Deserialize, ct, new() {
|
public async Task<LuaPackedArray> RawCommandAsync(string command, CancellationToken ct) => await Method(CmdCommand, LuaPackedArray.Deserialize, ct, new() {
|
||||||
["command"] = command
|
["command"] = command
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
: parameters.Length is > 2
|
: parameters.Length is > 2
|
||||||
? throw new ReplyException("Yo, those are way too many arguments! I want only item name and maybe an amount!")
|
? throw new ReplyException("Yo, those are way too many arguments! I want only item name and maybe an amount!")
|
||||||
: throw new InvalidOperationException($"Forgot to match parameter length {parameters.Length}!");
|
: throw new InvalidOperationException($"Forgot to match parameter length {parameters.Length}!");
|
||||||
return await CraftItem(itemid, amount, ct)
|
return await CraftItemAsync(itemid, amount, ct)
|
||||||
? ResponseType.AsString($"Alright, I'm starting to craft {amount} {itemid}.")
|
? ResponseType.AsString($"Alright, I'm starting to craft {amount} {itemid}.")
|
||||||
: ResponseType.AsString($"Nope, that somehow doesn't work!");
|
: ResponseType.AsString($"Nope, that somehow doesn't work!");
|
||||||
}
|
}
|
||||||
@ -101,8 +101,8 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
if (parameters.Length is not 1) throw new ReplyException($"I only want one name or fingerprint to search for, you gave me {parameters.Length} arguments!");
|
if (parameters.Length is not 1) throw new ReplyException($"I only want one name or fingerprint to search for, you gave me {parameters.Length} arguments!");
|
||||||
itemid = parameters[0];
|
itemid = parameters[0];
|
||||||
var item = await (Md5Hash.TryParse(itemid, out var fingerprint)
|
var item = await (Md5Hash.TryParse(itemid, out var fingerprint)
|
||||||
? GetItemData(fingerprint, ct)
|
? GetItemDataAsync(fingerprint, ct)
|
||||||
: GetItemData(itemid, ct));
|
: GetItemDataAsync(itemid, ct));
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append($"We currently have {item.Amount:n0} {item.CleanDisplayName}!");
|
sb.Append($"We currently have {item.Amount:n0} {item.CleanDisplayName}!");
|
||||||
if (item.Tags is not null and var tags) {
|
if (item.Tags is not null and var tags) {
|
||||||
@ -140,7 +140,7 @@ public class RefinedStorageService : CommandRouter {
|
|||||||
public async Task<ResponseType> HandleRawCommand(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
public async Task<ResponseType> HandleRawCommand(SocketUserMessage message, string[] parameters, CancellationToken ct) {
|
||||||
_roleManager.RequireAdministrator(message.Author.Id, "You are not authorized to run raw commands on this instance!");
|
_roleManager.RequireAdministrator(message.Author.Id, "You are not authorized to run raw commands on this instance!");
|
||||||
var command = string.Join(' ', parameters);
|
var command = string.Join(' ', parameters);
|
||||||
var response = await RawCommand(command, ct);
|
var response = await RawCommandAsync(command, ct);
|
||||||
return ResponseType.AsString(response.ToString());
|
return ResponseType.AsString(response.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,9 @@ public class RootCommandService : CommandRouter, ITaskWaitSource {
|
|||||||
protected IWebSocketConnection? _socketField;
|
protected IWebSocketConnection? _socketField;
|
||||||
public override string HelpTextPrefix => "!";
|
public override string HelpTextPrefix => "!";
|
||||||
public RootCommandService(IUserRoleManager roleManager) : base() {
|
public RootCommandService(IUserRoleManager roleManager) : base() {
|
||||||
_rs = new RefinedStorageService(this, roleManager);
|
RefinedStorage = new RefinedStorageService(this, roleManager);
|
||||||
_pd = new PlayerDetectorService(this);
|
Players = new PlayerDetectorService(this);
|
||||||
|
Chat = new ChatBoxService(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<T> Method<T>(ITaskWaitSource taskSource, string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters) {
|
public static async Task<T> Method<T>(ITaskWaitSource taskSource, string methodName, Func<string, T> parser, CancellationToken ct, Dictionary<string, object>? parameters) {
|
||||||
@ -38,6 +39,10 @@ public class RootCommandService : CommandRouter, ITaskWaitSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RefinedStorageService RefinedStorage { get; }
|
||||||
|
public PlayerDetectorService Players { get; }
|
||||||
|
public ChatBoxService Chat { get; }
|
||||||
|
|
||||||
private void OnMessage(string message) {
|
private void OnMessage(string message) {
|
||||||
switch (Message.Deserialize(message)) {
|
switch (Message.Deserialize(message)) {
|
||||||
case ChatEvent msg:
|
case ChatEvent msg:
|
||||||
@ -92,15 +97,15 @@ public class RootCommandService : CommandRouter, ITaskWaitSource {
|
|||||||
return waiter;
|
return waiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ICommandHandler<ResponseType> _rs;
|
|
||||||
private readonly ICommandHandler<ResponseType> _pd;
|
|
||||||
|
|
||||||
[CommandHandler("rs", HelpText = "Provides some commands for interacting with the Refined Storage system.")]
|
[CommandHandler("rs", HelpText = "Provides some commands for interacting with the Refined Storage system.")]
|
||||||
public Task<ResponseType> RefinedStorageHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
public Task<ResponseType> RefinedStorageHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
||||||
=> _rs.HandleCommand(message, parameters, ct);
|
=> RefinedStorage.HandleCommand(message, parameters, ct);
|
||||||
[CommandHandler("pd", HelpText = "Provides some commands for interacting with the Player Detector.")]
|
[CommandHandler("pd", HelpText = "Provides some commands for interacting with the Player Detector.")]
|
||||||
public Task<ResponseType> PlayerDetectorHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
public Task<ResponseType> PlayerDetectorHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
||||||
=> _pd.HandleCommand(message, parameters, ct);
|
=> Players.HandleCommand(message, parameters, ct);
|
||||||
|
[CommandHandler("chat", HelpText = "Provides some commands for chatting.")]
|
||||||
|
public Task<ResponseType> ChatBoxHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
||||||
|
=> Chat.HandleCommand(message, parameters, ct);
|
||||||
|
|
||||||
public static Func<string, T> Deserialize<T>() => msg
|
public static Func<string, T> Deserialize<T>() => msg
|
||||||
=> JsonConvert.DeserializeObject<T>(msg) ?? throw new InvalidProgramException("Empty response!");
|
=> JsonConvert.DeserializeObject<T>(msg) ?? throw new InvalidProgramException("Empty response!");
|
||||||
|
Loading…
Reference in New Issue
Block a user