9fd50ee01e
Fixed cli help texts Added administrator options for critical methods Added result state for client and server specific errors Redirect root to help text Fixed fingerprint error, fingerprint must be case sensitive Re-Added online messages Added typing trigger for discord bot messages client: fixed chunkString for empty results preemtive wrap error objects for server messages both: added raw lua RS Bridge command entry
76 lines
3.3 KiB
C#
76 lines
3.3 KiB
C#
using Discord.WebSocket;
|
|
using Fleck;
|
|
using MinecraftDiscordBot.Commands;
|
|
using MinecraftDiscordBot.Models;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace MinecraftDiscordBot.Services;
|
|
|
|
public delegate Task<TResponse> HandleCommandDelegate<TResponse>(SocketUserMessage message, string[] parameters, CancellationToken ct);
|
|
public delegate Task HandleCommandDelegate(SocketUserMessage message, string[] parameters, CancellationToken ct);
|
|
|
|
public class RootCommandService : CommandRouter, ITaskWaitSource {
|
|
protected readonly IWebSocketConnection _socket;
|
|
public override string HelpTextPrefix => "!";
|
|
public RootCommandService(IWebSocketConnection socket, IUserRoleManager roleManager) : base() {
|
|
socket.OnMessage = OnMessage;
|
|
_socket = socket;
|
|
_rs = new RefinedStorageService(this, roleManager);
|
|
}
|
|
|
|
private void OnMessage(string message) {
|
|
if (JsonConvert.DeserializeObject<ReplyMessage>(message) is not ReplyMessage msg) return;
|
|
IChunkWaiter? waiter;
|
|
lock (_syncRoot) if (!_waits.TryGetValue(msg.AnswerId, out waiter)) {
|
|
Program.LogWarningAsync("Socket", $"Invalid wait id '{msg.AnswerId}'!");
|
|
return;
|
|
}
|
|
waiter.SetResultState(msg.State);
|
|
waiter.AddChunk(msg.Chunk, msg.Total, msg.Result);
|
|
if (waiter.Finished || waiter.IsCancellationRequested)
|
|
lock (_syncRoot)
|
|
_waits.Remove(waiter.ID);
|
|
}
|
|
|
|
public Task Send(string message) => _socket.Send(message);
|
|
public Task Send(Message message) => Send(JsonConvert.SerializeObject(message));
|
|
private readonly object _syncRoot = new();
|
|
private readonly Dictionary<int, IChunkWaiter> _waits = new();
|
|
private readonly Random _rnd = new();
|
|
public IWebSocketConnectionInfo ConnectionInfo => _socket.ConnectionInfo;
|
|
|
|
private int GetFreeId() {
|
|
var attempts = 0;
|
|
while (true) {
|
|
var id = _rnd.Next();
|
|
if (!_waits.ContainsKey(id))
|
|
return id;
|
|
Program.LogWarningAsync(Program.WebSocketSource, $"Could not get a free ID after {++attempts} attempts!");
|
|
}
|
|
}
|
|
|
|
public ChunkWaiter<T> GetWaiter<T>(Func<string, T> resultParser, CancellationToken ct) {
|
|
ChunkWaiter<T> waiter;
|
|
lock (_syncRoot) {
|
|
waiter = new ChunkWaiter<T>(GetFreeId(), resultParser, ct);
|
|
_waits.Add(waiter.ID, waiter);
|
|
}
|
|
return waiter;
|
|
}
|
|
|
|
private readonly ICommandHandler<ResponseType> _rs;
|
|
[CommandHandler("rs", HelpText = "Provides some commands for interacting with the Refined Storage system.")]
|
|
public Task<ResponseType> RefinedStorageHandler(SocketUserMessage message, string[] parameters, CancellationToken ct)
|
|
=> _rs.HandleCommand(message, parameters, ct);
|
|
|
|
public static Func<string, T> Deserialize<T>() => msg
|
|
=> JsonConvert.DeserializeObject<T>(msg) ?? throw new InvalidProgramException("Empty response!");
|
|
public override Task<ResponseType> FallbackHandler(SocketUserMessage message, string method, string[] parameters, CancellationToken ct)
|
|
=> throw new ReplyException($"What the fuck do you mean by '{method}'?");
|
|
}
|
|
|
|
public interface ITaskWaitSource {
|
|
ChunkWaiter<T> GetWaiter<T>(Func<string, T> resultParser, CancellationToken ct);
|
|
Task Send(Message requestMessage);
|
|
}
|