65 lines
2.5 KiB
C#
65 lines
2.5 KiB
C#
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using Discord.Commands;
|
|
using NLua;
|
|
|
|
namespace ChaosBot.Services.ProgrammingLanguageInterpreter
|
|
{
|
|
internal class LuaProgrammingLanguageInterpreter : IProgrammingLanguageInterpreter
|
|
{
|
|
private readonly StringBuilder _outputBuilder = new StringBuilder();
|
|
private CancellationToken _ct;
|
|
private Lua _state;
|
|
|
|
public string Interpret(CancellationToken ct, SocketCommandContext context, string content, string command)
|
|
{
|
|
LoggingFacade.Debug($"Interpreting code for {command} using Lua");
|
|
LoggingFacade.Trace($"Using CancellationToken: {ct}");
|
|
_ct = ct;
|
|
LoggingFacade.Trace("Starting Lua interpreter");
|
|
_state = new Lua();
|
|
LoggingFacade.Trace("Setting Lua debug hook");
|
|
_state.SetDebugHook(KeraLua.LuaHookMask.Line, 0);
|
|
_state.DebugHook += LuaDebugHook;
|
|
|
|
MethodInfo printMethod = GetType().GetMethod("Print", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
LoggingFacade.Trace($"Overwriting print function with {printMethod}");
|
|
_state["print"] = _state.RegisterFunction("print", this, printMethod);
|
|
LoggingFacade.Trace("Adding command context to environment");
|
|
_state["context"] = context;
|
|
|
|
LoggingFacade.Trace("Disabling Lua `import` function");
|
|
_state.DoString ("\nimport = function () end\n");
|
|
LoggingFacade.Trace("Disabling Lua `metatable` functionality");
|
|
_state.DoString ("\ngetmetatable = function () end\n");
|
|
_state.DoString ("\nsetmetatable = function () end\n");
|
|
|
|
LoggingFacade.Trace("Running user Lua code");
|
|
_state.DoString(content, command);
|
|
|
|
LoggingFacade.Trace("Returning Lua output");
|
|
return _outputBuilder.ToString();
|
|
}
|
|
|
|
private void LuaDebugHook(object sender, NLua.Event.DebugHookEventArgs e)
|
|
{
|
|
if (_ct.IsCancellationRequested)
|
|
{
|
|
Lua l = (Lua) sender;
|
|
l.State.Error("Timeout kill");
|
|
}
|
|
}
|
|
|
|
// This is being used in the `Interpret` function to register the print function
|
|
// ReSharper disable once UnusedMember.Local
|
|
private void Print(params object[] parameters)
|
|
{
|
|
string str = string.Join("\t", from param in parameters select param == null ? string.Empty : param.ToString());
|
|
|
|
_outputBuilder.AppendLine(str);
|
|
}
|
|
}
|
|
}
|