From 1c1f30a2976aa40c0e4e6d1252a0d0928965bdc6 Mon Sep 17 00:00:00 2001 From: limil Date: Tue, 2 Dec 2025 21:26:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86utils=E6=9B=BF=E6=8D=A2=E4=B8=BA?= =?UTF-8?q?=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BangumiRenamer.csproj | 5 +- Src/ConfigSchema/ProxyConfig.cs | 2 +- Src/ConfigSchema/TMDBConfig.cs | 2 +- Src/Tools/Config.cs | 15 +++ Src/Tools/EmbededResourceViewer.cs | 15 +-- Src/Tools/FolderCloner.cs | 11 +- Src/Tools/Logger.cs | 15 +++ Src/Tools/ShowCompletionChecker.cs | 36 ++---- Src/Utils/Config.cs | 161 --------------------------- Src/Utils/Log.cs | 169 ----------------------------- Src/Utils/ResourceLoader.cs | 41 ------- 11 files changed, 47 insertions(+), 425 deletions(-) create mode 100644 Src/Tools/Config.cs create mode 100644 Src/Tools/Logger.cs delete mode 100644 Src/Utils/Config.cs delete mode 100644 Src/Utils/Log.cs delete mode 100644 Src/Utils/ResourceLoader.cs diff --git a/BangumiRenamer.csproj b/BangumiRenamer.csproj index 9604884..08a27c8 100644 --- a/BangumiRenamer.csproj +++ b/BangumiRenamer.csproj @@ -16,12 +16,9 @@ + - - - - diff --git a/Src/ConfigSchema/ProxyConfig.cs b/Src/ConfigSchema/ProxyConfig.cs index ad4b0de..58cb2a2 100644 --- a/Src/ConfigSchema/ProxyConfig.cs +++ b/Src/ConfigSchema/ProxyConfig.cs @@ -1,4 +1,4 @@ -using BangumiRenamer.Utils; +using LLCSharpUtils; namespace BangumiRenamer.ConfigSchema; diff --git a/Src/ConfigSchema/TMDBConfig.cs b/Src/ConfigSchema/TMDBConfig.cs index 90ef023..1cecbd9 100644 --- a/Src/ConfigSchema/TMDBConfig.cs +++ b/Src/ConfigSchema/TMDBConfig.cs @@ -1,4 +1,4 @@ -using BangumiRenamer.Utils; +using LLCSharpUtils; namespace BangumiRenamer.Config; diff --git a/Src/Tools/Config.cs b/Src/Tools/Config.cs new file mode 100644 index 0000000..59778a9 --- /dev/null +++ b/Src/Tools/Config.cs @@ -0,0 +1,15 @@ +namespace BangumiRenamer.Tools; + +public class Config +{ + private static readonly Lazy _lazyConfig = new (() => + { + var config = new LLCSharpUtils.Config + { + ConfigPath = "config.json" + }; + if (!config.Load(true)) throw new Exception("Failed to load config.json"); + return config; + }); + public static LLCSharpUtils.Config G => _lazyConfig.Value; +} \ No newline at end of file diff --git a/Src/Tools/EmbededResourceViewer.cs b/Src/Tools/EmbededResourceViewer.cs index 7704d51..2f84548 100644 --- a/Src/Tools/EmbededResourceViewer.cs +++ b/Src/Tools/EmbededResourceViewer.cs @@ -1,23 +1,16 @@ -using BangumiRenamer.Utils; +using LLCSharpUtils; namespace BangumiRenamer.Tools; public class EmbededResourceViewer { - private static readonly Lazy _lazy = new (() => - { - var log = new Log(new Log.LogConfig()); - if (!log.Init()) return null; - return log; - }); - static ILog Log => _lazy.Value; - public static void PrintResourceNames() { - var names = ResourceLoader.GetAllResNames(); + var loader = new EmbeddedResourceLoader(); + var names = loader.GetAllResNames(); foreach (var name in names) { - Log.Info(name); + Logger.G.Info(name); } } } \ No newline at end of file diff --git a/Src/Tools/FolderCloner.cs b/Src/Tools/FolderCloner.cs index aa6d183..e713866 100644 --- a/Src/Tools/FolderCloner.cs +++ b/Src/Tools/FolderCloner.cs @@ -1,19 +1,10 @@ using System.Diagnostics; -using BangumiRenamer.Utils; using NativeFileDialogSharp; namespace BangumiRenamer.Tools; public static class FolderCloner { - private static readonly Lazy _lazy = new (() => - { - var log = new Log(new Log.LogConfig()); - if (!log.Init()) return null; - return log; - }); - static ILog Log => _lazy.Value; - public static void Run() { var result = Dialog.FolderPicker(); @@ -73,7 +64,7 @@ public static class FolderCloner } catch (Exception ex) { - Log.Error(ex, "Clone"); + Logger.G.Error(ex, "Clone"); } } } diff --git a/Src/Tools/Logger.cs b/Src/Tools/Logger.cs new file mode 100644 index 0000000..84328db --- /dev/null +++ b/Src/Tools/Logger.cs @@ -0,0 +1,15 @@ +using LLCSharpUtils; + +namespace BangumiRenamer.Tools; + +public class Logger +{ + private static readonly Lazy _lazy = new (() => + { + var log = new Log(new LogConfig()); + if (!log.Init()) throw new Exception("Failed to initialize log"); + return log; + }); + + public static Log G => _lazy.Value; +} \ No newline at end of file diff --git a/Src/Tools/ShowCompletionChecker.cs b/Src/Tools/ShowCompletionChecker.cs index 65451c5..faca820 100644 --- a/Src/Tools/ShowCompletionChecker.cs +++ b/Src/Tools/ShowCompletionChecker.cs @@ -1,34 +1,16 @@ using BangumiRenamer.Config; using BangumiRenamer.ConfigSchema; - -namespace BangumiRenamer.Tools; - -using Utils; using TMDbLib.Client; -using Data; using NativeFileDialogSharp; using System.Net; using System.Text; using System.Text.RegularExpressions; +using BangumiRenamer.Data; + +namespace BangumiRenamer.Tools; public static class ShowCompletionChecker { - private static readonly Lazy _lazyLog = new (() => - { - var log = new Log(new Log.LogConfig()); - if (!log.Init()) return null; - return log; - }); - static ILog Log => _lazyLog.Value; - - private static readonly Lazy _lazyConfig = new (() => - { - var config = new Config("config.json"); - if (!config.Load()) return null; - return config; - }); - static IConfig Config => _lazyConfig.Value; - static List FindShows(string checkPath) { var shows = new List(); @@ -72,11 +54,11 @@ public static class ShowCompletionChecker var checkPath = dir.Path; var shows = FindShows(checkPath); - Log.Info($"Total Shows: {shows.Count}"); + Logger.G.Info($"Total Shows: {shows.Count}"); var client = new TMDbClient( - apiKey: Config.Get().ApiKey , - proxy: new WebProxy(Config.Get().HttpProxy)); + apiKey: Config.G.Get().ApiKey , + proxy: new WebProxy(Config.G.Get().HttpProxy)); var output = new StringBuilder(); foreach (var t in shows) @@ -88,7 +70,7 @@ public static class ShowCompletionChecker var info = result.Results.FirstOrDefault(); if (info == null) { - Log.Error($"找不到对应的TV:{t.title}"); + Logger.G.Error($"找不到对应的TV:{t.title}"); continue; } foreach (var session in t.sessions) @@ -96,7 +78,7 @@ public static class ShowCompletionChecker var sessionInfo = client.GetTvSeasonAsync(info.Id, session.id).Result; if (sessionInfo == null) { - Log.Error($"季度对不上,可能找错了:{t.title} -> {info.OriginalName}"); + Logger.G.Error($"季度对不上,可能找错了:{t.title} -> {info.OriginalName}"); break; } foreach (var episode in sessionInfo.Episodes) @@ -109,6 +91,6 @@ public static class ShowCompletionChecker } } } - Log.Info(output.ToString()); + Logger.G.Info(output.ToString()); } } \ No newline at end of file diff --git a/Src/Utils/Config.cs b/Src/Utils/Config.cs deleted file mode 100644 index 4dff33f..0000000 --- a/Src/Utils/Config.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Reflection; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace BangumiRenamer.Utils; - -public class ConfigItemAttribute(string name) : Attribute -{ - public readonly string Name = name; -} - -public interface IConfigItem -{ - public void BeforeSave() - { - } - - public void AfterLoad() - { - } -} - -public interface IConfig -{ - public T Get() where T : class, IConfigItem, new(); - - public void Reset() where T : class, IConfigItem, new(); - - public bool Save(); -} - -public sealed class Config(string configPath) : IConfig -{ - public static IConfig G => _G; - public static Config _G { private get; set; } - - private static readonly ConcurrentDictionary Cache = new(); - private readonly ConcurrentDictionary _configObjects = new(); - private readonly ConcurrentDictionary _configs = new(); - - private static string GetConfigItemName(Type type) - { - if (Cache.TryGetValue(type, out var name)) return name; - name = type.Name; - if(type.GetCustomAttribute(typeof(ConfigItemAttribute)) is ConfigItemAttribute info) - { - name = string.IsNullOrEmpty(info.Name) ? type.Name : info.Name; - } - Cache[type] = name; - return name; - } - - public T Get() where T : class, IConfigItem, new() - { - var name = GetConfigItemName(typeof(T)); - if (_configObjects.TryGetValue(name, out var value)) - { - return (T) value; - } - T result; - if (_configs.TryGetValue(name, out var jObject)) - { - result = jObject.ToObject(); - result.AfterLoad(); - } - else - { - result = new T(); - } - _configObjects[name] = result; - return result; - } - - public void Reset() where T : class, IConfigItem, new() - { - var name = GetConfigItemName(typeof(T)); - _configs.TryRemove(name, out _); - _configObjects.Remove(name, out _); - } - - public bool Load() - { - _configs.Clear(); - _configObjects.Clear(); - if (!File.Exists(configPath)) return false; - try - { - var configJson = File.ReadAllText(configPath); - var config = JObject.Parse(configJson); - foreach (var kv in config) - { - _configs[kv.Key] = kv.Value.ToObject(); - } - } - catch (Exception) - { - return false; - } - return true; - } - - public bool Save() - { - if (string.IsNullOrEmpty(configPath)) return false; - try - { - foreach (var config in _configObjects) - { - config.Value.BeforeSave(); - _configs[config.Key] = JObject.FromObject(config.Value); - } - - File.WriteAllText(configPath, JsonConvert.SerializeObject(_configs, Formatting.Indented)); - } - catch (Exception) - { - return false; - } - return true; - } - - public static void CreateEmptyConfig() - { - var configItemTypes = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(assembly => - { - try - { - return assembly.GetTypes(); - } - catch (ReflectionTypeLoadException) - { - return Array.Empty(); - } - }) - .Where(type => type.IsClass && - !type.IsAbstract && - typeof(IConfigItem).IsAssignableFrom(type)) - .ToList(); - - var filePath = "config.json"; - var config = new Config(filePath); - foreach (var type in configItemTypes) - { - var name = GetConfigItemName(type); - config._configObjects[name] = (IConfigItem) Activator.CreateInstance(type); - } - config.Save(); - - if (File.Exists(filePath)) - { - // 使用 explorer.exe 的 /select 命令行参数 - string argument = $"/select,\"{filePath}\""; - - // 启动 explorer.exe 进程 - Process.Start("explorer.exe", argument); - } - } -} \ No newline at end of file diff --git a/Src/Utils/Log.cs b/Src/Utils/Log.cs deleted file mode 100644 index 94475bd..0000000 --- a/Src/Utils/Log.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System.Runtime.CompilerServices; -using Newtonsoft.Json; -using Serilog; -using Serilog.Context; -using Serilog.Core; -using Serilog.Events; -using Serilog.Sinks.SystemConsole.Themes; - -namespace BangumiRenamer.Utils; - -public interface ILog -{ - public void Debug(string message, [CallerFilePath] string callerFilePath = "", - [CallerMemberName] string callerMemberName = ""); - - public void Info(string message, [CallerFilePath] string callerFilePath = "", - [CallerMemberName] string callerMemberName = ""); - - public void Warn(string message, [CallerFilePath] string callerFilePath = "", - [CallerMemberName] string callerMemberName = ""); - - public void Error(string message, [CallerFilePath] string callerFilePath = "", - [CallerMemberName] string callerMemberName = ""); - - public void Error(Exception ex, string message); -} - -public sealed class Log : ILog -{ - public enum LogLevel - { - Error, - Warn, - Info, - Debug, - } - - [ConfigItem("Log")] - public class LogConfig : IConfigItem - { - [JsonIgnore] public LogLevel Level = LogLevel.Debug; - [JsonProperty("Level")] private string _level; - - public bool ToConsole = true; - - public bool ToFile = false; - public string LogFilePath; - - public void AfterLoad() - { - if (!string.IsNullOrEmpty(_level)) LogLevel.TryParse(_level, out Level); - } - - public void BeforeSave() - { - _level = Level.ToString(); - } - } - - public static ILog G => _G; - public static Log _G { private get; set; } - - private LogConfig _config; - - private Logger _logger; - - public Log(LogConfig config) - { - _config = config; - } - - public bool Init() - { - if (_config == null) return false; - var config = new LoggerConfiguration(); - switch (_config.Level) - { - case LogLevel.Error: - config.MinimumLevel.Error(); - break; - case LogLevel.Warn: - config.MinimumLevel.Warning(); - break; - case LogLevel.Debug: - config.MinimumLevel.Debug(); - break; - case LogLevel.Info: - default: - config.MinimumLevel.Information(); - break; - } - - var outputTemplate = "[{Timestamp:HH:mm:ss}][{CallerPlace}][{Level:u3}] {Message:lj}{NewLine}{Exception}"; - - if (_config.ToConsole) - { - config.WriteTo.Console( - outputTemplate: outputTemplate, - theme: AnsiConsoleTheme.Sixteen - ); - } - - if (_config.ToFile) - { - if (string.IsNullOrEmpty(_config.LogFilePath)) - { - return false; - } - config.WriteTo.File( - outputTemplate: outputTemplate, - path: _config.LogFilePath - ); - } - - config.Enrich.FromLogContext() - .Enrich.WithThreadId(); - try - { - _logger = config.CreateLogger(); - } - catch (Exception) - { - return false; - } - return true; - } - - - // 静态快捷方法 - 使用更简短的名称 - public void Debug(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") - { - using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) - { - _logger.Write(LogEventLevel.Debug, message); - } - } - - public void Info(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") - { - using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) - { - _logger.Write(LogEventLevel.Information, message); - } - } - - public void Warn(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") - { - using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) - { - _logger.Write(LogEventLevel.Warning, message); - } - } - - public void Error(string message, [CallerFilePath] string callerFilePath = "", [CallerMemberName] string callerMemberName = "") - { - using (LogContext.PushProperty("CallerPlace", Path.GetFileNameWithoutExtension(callerFilePath) + "::" + callerMemberName)) - { - _logger.Write(LogEventLevel.Error, message); - } - } - - public void Error(Exception ex, string message) - => WriteLog(ex, message); - - private void WriteLog(Exception ex, string message) - { - _logger.Error(ex, message); - } -} \ No newline at end of file diff --git a/Src/Utils/ResourceLoader.cs b/Src/Utils/ResourceLoader.cs deleted file mode 100644 index 8009c04..0000000 --- a/Src/Utils/ResourceLoader.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Reflection; -using System.Text; - -namespace BangumiRenamer.Utils; - -public static class ResourceLoader -{ - public static IEnumerable GetAllResNames() - { - var assembly = Assembly.GetExecutingAssembly(); - return assembly.GetManifestResourceNames(); - } - - public static async Task ReadText(string resPath) - { - var stream = GetResStream(resPath); - if (stream.CanSeek) - { - stream.Position = 0; - } - - using var reader = new StreamReader(stream, Encoding.UTF8); - return await reader.ReadToEndAsync(); - } - - public static Stream GetResStream(string resPath) - { - var assembly = Assembly.GetExecutingAssembly(); - var resourceName = resPath; - if (assembly.GetManifestResourceInfo(resPath) == null) - { - resourceName = $"{assembly.GetName().Name}.{resourceName.Replace('\\', '.').Replace('/', '.')}"; - } - var stream = assembly.GetManifestResourceStream(resourceName); - if (stream == null) - { - throw new FileNotFoundException($"资源 {resourceName} 未找到"); - } - return stream; - } -} \ No newline at end of file