public async Task EvalAsync([Remainder] string code = null) { if (code == null) { return; } var options = ScriptOptions.Default.AddImports("System.Collections.Generic"); var globals = new ScriptGlobals { ctx = Context, client = Context.Client, manager = _manager }; try { var start = DateTime.Now.Millisecond; var script = CSharpScript.Create(code, options, typeof(ScriptGlobals)); var scriptState = await script.RunAsync(globals); var returnValue = scriptState.ReturnValue; if (returnValue != null) { await Context.Channel.SendMessageAsync($"<:yes:615730280619048970> **Success :**\n" + "```\n" + returnValue.ToString() + "\n```"); } } catch (Exception ex) { await Context.Channel.SendMessageAsync("<:no:615730302936940554> **Error :**\n" + "```ini\n" + ex.Message + "\n```"); } }
public async Task ExecuteAsync([Remainder] string code) { IEnumerable <string> refs = new List <string> () { "System", "System.Diagnostics", "System.Collections.Generic", "System.Linq", "System.Net", "System.Net.Http", "System.IO", "System.Threading.Tasks", "System.Xml", "Newtonsoft.Json" }; var globals = new ScriptGlobals { client = _client }; var options = ScriptOptions.Default .AddReferences(refs) .AddImports(refs); var text = code.Trim('`'); try { var script = CSharpScript.Create(text, options, typeof(ScriptGlobals)); var scriptState = await script.RunAsync(globals); var returnValue = scriptState.ReturnValue; if (returnValue != null) { await ReplyAsync($"```cs\n{returnValue.ToString()}\n```"); } else { await ReplyAsync("The script's return value output as null"); } } catch (Exception ex) { await ReplyAsync($"```cs\n{ex.Message}\n```"); } }
public async Task Bot_Cannot_MoveForward_With_North_Orientation_On_1x1_Arena( ) { // Arrange Arena arena = new Arena { Width = 1, Height = 1 }; Team team = new Team { Name = "Team!" }; Bot bot = new Bot { LocationX = 0, LocationY = 0, Orientation = Orientation.North, MaximumStamina = 1, CurrentStamina = 1, StaminaDrain = 0 }; Deployment deployment = new Deployment { Arena = arena, Team = team, Bot = bot }; bot.Deployments = (new[] { deployment }).ToList( ); Script botScript = await BotScript.PrepareScript("MoveForward();".Base64Encode( )); botScript.Compile( ); ScriptGlobals globals = new ScriptGlobals(arena, bot, new List <Bot>( )); // Act await botScript.RunAsync(globals); // Assert Assert.AreEqual(0, globals.LocationX); Assert.AreEqual(0, globals.LocationY); Assert.AreEqual(1, globals.Stamina); Assert.AreEqual(0, globals.StaminaDrain); }
public MessageNavigatorToolWindowControlViewModel(MessageNavigatorToolWindowState state) { try { MyPackage.CmmnEventAggregator.Subscribe(this); ToolWindowState = state; Status = "Ready"; Errors = null; ErrorList = new List <string>(); _scriptGlobals = new ScriptGlobals(ResetCancellationToken()); if (_scriptGlobals.IsSolutionReady) { Initialize(); } else { _scriptGlobals.SolutionReady += OnSolutionReady; } Publications = new ObservableCollection <ItemViewModel>(); Handlers = new ObservableCollection <ItemViewModel>(); } catch (Exception ex) { HandleError(ex); throw; } }
public void ScriptGlobals_LoadFromMemory_Should_Return_A_Default_Value_For_Unknown_Key() { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var key = "VAL"; // Act var result = scriptGlobals.LoadFromMemory <int>(key); // Assert result.Should().BeZero(); }
public void ScriptGlobals_Talk_Should_Add_Entry_To_Messages() { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var message = "Message!"; // Act scriptGlobals.Talk(message); // Assert botProperties.Messages.Should().HaveCount(1); botProperties.Messages.Should().Contain(message); }
public void ScriptGlobals_Action_Correctly_Ignores_CurrentMove_If_Not_Idling(Action <ScriptGlobals> action, PossibleMoves originalMove) { // Arrange var botProperties = BuildBotProperties(); botProperties.CurrentMove = originalMove; var scriptGlobals = ScriptGlobals.Build(botProperties); // Act action(scriptGlobals); // Assert originalMove.Should().NotBe(PossibleMoves.Idling); botProperties.CurrentMove.Should().Be(originalMove); }
public async Task Process(BotDto bot, ProcessingContext context) { var botProperties = context.GetBotProperties(bot.Id); try { var botScript = await GetCompiledBotScript(bot); var scriptGlobals = ScriptGlobals.Build(botProperties); await botScript.RunAsync(scriptGlobals); } catch { botProperties.CurrentMove = PossibleMoves.ScriptError; } }
public void ScriptGlobals_StoreInMemory_Should_Store_A_Value_In_Memory() { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var key = "VAL"; var value = 42; // Act scriptGlobals.StoreInMemory(key, value); // Assert botProperties.Memory.Should().HaveCount(1); botProperties.Memory.Should().ContainKey(key); botProperties.Memory.Should().ContainValue(value.Serialize()); }
public void ScriptGlobals_Action_Correctly_Sets_CurrentMove_If_Idling(Action <ScriptGlobals> action, PossibleMoves expectedMove, int moveDestinationX, int moveDestinationY) { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var originalMove = botProperties.CurrentMove; // Act action(scriptGlobals); // Assert originalMove.Should().Be(PossibleMoves.Idling); botProperties.CurrentMove.Should().Be(expectedMove); botProperties.MoveDestinationX.Should().Be(moveDestinationX); botProperties.MoveDestinationY.Should().Be(moveDestinationY); }
public void ScriptGlobals_RemoveFromMemory_Should_Remove_A_Stored_Value() { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var key = "VAL"; var value = 42; scriptGlobals.StoreInMemory(key, value); // Act scriptGlobals.RemoveFromMemory(key); // Assert botProperties.Memory.Should().HaveCount(0); }
public void ScriptGlobals_LoadFromMemory_Should_Return_A_Stored_Value() { // Arrange var botProperties = BuildBotProperties(); var scriptGlobals = ScriptGlobals.Build(botProperties); var key = "VAL"; var value = 42; scriptGlobals.StoreInMemory(key, value); // Act var result = scriptGlobals.LoadFromMemory <int>(key); // Assert result.Should().Be(value); }
private async Task <(bool, object?, Exception?)> ExecuteAsync(Message message, string code) { var globals = new ScriptGlobals { Message = message, Client = Client }; try { var result = await _eval.EvaluateAsync(code, globals); return(false, result, null); } catch (Exception exception) { return(true, null, exception); } }
public Interpreter LoadScriptInterpreter(GameClient client, OptionsDataItem item) { var parser = new YamlMenuParser(); var yamlPath = ServerContext.StoragePath + $@"\Interactive\Menus\{GetType().Name}\{item.Text}.yaml"; var globals = new ScriptGlobals { actor = Mundane, client = client, user = client.Aisling }; if (File.Exists(yamlPath)) { if (client.MenuInterpter == null) { client.MenuInterpter = parser.CreateInterpreterFromFile(yamlPath); client.MenuInterpter.Client = client; client.MenuInterpter.OnMovedToNextStep += MenuInterpreter_OnMovedToNextStep; client.MenuInterpter.RegisterCheckpointHandler($"On{item.Text}", (c, res) => { }); client.MenuInterpter.RegisterCheckpointHandler("Call", async(c, res) => { try { await CSharpScript.EvaluateAsync <bool>(res.Value, GameServer.ScriptOptions, globals); res.Result = globals.result; reset = true; } catch (Exception e) { ServerContext.Logger($"Script Error: {res.Value}."); ServerContext.Error(e); res.Result = false; } }); } } return(client.MenuInterpter); }
private void cmdGo_Click(object sender, RoutedEventArgs e) { Script script = Setup(); try { ScriptGlobals g = new ScriptGlobals(); foreach (var currentRecord in _Records) { g.CurrentRecord = currentRecord; ScriptState state = script.RunAsync(g).Result; } } catch (Exception ex) { Logger.Write($"Exception: {ex.Message}"); } }
public static void UpdateBot(this Bot bot, ScriptGlobals coreGlobals) { bot.LocationX = coreGlobals.LocationX; bot.LocationY = coreGlobals.LocationY; bot.Orientation = coreGlobals.Orientation; bot.LastAction = coreGlobals.CurrentAction; bot.CurrentPhysicalHealth = coreGlobals.PhysicalHealth; bot.CurrentStamina = coreGlobals.Stamina; bot.LastAttackLocationX = coreGlobals.LastAttackLocation.X; bot.LastAttackLocationY = coreGlobals.LastAttackLocation.Y; bot.LastAttackBotId = coreGlobals.LastAttackBotId; bot.PhysicalDamageDone += coreGlobals.PhysicalDamageDone; bot.Kills += coreGlobals.Kills; if (bot.LastAction == LastAction.SelfDestruct) { bot.TimeOfDeath = DateTime.UtcNow; } bot.Memory = coreGlobals.Memory.Serialize(); }
public async Task <bool> Roslyn(Parameter parameter) { List <int> results = new List <int>(parameter.Numbers.Length); ScriptGlobals globals = new ScriptGlobals() { n = parameter.Numbers }; Script baseScript = Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.Create("", globalsType: typeof(ScriptGlobals)); foreach (int number in parameter.Numbers) { ScriptState <int> result = await baseScript.ContinueWith <int>(parameter.Statements[number]).RunAsync(globals).ConfigureAwait(false); results.Add(result.ReturnValue); } return(Assert(results, parameter.Sum)); }
private async Task GoBot(Bot bot, Arena arena, List <Bot> bots) { Script botScript = await GetCompiledBotScript(bot); ScriptGlobals globals = new ScriptGlobals(arena, bot, bots); try { await botScript.RunAsync(globals); bot.UpdateBot(globals); } catch { // Even if there are errors in the botscript, persist memory. bot.Memory = globals.Memory.Serialize(); // Last action was a script error. bot.LastAction = LastAction.ScriptError; } }
public async Task RunAsync(CoreMessage message, string code) { var globals = new ScriptGlobals { Message = message }; try { var result = await _eval.EvaluateAsync(code, globals); if (result != null) { await message.SendAsync(result.ToString() !); } } catch (CompilationErrorException e) { await message.SendAsync(String.Join("\n", e.Diagnostics.Select(x => x.ToString()))); } }
public GraphedItems RunScript(string scriptContent) { var items = new GraphedItems(); var globals = new ScriptGlobals { Graph = new DrawMethods(items) }; try { CSharpScript.RunAsync(scriptContent, _scriptOptions, globals).GetAwaiter().GetResult(); } catch (CompilationErrorException exception) { // Since this is a compiler error then we don't need the stack trace shown, as that's just // noise that won't help end users throw new ScriptException("Compile Error", false, exception); } return(items); }
public void ScriptGlobals_Properties_Represent_BotProperties_Correctly() { // Arrange var botProperties = BuildBotProperties(); // Act var scriptGlobals = ScriptGlobals.Build(botProperties); // Assert scriptGlobals.Should().NotBeNull(); scriptGlobals.Should().BeEquivalentTo(botProperties, o => o .Including(x => x.Width) .Including(x => x.Height) .Including(x => x.X) .Including(x => x.Y) .Including(x => x.Orientation) .Including(x => x.LastMove) .Including(x => x.MaximumHealth) .Including(x => x.CurrentHealth) .Including(x => x.MaximumStamina) .Including(x => x.CurrentStamina)); }
void ProcessScriptGlobals(ProjectState state, IO.XmlStream s) { foreach (XmlNode n in s.Cursor.ChildNodes) { if (n.Name != "global") { continue; } s.SaveCursor(n); var sg = new ScriptGlobal(state, s); s.RestoreCursor(); string name_str = sg.ToString(); if (state.scriptingInterface.Globals.Contains(name_str)) { Debug.LogFile.WriteLine("Engine already contains a {0} named '{1}', ignoring...", "script global", name_str); continue; } try { ScriptGlobals.Add(name_str, sg); } catch (ArgumentException) { Debug.LogFile.WriteLine(kDuplicateErrorStr, "script global definition", name_str); } } }
private async Task Run() { try { // Build the C# script if not in CSharp mode if (Config.Mode != ConfigMode.CSharp) { Config.CSharpScript = Config.Mode == ConfigMode.Stack ? Stack2CSharpTranspiler.Transpile(Config.Stack, Config.Settings) : Loli2CSharpTranspiler.Transpile(Config.LoliCodeScript, Config.Settings); } } catch (Exception ex) { await js.AlertException(ex); } if (options.UseProxy && !options.TestProxy.Contains(':')) { await js.AlertError(Loc["InvalidProxy"], Loc["InvalidProxyMessage"]); return; } if (!options.PersistLog) { logger.Clear(); } // Close any previously opened browser if (lastBrowser != null) { await lastBrowser.CloseAsync(); } options.Variables.Clear(); isRunning = true; cts = new CancellationTokenSource(); var sw = new Stopwatch(); var wordlistType = RuriLibSettings.Environment.WordlistTypes.First(w => w.Name == options.WordlistType); var dataLine = new DataLine(options.TestData, wordlistType); var proxy = options.UseProxy ? Proxy.Parse(options.TestProxy, options.ProxyType) : null; var providers = new Providers(RuriLibSettings) { RandomUA = RandomUAProvider, RNG = RNGProvider }; // Build the BotData var data = new BotData(providers, Config.Settings, logger, dataLine, proxy, options.UseProxy); data.CancellationToken = cts.Token; data.Objects.Add("httpClient", new HttpClient()); var runtime = Python.CreateRuntime(); var pyengine = runtime.GetEngine("py"); var pco = (PythonCompilerOptions)pyengine.GetCompilerOptions(); pco.Module &= ~ModuleOptions.Optimized; data.Objects.Add("ironPyEngine", pyengine); var script = new ScriptBuilder() .Build(Config.CSharpScript, Config.Settings.ScriptSettings, PluginRepo); logger.Log($"Sliced {dataLine.Data} into:"); foreach (var slice in dataLine.GetVariables()) { var sliceValue = data.ConfigSettings.DataSettings.UrlEncodeDataAfterSlicing ? Uri.EscapeDataString(slice.AsString()) : slice.AsString(); logger.Log($"{slice.Name}: {sliceValue}"); } logger.NewEntry += OnNewEntry; try { var scriptGlobals = new ScriptGlobals(data, new ExpandoObject()); foreach (var input in Config.Settings.InputSettings.CustomInputs) { (scriptGlobals.input as IDictionary <string, object>).Add(input.VariableName, input.DefaultAnswer); } sw.Start(); var state = await script.RunAsync(scriptGlobals, null, cts.Token); foreach (var scriptVar in state.Variables) { try { var type = DescriptorsRepository.ToVariableType(scriptVar.Type); if (type.HasValue && !scriptVar.Name.StartsWith("tmp_")) { var variable = DescriptorsRepository.ToVariable(scriptVar.Name, scriptVar.Type, scriptVar.Value); variable.MarkedForCapture = data.MarkedForCapture.Contains(scriptVar.Name); options.Variables.Add(variable); } } catch { // The type is not supported, e.g. it was generated using custom C# code and not blocks // so we just disregard it } } } catch (OperationCanceledException) { data.STATUS = "ERROR"; logger.Log($"Operation canceled", LogColors.Tomato); } catch (Exception ex) { data.STATUS = "ERROR"; logger.Log($"[{data.ExecutionInfo}] {ex.GetType().Name}: {ex.Message}", LogColors.Tomato); await js.AlertError(ex.GetType().Name, $"[{data.ExecutionInfo}] {ex.Message}"); } finally { sw.Stop(); isRunning = false; logger.Log($"BOT ENDED AFTER {sw.ElapsedMilliseconds} ms WITH STATUS: {data.STATUS}"); // Save the browser for later use lastBrowser = data.Objects.ContainsKey("puppeteer") && data.Objects["puppeteer"] is Browser currentBrowser ? currentBrowser : null; // Dispose all disposable objects foreach (var obj in data.Objects.Where(o => o.Value is IDisposable)) { if (obj.Key.Contains("puppeteer")) { continue; } try { (obj.Value as IDisposable).Dispose(); } catch { } } } await loggerViewer?.Refresh(); variablesViewer?.Refresh(); await InvokeAsync(StateHasChanged); }
public CachedWriter(ScriptGlobals owner) { this.owner = owner; PrintOptions = owner.PrintOptionsImpl.Clone(); cachedList = new List<ColorAndText>(); }
public ScriptInstance() { Globals = new ScriptGlobals(this); }
public async Task <ScriptValidationResponse> Validate(ScriptValidationRequest request) { var scriptValidation = new ScriptValidationResponse(); var botScript = await PrepareScript(request.Script); ImmutableArray <Diagnostic> diagnostics; using (var sw = new SimpleStopwatch()) { diagnostics = botScript.Compile(); scriptValidation.CompilationTimeInMilliseconds = sw.ElapsedMilliseconds; } if (!diagnostics.Any(x => x.Severity == DiagnosticSeverity.Error)) { var task = Task.Run(() => { var arena = new ArenaDto { Width = 10, Height = 10 }; var bot = new BotDto { Id = Guid.NewGuid(), Name = "Bot", MaximumHealth = 100, CurrentHealth = 100, MaximumStamina = 100, CurrentStamina = 100, X = 1, Y = 1, Orientation = PossibleOrientations.South, Memory = new Dictionary <string, string>().Serialize() }; var friendBot = new BotDto { Id = Guid.NewGuid(), Name = "Friend", MaximumHealth = 100, CurrentHealth = 100, MaximumStamina = 100, CurrentStamina = 100, X = 1, Y = 3, Orientation = PossibleOrientations.North }; var enemyBot = new BotDto { Id = Guid.NewGuid(), Name = "Enemy", MaximumHealth = 100, CurrentHealth = 100, MaximumStamina = 100, CurrentStamina = 100, X = 1, Y = 5, Orientation = PossibleOrientations.North }; var botProperties = BotProperties.Build(bot, arena, new[] { bot, friendBot, enemyBot }.ToList()); var scriptGlobals = ScriptGlobals.Build(botProperties); using (var sw = new SimpleStopwatch()) { try { botScript.RunAsync(scriptGlobals).Wait(); } catch (Exception ex) { scriptValidation.ValidationMessages.Add(new ScriptValidationMessage { Message = "Runtime error: " + ex.Message }); } scriptValidation.RunTimeInMilliseconds = sw.ElapsedMilliseconds; } }); if (!task.Wait(TimeSpan.FromSeconds(2))) { scriptValidation.ValidationMessages.Add(new ScriptValidationMessage { Message = "Your script did not finish in a timely fashion!" }); scriptValidation.RunTimeInMilliseconds = long.MaxValue; } } foreach (var diagnostic in diagnostics) { if (diagnostic.Severity == DiagnosticSeverity.Error) { scriptValidation.ValidationMessages.Add(new ScriptValidationMessage { Message = diagnostic.GetMessage(), LocationStart = diagnostic.Location.SourceSpan.Start, LocationEnd = diagnostic.Location.SourceSpan.End }); } } return(scriptValidation); }
public async Task Run() { // Build the C# script if not in CSharp mode if (config.Mode != ConfigMode.CSharp) { config.CSharpScript = config.Mode == ConfigMode.Stack ? Stack2CSharpTranspiler.Transpile(config.Stack, config.Settings) : Loli2CSharpTranspiler.Transpile(config.LoliCodeScript, config.Settings); } if (options.UseProxy && !options.TestProxy.Contains(':')) { throw new InvalidProxyException(options.TestProxy); } if (!options.PersistLog) { logger.Clear(); } // Close any previously opened browser if (lastBrowser != null) { await lastBrowser.CloseAsync(); } options.Variables.Clear(); IsRunning = true; cts = new CancellationTokenSource(); var sw = new Stopwatch(); var wordlistType = RuriLibSettings.Environment.WordlistTypes.First(w => w.Name == options.WordlistType); var dataLine = new DataLine(options.TestData, wordlistType); var proxy = options.UseProxy ? Proxy.Parse(options.TestProxy, options.ProxyType) : null; var providers = new Bots.Providers(RuriLibSettings) { RNG = RNGProvider }; if (!RuriLibSettings.RuriLibSettings.GeneralSettings.UseCustomUserAgentsList) { providers.RandomUA = RandomUAProvider; } // Build the BotData var data = new BotData(providers, config.Settings, logger, dataLine, proxy, options.UseProxy) { CancellationToken = cts.Token }; using var httpClient = new HttpClient(); data.SetObject("httpClient", httpClient); var runtime = Python.CreateRuntime(); var pyengine = runtime.GetEngine("py"); var pco = (PythonCompilerOptions)pyengine.GetCompilerOptions(); pco.Module &= ~ModuleOptions.Optimized; data.SetObject("ironPyEngine", pyengine); data.AsyncLocker = new(); dynamic globals = new ExpandoObject(); var script = new ScriptBuilder() .Build(config.CSharpScript, config.Settings.ScriptSettings, PluginRepo); logger.Log($"Sliced {dataLine.Data} into:"); foreach (var slice in dataLine.GetVariables()) { var sliceValue = data.ConfigSettings.DataSettings.UrlEncodeDataAfterSlicing ? Uri.EscapeDataString(slice.AsString()) : slice.AsString(); logger.Log($"{slice.Name}: {sliceValue}"); } // Initialize resources Dictionary <string, ConfigResource> resources = new(); // Resources will need to be disposed of foreach (var opt in config.Settings.DataSettings.Resources) { try { resources[opt.Name] = opt switch { LinesFromFileResourceOptions x => new LinesFromFileResource(x), RandomLinesFromFileResourceOptions x => new RandomLinesFromFileResource(x), _ => throw new NotImplementedException() }; } catch { logger.Log($"Could not create resource {opt.Name}", LogColors.Tomato); } } // Add resources to global variables globals.Resources = resources; var scriptGlobals = new ScriptGlobals(data, globals); // Set custom inputs foreach (var input in config.Settings.InputSettings.CustomInputs) { (scriptGlobals.input as IDictionary <string, object>).Add(input.VariableName, input.DefaultAnswer); } try { sw.Start(); Started?.Invoke(this, EventArgs.Empty); var state = await script.RunAsync(scriptGlobals, null, cts.Token); foreach (var scriptVar in state.Variables) { try { var type = DescriptorsRepository.ToVariableType(scriptVar.Type); if (type.HasValue && !scriptVar.Name.StartsWith("tmp_")) { var variable = DescriptorsRepository.ToVariable(scriptVar.Name, scriptVar.Type, scriptVar.Value); variable.MarkedForCapture = data.MarkedForCapture.Contains(scriptVar.Name); options.Variables.Add(variable); } } catch { // The type is not supported, e.g. it was generated using custom C# code and not blocks // so we just disregard it } } } catch (OperationCanceledException) { data.STATUS = "ERROR"; logger.Log($"Operation canceled", LogColors.Tomato); } catch (Exception ex) { data.STATUS = "ERROR"; var logErrorMessage = RuriLibSettings.RuriLibSettings.GeneralSettings.VerboseMode ? ex.ToString() : ex.Message; logger.Log($"[{data.ExecutionInfo}] {ex.GetType().Name}: {logErrorMessage}", LogColors.Tomato); IsRunning = false; throw; } finally { sw.Stop(); logger.Log($"BOT ENDED AFTER {sw.ElapsedMilliseconds} ms WITH STATUS: {data.STATUS}"); // Save the browser for later use lastBrowser = data.TryGetObject <Browser>("puppeteer"); // Dispose stuff in data.Objects data.DisposeObjectsExcept(new[] { "puppeteer", "puppeteerPage", "puppeteerFrame" }); // Dispose resources foreach (var resource in resources.Where(r => r.Value is IDisposable) .Select(r => r.Value).Cast <IDisposable>()) { resource.Dispose(); } data.AsyncLocker.Dispose(); } IsRunning = false; Stopped?.Invoke(this, EventArgs.Empty); }
static async Task Main(string[] args) { var token = File.ReadAllText("token.ignore"); var client = new DiscordSocketClient(new DiscordSocketConfig { LogLevel = LogSeverity.Debug }); var logQueue = new ConcurrentQueue <LogMessage>(); var logCancelToken = new CancellationTokenSource(); int presenceUpdates = 0; client.Log += msg => { logQueue.Enqueue(msg); return(Task.CompletedTask); }; Console.CancelKeyPress += (_ev, _s) => { logCancelToken.Cancel(); }; var logTask = Task.Run(async() => { var fs = new FileStream("idn.log", FileMode.Append); var logStringBuilder = new StringBuilder(200); string logString = ""; byte[] helloBytes = Encoding.UTF8.GetBytes($"### new log session: {DateTime.Now} ###\n\n"); await fs.WriteAsync(helloBytes); while (!logCancelToken.IsCancellationRequested) { if (logQueue.TryDequeue(out var msg)) { if (msg.Message?.IndexOf("PRESENCE_UPDATE)") > 0) { presenceUpdates++; continue; } _ = msg.ToString(builder: logStringBuilder); logStringBuilder.AppendLine(); logString = logStringBuilder.ToString(); Debug.Write(logString, "DNET"); await fs.WriteAsync(Encoding.UTF8.GetBytes(logString)); } await fs.FlushAsync(); try { await Task.Delay(100, logCancelToken.Token); } finally { } } byte[] goodbyeBytes = Encoding.UTF8.GetBytes($"#!! end log session: {DateTime.Now} !!#\n\n\n"); await fs.WriteAsync(goodbyeBytes); await fs.DisposeAsync(); }); await client.LoginAsync(TokenType.Bot, token); await client.StartAsync(); var options = ScriptOptions.Default .AddReferences(GetAssemblies().ToArray()) .AddImports(Imports); var globals = new ScriptGlobals { Client = client, PUCount = -1, }; while (true) { Console.Write("> "); string input = Console.ReadLine(); if (input == "quit!") { break; } object eval; try { globals.PUCount = presenceUpdates; eval = await CSharpScript.EvaluateAsync(input, options, globals); } catch (Exception e) { eval = e; } Console.WriteLine(Inspector.Inspect(eval)); } await client.StopAsync(); client.Dispose(); logCancelToken.Cancel(); try { await logTask; } finally { Console.WriteLine("goodbye!"); } }