69 lines
2.9 KiB
C#
69 lines
2.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
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
|
|
{
|
|
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
|
LimitedSocketCommandContext limitedContext = new LimitedSocketCommandContext(context);
|
|
Task<string> task = Task.Run(() =>
|
|
{
|
|
Thread.CurrentThread.Priority = ThreadPriority.Lowest;
|
|
return interpreter.Interpret(tokenSource.Token, limitedContext, customCommand.Content, customCommand.Command);
|
|
}, tokenSource.Token);
|
|
|
|
const int timeout = 250;
|
|
bool isTaskCompleted = task.Wait(TimeSpan.FromMilliseconds(timeout));
|
|
|
|
if (!isTaskCompleted)
|
|
{
|
|
tokenSource.Cancel();
|
|
throw new TimeoutException($"Command '{customCommand.Command}' took more than {timeout}ms to run. It has been killed.");
|
|
}
|
|
|
|
string output = task.Result;
|
|
|
|
if (output.Length > 2000)
|
|
{
|
|
context.Channel.SendMessageAsync($"Command '{customCommand.Command}' has {output.Length} characters of output. That is more than the 2000 limit. Packaging into file...").GetAwaiter().GetResult();
|
|
Stream stream = new MemoryStream(Encoding.ASCII.GetBytes(output));
|
|
if (stream.Length > 8 * 1024 * 1024)
|
|
context.Channel.SendMessageAsync($"Packaged filesize of {stream.Length / 1024 / 1024} MB is too big.");
|
|
else
|
|
context.Channel.SendFileAsync(stream, "command-output.txt");
|
|
}
|
|
else if (output.Length > 0)
|
|
context.Channel.SendMessageAsync(output);
|
|
else
|
|
context.Channel.SendMessageAsync($"Command '{customCommand.Command}' had no output.");
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LoggingFacade.Exception(ex);
|
|
errorReason = $"There was an error with your code ({ex.GetType().Name}): {ex.Message}";
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|