Skip to content

Instantly share code, notes, and snippets.

@nathan130200
Last active December 19, 2018 17:32
Show Gist options
  • Save nathan130200/7b0ad842d408726544227d96d9679138 to your computer and use it in GitHub Desktop.
Save nathan130200/7b0ad842d408726544227d96d9679138 to your computer and use it in GitHub Desktop.
C# Eval event based.
using DSharpPlus;
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
using DSharpPlus.Entities;
using DSharpPlus.Interactivity;
using GameStage.Core.Entities.Eval;
using Humanizer;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.CodeAnalysis.Scripting.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace GameStage.Core.Modules
{
[RequireOwner]
public class BotOwnerModule : BaseCommandModule
{
[Command("shutdown"), Description("Finaliza e desliga o bot."), Aliases("desligar")]
public async Task Shutdown(CommandContext ctx,
[RemainingText, Description("Código de finalização do bot.")]
int codigo = 0)
{
await ctx.RespondAsync($"{ctx.User.Mention} :white_check_mark: Finalizando o bot com código `{codigo}`.");
await Task.Delay(2500);
Program.Exit(codigo);
}
[Command("gc"), Description("Chama o GC e tentar limpar conteúdo não utilizado da memória.")]
public async Task Gc(CommandContext ctx,
[RemainingText, Description("Quantidade de bytes que o GC deverá limpar.")]
int? quantidade = null)
{
await ctx.TriggerTypingAsync();
if (quantidade != null)
GC.Collect(quantidade.Value, GCCollectionMode.Forced);
else
GC.Collect();
var text = $"{ctx.User.Mention} Sucesso! O GC foi acionado para limpar a memporia";
if (quantidade != null)
text += $"em {quantidade.Value.Bytes().ToString("#.##")}";
text += "!";
await ctx.RespondAsync(text);
}
[Command("eval"), Description("Interpreta, Compila e Executa o trecho de código em C#")]
public async Task Eval(CommandContext ctx,
[RemainingText, Description("Código que será utilizado pela .NET Core Roslyn")]
string code)
{
await ctx.TriggerTypingAsync();
var start_index = code.IndexOf("```") + 3;
start_index = code.IndexOf('\n', start_index) + 1;
var end_index = code.LastIndexOf("```");
if (start_index != -1 && end_index != -1)
code = code.Substring(start_index, end_index - start_index);
using (var script = new GameStageBotEvulationScript(code, ctx))
{
script.OnSuccess += async state =>
{
await ctx.RespondAsync(ctx.User.Mention, embed: new DiscordEmbedBuilder()
.AsInformation()
.WithRequestedBy(ctx.User)
.WithAuthor("GST3: Eval", iconUrl: "https://i.imgur.com/zmGTgPr.png")
.AddField("Status", "Sucesso")
.AddField("Valor Retornado", state.ReturnValue != null ? state.ReturnValue.ToString().Truncate(1500) : "Nenhum valor retornado")
);
};
script.OnError += async exception =>
{
if(exception is CompilationErrorException ce)
{
var pages = new List<Page>();
var fmt = string.Empty;
var i = 1;
foreach (var error in ce.Diagnostics)
{
var ls = error.Location.GetLineSpan();
if (fmt.Length < 1500)
{
fmt += $"{ls.StartLinePosition.Line.ToString("#,##0")};" +
$"{ls.StartLinePosition.Character.ToString("#,##0")}: " +
$"{Formatter.InlineCode(error.GetMessage())}\n";
}
else
{
pages.Add(new Page
{
Content = ctx.User.Mention,
Embed = new DiscordEmbedBuilder()
.AsError()
.WithRequestedBy(ctx.User)
.WithAuthor("GST3: Eval", iconUrl: "https://i.imgur.com/zmGTgPr.png")
.WithDescription($"Página {i}/{ce.Diagnostics.Length}")
.AddField("Status", "Falha")
.AddField("Ocorreu Em", "Compilação")
.WithDescription(fmt)
});
i++;
fmt = string.Empty;
}
}
if (!string.IsNullOrEmpty(fmt))
{
i++;
pages.Add(new Page
{
Content = ctx.User.Mention,
Embed = new DiscordEmbedBuilder()
.AsError()
.WithRequestedBy(ctx.User)
.WithAuthor("GST3: Eval", iconUrl: "https://i.imgur.com/zmGTgPr.png")
.WithDescription($"Página {i}/{ce.Diagnostics.Length}")
.AddField("Status", "Falha")
.AddField("Ocorreu Em", "Compilação")
.WithDescription(fmt)
});
}
await ctx.Client.GetInteractivity()
.SendPaginatedMessage(ctx.Channel, ctx.User, pages);
}
};
await script.RunAsync();
}
}
}
}
namespace GameStage.Core.Entities.Eval
{
public class GameStageBotEvulationEnvironment
{
public GameStageBotEvulationEnvironment(CommandContext context, string code)
{
this.Context = context;
this.Code = code;
}
public string Code {
get;
private set;
}
public GameStageBot Bot {
get {
return GameStageBot.Instance;
}
}
public CommandContext Context {
get;
private set;
}
public T GetService<T>()
{
return Context.CommandsNext.Services.GetRequiredService<T>();
}
public object GetService(Type serviceType)
{
return Context.CommandsNext.Services.GetRequiredService(serviceType);
}
}
public delegate Task GameStageBotEvulationScript_OnSuccess(ScriptState<object> state);
public delegate Task GameStageBotEvulationScript_OnError(Exception exception);
public class GameStageBotEvulationScript : IDisposable
{
private volatile bool _disposed;
private volatile int _code = 0;
private event GameStageBotEvulationScript_OnSuccess _onSuccess;
private event GameStageBotEvulationScript_OnError _onError;
private InteractiveAssemblyLoader _loader;
private GameStageBotEvulationEnvironment _env;
private Script<object> _script;
public event GameStageBotEvulationScript_OnSuccess OnSuccess {
add {
_onSuccess += value;
}
remove {
_onSuccess -= value;
}
}
public event GameStageBotEvulationScript_OnError OnError {
add {
_onError += value;
}
remove {
_onError -= value;
}
}
public GameStageBotEvulationScript(string code, CommandContext context)
{
_loader = new InteractiveAssemblyLoader();
_env = new GameStageBotEvulationEnvironment(context, code);
_script = CSharpScript.Create(code, BuildScriptOptions(), typeof(GameStageBotEvulationEnvironment), _loader);
}
public void Dispose()
{
if (!_disposed)
{
_env = null;
_script = null;
_loader.Dispose();
_loader = null;
_disposed = true;
}
}
public async Task RunAsync()
{
await Task.Yield();
var compilation = _script.Compile();
if (compilation.Any(xd => xd.Severity == DiagnosticSeverity.Error))
{
await _onError?.Invoke(new CompilationErrorException("Falha ao compilar o script!", compilation));
return;
}
else
{
try
{
await _onSuccess?.Invoke(await _script.RunAsync(_env));
}
catch (Exception ex)
{
await _onError?.Invoke(ex);
}
}
}
static ScriptOptions _options;
public static ScriptOptions BuildScriptOptions()
{
if (_options != null)
return _options;
var options = ScriptOptions.Default;
options.WithFileEncoding(Encoding.UTF8)
.WithEmitDebugInformation(false)
.WithReferences(AppDomain.CurrentDomain.GetAssemblies()
.Where(xa => !xa.IsDynamic && !string.IsNullOrEmpty(xa.Location)))
.WithImports("System", "System.Text", "System.Linq", "System.Threading", "System.Threading.Tasks",
"DSharpPlus", "DSharpPlus.CommandsNext", "DSharpPlus.Interactivity", "DSharpPlus.Lavalink",
"DSharpPlus.CommandsNext.Entities", "DSharpPlus.Entities", "DSharpPlus.Lavalink.Entities",
"GameStage", "GameStage.Core");
return _options = options;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment