diff --git a/TorchRemote.Models/Requests/ChatCommandRequest.cs b/TorchRemote.Models/Requests/ChatCommandRequest.cs index 743b333..7534964 100644 --- a/TorchRemote.Models/Requests/ChatCommandRequest.cs +++ b/TorchRemote.Models/Requests/ChatCommandRequest.cs @@ -1,3 +1,3 @@ namespace TorchRemote.Models.Requests; -public record ChatCommandRequest(string Command); \ No newline at end of file +public record ChatCommandRequest(string Command, bool Streamed = false, TimeSpan? StreamingDuration = null); \ No newline at end of file diff --git a/TorchRemote.Plugin/Abstractions/Controllers/IChatController.cs b/TorchRemote.Plugin/Abstractions/Controllers/IChatController.cs index 780abef..9952a4d 100644 --- a/TorchRemote.Plugin/Abstractions/Controllers/IChatController.cs +++ b/TorchRemote.Plugin/Abstractions/Controllers/IChatController.cs @@ -4,5 +4,5 @@ namespace TorchRemote.Plugin.Abstractions.Controllers; public interface IChatController { void SendMessage(ChatMessageRequest request); - Task InvokeCommand(ChatCommandRequest request); + Task InvokeCommand(ChatCommandRequest request); } diff --git a/TorchRemote.Plugin/Controllers/ChatController.cs b/TorchRemote.Plugin/Controllers/ChatController.cs index 5b05c37..2582140 100644 --- a/TorchRemote.Plugin/Controllers/ChatController.cs +++ b/TorchRemote.Plugin/Controllers/ChatController.cs @@ -1,5 +1,6 @@ using System.Net; using System.Reflection; +using System.Text.Json; using System.Text.RegularExpressions; using EmbedIO; using EmbedIO.Routing; @@ -83,7 +84,7 @@ public class ChatController : WebApiController, IChatController } [Route(HttpVerbs.Post, $"{RootPath}/command")] - public async Task InvokeCommand([JsonData] ChatCommandRequest request) + public async Task InvokeCommand([JsonData] ChatCommandRequest request) { if (Statics.CommandManager is null) throw new HttpException(HttpStatusCode.ServiceUnavailable); @@ -94,12 +95,27 @@ public class ChatController : WebApiController, IChatController var argsList = Regex.Matches(argText, "(\"[^\"]+\"|\\S+)").Cast().Select(x => x.ToString().Replace("\"", "")).ToList(); var id = Guid.NewGuid(); - var context = new WebSocketCommandContext(Statics.Torch, command.Plugin, argText, argsList, Statics.ChatModule, id); - if (await Statics.Torch.InvokeAsync(() => command.TryInvoke(context))) - return id; + CommandContext context = request.Streamed ? new StreamedCommandContext(Statics.Torch, command.Plugin, argText, argsList, id) : + new WebSocketCommandContext(Statics.Torch, command.Plugin, argText, argsList, Statics.ChatModule, id); + + if (!await Statics.Torch.InvokeAsync(() => command.TryInvoke(context))) + throw HttpException.BadRequest("Invalid syntax", request.Command); - throw HttpException.BadRequest("Invalid syntax", request.Command); + Response.StatusCode = 200; + Response.ContentType = "application/json"; + + if (request.Streamed) + { + await Task.Delay(request.StreamingDuration ?? TimeSpan.FromSeconds(15)); + await JsonSerializer.SerializeAsync(Response.OutputStream, ((StreamedCommandContext)context).Answers, Statics.SerializerOptions); + } + else + { + await JsonSerializer.SerializeAsync(Response.OutputStream, id, Statics.SerializerOptions); + } + + Response.Close(); } } @@ -117,4 +133,23 @@ internal class WebSocketCommandContext : CommandContext { _module.SendChatResponse(new ChatCommandResponse(_id, sender ?? Torch.Config.ChatName, message)); } +} + +internal class StreamedCommandContext : CommandContext +{ + private readonly Guid _id; + private readonly List _answers = new(); + + public IEnumerable Answers => _answers; + + public StreamedCommandContext(ITorchBase torch, ITorchPlugin plugin, string rawArgs, List args, Guid id) : base( + torch, plugin, Sync.MyId, rawArgs, args) + { + _id = id; + } + + public override void Respond(string message, string? sender = null, string? font = null) + { + _answers.Add(new ChatCommandResponse(_id, sender ?? Torch.Config.ChatName, message)); + } } \ No newline at end of file