Decompiled source of Gungeon Log Archiver v1.0.0
patchers/GungeonLogArchiverPatcher.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class GungeonLogArchiverPatcher { public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" }; public static void Patch(AssemblyDefinition assembly) { Logger.Listeners.Add((ILogListener)(object)new FileLogListener()); } } public class FileLogListener : ILogListener, IDisposable { internal static string _CurrentLogPath; private readonly StreamWriter _logWriter; public FileLogListener() { _CurrentLogPath = Path.Combine(Paths.BepInExRootPath, "LogOutput_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".log"); _logWriter = new StreamWriter(_CurrentLogPath, append: false) { AutoFlush = true }; } public void LogEvent(object sender, LogEventArgs eventArgs) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) _logWriter.WriteLine($"[{eventArgs.Level,-7}:{eventArgs.Source.SourceName,10}] {eventArgs.Data}"); } public void Dispose() { _logWriter.Dispose(); } } [BepInPlugin("pretzel.etg.logarchiver", "GungeonLogArchiver", "1.0.0")] public class GungeonLogArchiverPlugin : BaseUnityPlugin { public void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown try { ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "GungeonLogArchiver.cfg"), true); int num = val.Bind<int>("Main", "Max Days", 30, "The maximum number of days to keep logs for. Older logs will be deleted at startup.").Value; int num2 = val.Bind<int>("Main", "Max Logs", 100, "The maximum number of logs to keep. The oldest log will be deleted at startup once this limit is exceeded.").Value; bool value = val.Bind<bool>("Main", "Zip Log Files", true, "Whether log files should be archived in .gz format. This saves disk space and is recommended to leave on.").Value; if (num < 0) { num = 0; } if (num2 < 0) { num2 = 0; } Regex regex = new Regex("LogOutput_([0-9]{4}-[0-9]{2}-[0-9]{2})_[0-9]{2}-[0-9]{2}-[0-9]{2}.log(?:\\.gz)?$"); List<string> list = new List<string>(); string[] files = Directory.GetFiles(Paths.BepInExRootPath); foreach (string text in files) { if (regex.IsMatch(text) && FileLogListener._CurrentLogPath != text) { list.Add(text); } } list.Sort(); list.Reverse(); int num3 = list.Count - 1; int num4 = list.Count - num2; DateTime now = DateTime.Now; CultureInfo invariantCulture = CultureInfo.InvariantCulture; int num5 = 0; while (num3 >= 0) { bool flag = false; string text2 = list[num3]; if (num4 > 0) { flag = true; num4--; } else { string value2 = regex.Match(text2).Groups[1].Captures[0].Value; int days = (now - DateTime.ParseExact(value2, "yyyy-MM-dd", invariantCulture)).Days; if (days > num) { flag = true; } } if (!flag) { break; } if (File.Exists(text2)) { num5++; File.Delete(text2); } list.RemoveAt(num3); num3--; } if (value) { foreach (string item in list) { if (item.EndsWith(".gz")) { continue; } string path = item + ".gz"; if (!File.Exists(path)) { using FileStream fileStream = File.OpenRead(item); using FileStream stream = File.Create(path); using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: false); byte[] array = new byte[4096]; int count; while ((count = fileStream.Read(array, 0, array.Length)) != 0) { gZipStream.Write(array, 0, count); } } File.Delete(item); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"deleted {num5} old logs (keeping up to {num2} logs for up to {num} days each)"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("an error occurred initializing GungeonLogArchiver: " + ex.ToString())); } } }
plugins/GungeonLogArchiver.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class GungeonLogArchiverPatcher { public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" }; public static void Patch(AssemblyDefinition assembly) { Logger.Listeners.Add((ILogListener)(object)new FileLogListener()); } } public class FileLogListener : ILogListener, IDisposable { internal static string _CurrentLogPath; private readonly StreamWriter _logWriter; public FileLogListener() { _CurrentLogPath = Path.Combine(Paths.BepInExRootPath, "LogOutput_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".log"); _logWriter = new StreamWriter(_CurrentLogPath, append: false) { AutoFlush = true }; } public void LogEvent(object sender, LogEventArgs eventArgs) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) _logWriter.WriteLine($"[{eventArgs.Level,-7}:{eventArgs.Source.SourceName,10}] {eventArgs.Data}"); } public void Dispose() { _logWriter.Dispose(); } } [BepInPlugin("pretzel.etg.logarchiver", "GungeonLogArchiver", "1.0.0")] public class GungeonLogArchiverPlugin : BaseUnityPlugin { public void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown try { ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "GungeonLogArchiver.cfg"), true); int num = val.Bind<int>("Main", "Max Days", 30, "The maximum number of days to keep logs for. Older logs will be deleted at startup.").Value; int num2 = val.Bind<int>("Main", "Max Logs", 100, "The maximum number of logs to keep. The oldest log will be deleted at startup once this limit is exceeded.").Value; bool value = val.Bind<bool>("Main", "Zip Log Files", true, "Whether log files should be archived in .gz format. This saves disk space and is recommended to leave on.").Value; if (num < 0) { num = 0; } if (num2 < 0) { num2 = 0; } Regex regex = new Regex("LogOutput_([0-9]{4}-[0-9]{2}-[0-9]{2})_[0-9]{2}-[0-9]{2}-[0-9]{2}.log(?:\\.gz)?$"); List<string> list = new List<string>(); string[] files = Directory.GetFiles(Paths.BepInExRootPath); foreach (string text in files) { if (regex.IsMatch(text) && FileLogListener._CurrentLogPath != text) { list.Add(text); } } list.Sort(); list.Reverse(); int num3 = list.Count - 1; int num4 = list.Count - num2; DateTime now = DateTime.Now; CultureInfo invariantCulture = CultureInfo.InvariantCulture; int num5 = 0; while (num3 >= 0) { bool flag = false; string text2 = list[num3]; if (num4 > 0) { flag = true; num4--; } else { string value2 = regex.Match(text2).Groups[1].Captures[0].Value; int days = (now - DateTime.ParseExact(value2, "yyyy-MM-dd", invariantCulture)).Days; if (days > num) { flag = true; } } if (!flag) { break; } if (File.Exists(text2)) { num5++; File.Delete(text2); } list.RemoveAt(num3); num3--; } if (value) { foreach (string item in list) { if (item.EndsWith(".gz")) { continue; } string path = item + ".gz"; if (!File.Exists(path)) { using FileStream fileStream = File.OpenRead(item); using FileStream stream = File.Create(path); using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: false); byte[] array = new byte[4096]; int count; while ((count = fileStream.Read(array, 0, array.Length)) != 0) { gZipStream.Write(array, 0, count); } } File.Delete(item); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"deleted {num5} old logs (keeping up to {num2} logs for up to {num} days each)"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("an error occurred initializing GungeonLogArchiver: " + ex.ToString())); } } }