using System; using System.Threading; using System.Threading.Tasks; using ChaosBot.Models; using Discord.Commands; namespace ChaosBot.Services.ProgrammingLanguageInterpreter { public static class ProgrammingLanguageInterpreterFacade { public static bool TryInterpret(SocketCommandContext context, CustomCommand customCommand, out string errorReason) { errorReason = ""; IProgrammingLanguageInterpreter interpreter = ProgrammingLanguageInterpreterFactory.GetInterpreter(customCommand.Type); if (interpreter == null) { errorReason = "Could not set up an interpreter for the code"; return false; } try { Thread taskThread = null; Task task = Task.Run(() => { taskThread = Thread.CurrentThread; Thread.CurrentThread.Priority = ThreadPriority.Lowest; return interpreter.Interpret(context, customCommand.Content, customCommand.Command); }); const int timeout = 1000; bool isTaskCompleted = task.Wait(TimeSpan.FromMilliseconds(timeout)); if (!isTaskCompleted) { interpreter.StopExecution(); taskThread.Abort(); throw new TimeoutException($"Command '{customCommand.Command}' took more than {timeout}ms to run. It has been killed."); } string output = task.Result; if (output.Length > 0) context.Channel.SendMessageAsync(output); else context.Channel.SendMessageAsync($"Command '{customCommand.Command}' had no output."); return true; } catch (Exception ex) { errorReason = $"There was an error with your code ({ex.GetType().Name}): {ex.Message}"; return false; } } } }