diff --git a/SecretAdmin/API/Features/Module.cs b/SecretAdmin/API/Features/Module.cs index 8042f5e..79cac71 100644 --- a/SecretAdmin/API/Features/Module.cs +++ b/SecretAdmin/API/Features/Module.cs @@ -21,12 +21,12 @@ protected Module() public virtual void OnEnabled() { - Log.Raw($"The module {Name} [{Version}] by {Author} was enabled.", ConsoleColor.DarkMagenta); + Log.SpectreRaw($"The module {Name} [{Version}] by {Author} has been enabled.", "lightcyan1"); } public virtual void OnDisabled() { - Log.Raw($"The module {Name} [{Version}] by {Author} was disabled.", ConsoleColor.DarkMagenta); + Log.SpectreRaw($"The module {Name} [{Version}] by {Author} has been disabled.", "lightcyan1"); } public virtual void OnRegisteringCommands() diff --git a/SecretAdmin/API/ModuleManager.cs b/SecretAdmin/API/ModuleManager.cs index 704145e..effa5b4 100644 --- a/SecretAdmin/API/ModuleManager.cs +++ b/SecretAdmin/API/ModuleManager.cs @@ -5,6 +5,7 @@ using SecretAdmin.API.Features; using SecretAdmin.Features.Console; using SecretAdmin.Features.Program; +using Spectre.Console; using Module = SecretAdmin.API.Features.Module; namespace SecretAdmin.API @@ -16,29 +17,32 @@ public static class ModuleManager public static void LoadAll() { Log.WriteLine(); - Log.Raw("Loading modules dependencies!", ConsoleColor.DarkCyan); + Log.SpectreRaw("Loading module dependencies...", "lightpink1"); var startTime = DateTime.Now; + var count = 0; foreach (var file in Directory.GetFiles(Paths.ModulesDependenciesFolder, "*.dll")) { try { var assembly = Assembly.UnsafeLoadFrom(file); - Log.Raw($"Dependency {assembly.GetName().Name} ({assembly.GetName().Version}) has been loaded!"); + count++; + Log.SpectreRaw($"Dependency {assembly.GetName().Name} ({assembly.GetName().Version}) has been loaded!", "lightcyan1"); } catch (Exception e) { - Log.Raw($"Couldn't load the dependency in the path {file}\n{e}", ConsoleColor.Red); - throw; + Log.SpectreRaw($"Couldn't load the dependency in the path {file}", "deeppink2"); + AnsiConsole.WriteException(e); } } - - Log.Raw($"Dependencies loaded in {(DateTime.Now - startTime).TotalMilliseconds}ms", ConsoleColor.Cyan); - Log.Raw("Loading modules!", ConsoleColor.DarkCyan); + + Log.SpectreRaw(count > 0 ? $"{count} Dependencies loaded in {(DateTime.Now - startTime).TotalMilliseconds}ms" : "No Dependencies found.", "cornflowerblue"); + Log.SpectreRaw("Loading modules...", "lightpink1"); startTime = DateTime.Now; - + count = 0; + foreach (var file in Directory.GetFiles(Paths.ModulesFolder, "*.dll")) { var assembly = Assembly.Load(File.ReadAllBytes(file)); @@ -59,15 +63,17 @@ public static void LoadAll() module?.OnRegisteringCommands(); Modules.Add(module); + count++; } } catch (Exception e) { - Log.Raw(e, ConsoleColor.Red); + Log.SpectreRaw($"Couldn't load the module in the path {file}", "deeppink2"); + AnsiConsole.WriteException(e); } } - Log.Raw($"Modules loaded in {(DateTime.Now - startTime).TotalMilliseconds}ms", ConsoleColor.Cyan); + Log.SpectreRaw(count > 0 ? $"{count} Modules loaded in {(DateTime.Now - startTime).TotalMilliseconds}ms" : "No Modules found.", "cornflowerblue"); } } } \ No newline at end of file diff --git a/SecretAdmin/Features/Console/Log.cs b/SecretAdmin/Features/Console/Log.cs index e26fdfe..8b9d39b 100644 --- a/SecretAdmin/Features/Console/Log.cs +++ b/SecretAdmin/Features/Console/Log.cs @@ -1,6 +1,7 @@ using System; using System.Text.RegularExpressions; using SecretAdmin.API.Events.EventArgs; +using Spectre.Console; using SConsole = System.Console; using static SecretAdmin.Program; using SEvents = SecretAdmin.API.Events.Handlers.Server; @@ -22,83 +23,92 @@ public static void Intro() _`, :' '_.'' ..': ..'' '_.': : : :: :' .; :: ,. ,. :: :: ,. : `.__.'`.__.'`.__.':_; `.__.':_; :_;:_;`.__.':_;:_;:_;:_;:_;:_; "); - Write($"Secret Admin - Version v{SecretAdmin.Program.Version}"); - WriteLine(" by Jesus-QC", ConsoleColor.Blue); - WriteLine("Released under MIT License Copyright © Jesus-QC 2021", ConsoleColor.Red); + Write($"[cyan]Secret Admin - Version v{SecretAdmin.Program.Version}[/]"); + WriteLine(" [lightgoldenrod1]by Jesus-QC[/]"); + WriteLine("[thistle1]Released under MIT License Copyright © Jesus-QC 2021[/]"); - if (!ConfigManager.SecretAdminConfig.ManualStart) - return; - - WriteLine("Press any key to continue.", ConsoleColor.Green); - SConsole.ReadKey(); + if (ConfigManager.SecretAdminConfig.ManualStart) + ReadKey(); } public static void Input(string message, string title = "SERVER") { - SConsole.ForegroundColor = ConsoleColor.Yellow; - SConsole.Write($"{title} >>> "); - Raw(message, ConsoleColor.Magenta, false); + Write($"\n{title} >>> ", ConsoleColor.Yellow); + WriteLine(message.EscapeMarkup(), ConsoleColor.Magenta); } public static void Alert(object message, bool showTimeStamp = true) { if (showTimeStamp) - Write($"[{DateTime.Now:T}] ", ConsoleColor.DarkRed); + Write($"[[{DateTime.Now:T}]] ", ConsoleColor.DarkRed); - Write("[SecretAdmin] ", ConsoleColor.Yellow); + Write("[[SecretAdmin]] ", ConsoleColor.Yellow); SConsole.Write("(Alert) "); WriteLine(message, ConsoleColor.Gray); } + + public static void ReadKey() + { + SConsole.ForegroundColor = ConsoleColor.White; + WriteLine(); + AnsiConsole.Write(new Rule("[darkslategray3]Press any key to continue.[/]")); + SConsole.ReadKey(); + } // Alerts - public static void Raw(object message, ConsoleColor color = ConsoleColor.White, bool showTimeStamp = true) => WriteLine(showTimeStamp ? $"[{DateTime.Now:T}] {message}" : message, color); - + public static void Raw(object message, ConsoleColor color = ConsoleColor.White, bool showTimeStamp = true) => WriteLine(showTimeStamp ? $"[[{DateTime.Now:T}]] {message.ToString().EscapeMarkup()}" : message, color); + public static void SpectreRaw(object message, string color = "white", bool showTimeStamp = false, string timestampColor = "white") + { + WriteLine(showTimeStamp ? $"[{timestampColor}][[{DateTime.Now:T}]][/] [{color}]{message.ToString().EscapeMarkup()}[/]" : $"[{color}]{message.ToString().EscapeMarkup()}[/]"); + } + private static void Info(string title, string message) { - Write($"[{DateTime.Now:T}] ", ConsoleColor.Magenta); - Write("[INFO] ", ConsoleColor.DarkCyan); - Write($"{title} ", ConsoleColor.Yellow); - WriteLine(message); + Write($"[[{DateTime.Now:T}]] ", ConsoleColor.Magenta); + Write("[[INFO]] ", ConsoleColor.Cyan); + Write($"[{title}] ", ConsoleColor.Yellow); + WriteLine(message.EscapeMarkup()); } private static void Error(string title, string message) { - Write($"[{DateTime.Now:T}] ", ConsoleColor.DarkYellow); - Write("[ERROR] ", ConsoleColor.Red); - Write($"{title} ", ConsoleColor.Yellow); - WriteLine(message, ConsoleColor.Red); + Write($"[[{DateTime.Now:T}]] ", ConsoleColor.Magenta); + Write("[deeppink2][[ERROR]][/] "); + Write($"[{title}] ", ConsoleColor.Yellow); + WriteLine($"[deeppink2]{message.EscapeMarkup()}[/]"); } private static void Debug(string title, string message) { - Write($"[{DateTime.Now:T}] ", ConsoleColor.DarkGray); - Write("[DEBUG] ", ConsoleColor.Blue); - Write($"{title} ", ConsoleColor.DarkGray); - WriteLine(message, ConsoleColor.Cyan); + Write($"[grey58][[{DateTime.Now:T}]][/] "); + Write("[[DEBUG]] ", ConsoleColor.Blue); + Write($"[grey58][{title}][/] "); + WriteLine(message.EscapeMarkup(), ConsoleColor.Cyan); } private static void Warn(string title, string message) { - Write($"[{DateTime.Now:T}] ", ConsoleColor.Yellow); - Write("[WARN] ", ConsoleColor.Magenta); - Write($"{title} ", ConsoleColor.DarkYellow); - WriteLine(message, ConsoleColor.Yellow); + Write($"[[{DateTime.Now:T}]] ", ConsoleColor.Magenta); + Write("[gold1][[WARN]][/] "); + Write($"[plum2][{title}][/] ", ConsoleColor.DarkYellow); + WriteLine(message.EscapeMarkup(), ConsoleColor.Yellow); } public static void WriteLine(object message = null, ConsoleColor color = ConsoleColor.White) { SConsole.ForegroundColor = color; - SConsole.WriteLine(message); - ProgramLogger?.AppendLog(message, true); + AnsiConsole.MarkupLine(message?.ToString() ?? ""); } public static void Write(object message = null, ConsoleColor color = ConsoleColor.White) { SConsole.ForegroundColor = color; - SConsole.Write(message); - ProgramLogger?.AppendLog(message); + AnsiConsole.Markup(message?.ToString() ?? ""); } + + public static T GetOption(string msg, T def) => AnsiConsole.Ask($"[lightcyan3]{msg}[/]", def); + public static bool GetConfirm(string msg, bool def) => AnsiConsole.Confirm($"[lightcyan3]{msg}[/]", def); public static void HandleMessage(string message, byte code) { @@ -136,7 +146,15 @@ public static void HandleMessage(string message, byte code) } else { - Raw(message, (ConsoleColor)code); + switch (code) + { + case 10: + SpectreRaw(message, "springgreen3", true, "slateblue1"); + break; + default: + Raw(message, (ConsoleColor)code); + break; + } } } diff --git a/SecretAdmin/Features/Program/ArgumentsManager.cs b/SecretAdmin/Features/Program/ArgumentsManager.cs index 9d79883..a818592 100644 --- a/SecretAdmin/Features/Program/ArgumentsManager.cs +++ b/SecretAdmin/Features/Program/ArgumentsManager.cs @@ -2,7 +2,6 @@ { public static class ArgumentsManager { - // TODO: this /* * Arguments: * --reconfigure -r diff --git a/SecretAdmin/Features/Program/InputManager.cs b/SecretAdmin/Features/Program/InputManager.cs index 95c775d..0c21ce6 100644 --- a/SecretAdmin/Features/Program/InputManager.cs +++ b/SecretAdmin/Features/Program/InputManager.cs @@ -1,4 +1,5 @@ using SecretAdmin.Features.Console; +using SecretAdmin.Features.Server.Enums; namespace SecretAdmin.Features.Program { @@ -12,7 +13,7 @@ public static void Start() if (string.IsNullOrWhiteSpace(input)) continue; - + input = input.TrimStart(); Log.DeletePrevConsoleLine(); @@ -24,6 +25,12 @@ public static void Start() private static void ManageInput(string input) { + if (SecretAdmin.Program.Server.Status == ServerStatus.Restarting) + { + Log.Alert("The server hasn't been initialized yet."); + return; + } + Log.Input(input); SecretAdmin.Program.Server.Socket.SendMessage(input); } diff --git a/SecretAdmin/Features/Program/Paths.cs b/SecretAdmin/Features/Program/Paths.cs index 865b6e3..f04c3ef 100644 --- a/SecretAdmin/Features/Program/Paths.cs +++ b/SecretAdmin/Features/Program/Paths.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; namespace SecretAdmin.Features.Program { @@ -15,7 +16,7 @@ public static class Paths public static void Load() { - MainFolder = "SecretAdmin"; + MainFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SecretAdmin"); LogsFolder = Path.Combine(MainFolder, "Logs"); ServerLogsFolder = Path.Combine(LogsFolder, "Server"); ProgramLogsFolder = Path.Combine(LogsFolder, "SecretAdmin"); diff --git a/SecretAdmin/Features/Program/ProgramIntroduction.cs b/SecretAdmin/Features/Program/ProgramIntroduction.cs index e78b0fc..0f6eb71 100644 --- a/SecretAdmin/Features/Program/ProgramIntroduction.cs +++ b/SecretAdmin/Features/Program/ProgramIntroduction.cs @@ -2,6 +2,7 @@ using System.IO; using SecretAdmin.Features.Console; using SecretAdmin.Features.Program.Config; +using Spectre.Console; namespace SecretAdmin.Features.Program { @@ -22,63 +23,38 @@ public static void ShowIntroduction() var cfg = new MainConfig { - AutoUpdater = GetOption("Do you want to enable the auto updater?"), - ManualStart = GetOption("Do you want to manually have to enter a key to start the server?"), - SafeShutdown = GetOption("Do you want to safe shutdown the game processes?"), - ArchiveLogsDays = GetOption("In how many days the logs should be archived?", "1"), - RestartOnCrash = GetOption("Should the server automatically restart itself when it crashes?"), - RestartWithLowMemory = GetOption("Should the server restart itself when it has low memory?"), - MaxDefaultMemory = GetOption("Max memory the server can use, in MB.", "2048") + AutoUpdater = Log.GetConfirm("Do you want to enable the auto updater?", true), + ManualStart = Log.GetConfirm("Do you want to manually have to enter a key to start the server?", false), + SafeShutdown = Log.GetConfirm("Do you want to safe shutdown the game processes?", true), + ArchiveLogsDays = Log.GetOption("In how many days the logs should be archived?", 1), + RestartOnCrash = Log.GetConfirm("Should the server automatically restart itself when it crashes?", true), + RestartWithLowMemory = Log.GetConfirm("Should the server restart itself when it has low memory?", true), + MaxDefaultMemory = Log.GetOption("Max memory the server can use, in MB.", 2048) }; Paths.Load(); SecretAdmin.Program.ConfigManager.SaveConfig(cfg); Log.WriteLine(); - Log.Raw("That were all the program configs! You can edit them always in /SecretAdmin/config.yml.", ConsoleColor.Cyan); - Log.Alert("Time to edit the default server configs."); + Log.SpectreRaw($"That were all the program configs! You can edit them always in {Paths.ProgramConfig}.","skyblue2"); + Log.Alert("Time to edit the default server configs.\n"); // Server Options var srvConfig = new ServerConfig() { - Port = (uint)GetOption("Which should be the default server port?", "7777"), - RoundsToRestart = GetOption("In how many rounds the server should restart itself. -1 disable, 0 every round", "-1") + Port = Log.GetOption("Which should be the default server port?", (uint)7777), + RoundsToRestart = Log.GetOption("In how many rounds the server should restart itself. -1 disable, 0 every round", -1) }; + Log.SpectreRaw($"That were your default server configs! You can edit them always in {Path.Combine(Paths.ServerConfigsFolder, "default.yml")}.","skyblue2"); SecretAdmin.Program.ConfigManager.SaveServerConfig(srvConfig); // Start the server Log.Alert("Ok, thats all! Time to enjoy the server :)"); - System.Console.ForegroundColor = ConsoleColor.Green; - System.Console.WriteLine("Press any key to continue."); - System.Console.ReadKey(); - Directory.CreateDirectory("SecretAdmin"); - } - - private static bool GetOption(string msg) - { - START: - Log.Alert($"{msg} yes (y) / no (n)"); - var opt = System.Console.ReadLine()?.ToLower(); - if (!string.IsNullOrWhiteSpace(opt) && (opt[0] == 'y' || opt[0] == 'n')) - return opt[0] == 'y'; - Log.Alert("An error occurred parsing the input, please try again!"); - goto START; - } - - private static int GetOption(string msg, string def) - { - START: - Log.Alert($"{msg} introduce a number. (default = {def})"); - var opt = System.Console.ReadLine(); - if (string.IsNullOrWhiteSpace(opt)) - return int.Parse(def); - if (int.TryParse(opt, out var z)) - return z; - Log.Alert("An error occurred parsing the input, please try again!"); - goto START; + Log.ReadKey(); + Directory.CreateDirectory(Paths.MainFolder); } } } \ No newline at end of file diff --git a/SecretAdmin/Features/Server/Commands/CommandHandler.cs b/SecretAdmin/Features/Server/Commands/CommandHandler.cs index 63503c4..2c4b590 100644 --- a/SecretAdmin/Features/Server/Commands/CommandHandler.cs +++ b/SecretAdmin/Features/Server/Commands/CommandHandler.cs @@ -6,6 +6,7 @@ using SecretAdmin.Features.Console; using SecretAdmin.Features.Program; using SecretAdmin.Features.Server.Enums; +using Spectre.Console; namespace SecretAdmin.Features.Server.Commands { @@ -38,6 +39,27 @@ private void ExitCommand() SecretAdmin.Program.Server.Socket.SendMessage("exit"); } + [ConsoleCommand("Files")] + private void FilesCommand() + { + var root = new Tree($"\n[white]{Paths.MainFolder}[/]"); + var logs = root.AddNode("[yellow]Logs[/]"); + root.AddNode("[yellow]Configs[/]"); + root.AddNode("[yellow]Modules[/]"); + root.AddNode("[blue]config.yml[/]"); + logs.AddNode("[lime]SecretAdmin[/]"); + logs.AddNode("[lime]Server[/]"); + + AnsiConsole.Write(root); + Log.WriteLine(); + } + + [ConsoleCommand("sacreate")] + private void CreateServerFileCommand() + { + + } + public CommandHandler() { var ti = typeof(CommandHandler).GetTypeInfo(); diff --git a/SecretAdmin/Features/Server/Enums/ServerStatus.cs b/SecretAdmin/Features/Server/Enums/ServerStatus.cs index 9221b34..ffde957 100644 --- a/SecretAdmin/Features/Server/Enums/ServerStatus.cs +++ b/SecretAdmin/Features/Server/Enums/ServerStatus.cs @@ -4,6 +4,7 @@ public enum ServerStatus { Online, Exiting, - Restarting + Restarting, + Idling } } \ No newline at end of file diff --git a/SecretAdmin/Features/Server/MemoryManager.cs b/SecretAdmin/Features/Server/MemoryManager.cs index 8ae839d..cc35b2e 100644 --- a/SecretAdmin/Features/Server/MemoryManager.cs +++ b/SecretAdmin/Features/Server/MemoryManager.cs @@ -32,7 +32,7 @@ private async void CheckUse() if (mem > ConfigManager.SecretAdminConfig.MaxDefaultMemory) { - Log.Raw($"LOW MEMORY. USING {mem}MB / {ConfigManager.SecretAdminConfig.MaxDefaultMemory}"); + Log.SpectreRaw($"LOW MEMORY. USING {mem}MB / {ConfigManager.SecretAdminConfig.MaxDefaultMemory}", "gold1"); await Task.Delay(2500); if (ConfigManager.SecretAdminConfig.RestartWithLowMemory) diff --git a/SecretAdmin/Features/Server/ScpServer.cs b/SecretAdmin/Features/Server/ScpServer.cs index 4138715..5029cc3 100644 --- a/SecretAdmin/Features/Server/ScpServer.cs +++ b/SecretAdmin/Features/Server/ScpServer.cs @@ -101,7 +101,7 @@ private void OnExited(object o, EventArgs e) public void Kill() { - MemoryManager.Dispose(); + MemoryManager?.Dispose(); MemoryManager = null; Socket?.Dispose(); Socket = null; diff --git a/SecretAdmin/Features/Server/SilentCrashHandler.cs b/SecretAdmin/Features/Server/SilentCrashHandler.cs index c46c3c4..6f370c4 100644 --- a/SecretAdmin/Features/Server/SilentCrashHandler.cs +++ b/SecretAdmin/Features/Server/SilentCrashHandler.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using SecretAdmin.Features.Console; +using SecretAdmin.Features.Server.Enums; using Main = SecretAdmin.Program; namespace SecretAdmin.Features.Server @@ -24,8 +25,11 @@ private async void SendPing() await Task.Delay(15000); while (!_killed) { - _server.SendMessage("saping"); - _pingCount++; + if (Main.Server.Status == ServerStatus.Online) + { + _server.SendMessage("saping"); + _pingCount++; + } await Task.Delay(5000); if (_pingCount == 3) { diff --git a/SecretAdmin/Features/Server/SocketServer.cs b/SecretAdmin/Features/Server/SocketServer.cs index 31ea783..32201d8 100644 --- a/SecretAdmin/Features/Server/SocketServer.cs +++ b/SecretAdmin/Features/Server/SocketServer.cs @@ -6,6 +6,7 @@ using SecretAdmin.API.Events.EventArgs; using SecretAdmin.Features.Console; using SecretAdmin.Features.Server.Enums; +using Spectre.Console; using SEvents = SecretAdmin.API.Events.Handlers.Server; namespace SecretAdmin.Features.Server @@ -106,7 +107,7 @@ public void SendMessage(string message) } catch (Exception e) { - Log.Alert("ERROR " + e); + AnsiConsole.WriteException(e); } } @@ -122,17 +123,19 @@ public void HandleAction(byte action) { case OutputCodes.RoundRestart: SEvents.OnRestartedRound(); - Log.Raw("Waiting for players.", ConsoleColor.DarkCyan); + Log.SpectreRaw("Waiting for players.", "lightsteelblue1", true, "slateblue1"); _server.AddLog("Waiting for players."); break; case OutputCodes.IdleEnter: - Log.Raw("Server entered idle mode.", ConsoleColor.DarkYellow); + _server.Status = ServerStatus.Idling; + Log.SpectreRaw("Server entered idle mode.", "plum2", true, "slateblue1"); _server.AddLog("Server entered idle mode."); break; case OutputCodes.IdleExit: - Log.Raw("Server exited idle mode.", ConsoleColor.DarkYellow); + _server.Status = ServerStatus.Online; + Log.SpectreRaw("Server exited idle mode.", "plum2", true, "slateblue1"); _server.AddLog("Server exited idle mode."); break; diff --git a/SecretAdmin/Program.cs b/SecretAdmin/Program.cs index 336d6c4..ae80ab6 100644 --- a/SecretAdmin/Program.cs +++ b/SecretAdmin/Program.cs @@ -6,6 +6,7 @@ using SecretAdmin.Features.Program.Config; using SecretAdmin.Features.Server; using SecretAdmin.Features.Server.Commands; +using Spectre.Console; namespace SecretAdmin { @@ -14,7 +15,6 @@ class Program public static Version Version { get; } = new (0, 0, 0,1); public static ScpServer Server { get; private set; } public static ConfigManager ConfigManager { get; private set; } - public static Logger ProgramLogger { get; private set; } public static CommandHandler CommandHandler { get; private set; } static void Main(string[] args) @@ -22,6 +22,8 @@ static void Main(string[] args) AppDomain.CurrentDomain.ProcessExit += OnExit; Console.Title = $"SecretAdmin [v{Version}]"; + AnsiConsole.Record(); + var arguments = ArgumentsManager.GetArgs(args); Paths.Load(); @@ -29,14 +31,12 @@ static void Main(string[] args) if (ProgramIntroduction.FirstTime || arguments.Reconfigure) ProgramIntroduction.ShowIntroduction(); ConfigManager.LoadConfig(); - - if(arguments.Logs) - ProgramLogger = new Logger(Path.Combine(Paths.ProgramLogsFolder, $"{DateTime.Now:MM.dd.yyyy-hh.mm.ss}.log")); if(ConfigManager.SecretAdminConfig.AutoUpdater) AutoUpdater.CheckForUpdates(); Log.Intro(); + Utils.ArchiveControlLogs(); CommandHandler = new CommandHandler(); @@ -61,6 +61,7 @@ private static void OnExit(object obj, EventArgs ev) Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Everything seems good to go! Bye :)"); + File.WriteAllText(Path.Combine(Paths.ProgramLogsFolder, $"{DateTime.Now:MM.dd.yyyy-hh.mm.ss}.log"), AnsiConsole.ExportText()); } } } \ No newline at end of file diff --git a/SecretAdmin/SecretAdmin.csproj b/SecretAdmin/SecretAdmin.csproj index 47dbb93..9d241cf 100644 --- a/SecretAdmin/SecretAdmin.csproj +++ b/SecretAdmin/SecretAdmin.csproj @@ -12,6 +12,7 @@ +