更新
This commit is contained in:
parent
47df98a25e
commit
cf128159d1
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
/android/
|
||||
.idea/
|
||||
data.json
|
||||
config.json
|
||||
@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using Learn.Models;
|
||||
using Learn.Parsers;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Learn.Component;
|
||||
@ -95,15 +98,22 @@ public partial class MainTreePanel : Tree
|
||||
|
||||
private void OnMultiSelected(TreeItem item, long column, bool selected)
|
||||
{
|
||||
if(selected) _selectingNodes.Add(_mapper[item]);
|
||||
else _selectingNodes.Remove(_mapper[item]);
|
||||
for (int i = 0; i < Columns; i++)
|
||||
{
|
||||
if (i == column ? selected : item.IsSelected(i))
|
||||
{
|
||||
_selectingNodes.Add(_mapper[item]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_selectingNodes.Remove(_mapper[item]);
|
||||
}
|
||||
|
||||
|
||||
private TreeItem CreateNode(TreeItem father, Item item)
|
||||
{
|
||||
var node = CreateItem(father);
|
||||
var name = Path.GetFileName(item.MainInfo["Path"]);
|
||||
var name = Path.GetFileName(item.MainInfo[ItemFields.MainKey_Path]);
|
||||
node.SetText(0, name);
|
||||
return node;
|
||||
}
|
||||
@ -118,8 +128,8 @@ public partial class MainTreePanel : Tree
|
||||
{
|
||||
MainInfo =
|
||||
{
|
||||
["IsDir"] = isDir ? "True" : "False",
|
||||
["Path"] = path
|
||||
[ItemFields.MainKey_IsDir] = isDir ? "True" : "False",
|
||||
[ItemFields.MainKey_Path] = path
|
||||
}
|
||||
};
|
||||
_items.Add(path, item);
|
||||
|
||||
@ -39,15 +39,16 @@ public partial class NodeInfoEditPanel : Tree
|
||||
|
||||
private void OnMultiSelected(TreeItem item, long column, bool selected)
|
||||
{
|
||||
if (selected)
|
||||
for (int i = 0; i < Columns; i++)
|
||||
{
|
||||
if (i == column ? selected : item.IsSelected(i))
|
||||
{
|
||||
_selectingNodes.Add(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectingNodes.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemEdited()
|
||||
{
|
||||
|
||||
9
Config/ProxyConfig.cs
Normal file
9
Config/ProxyConfig.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Learn.Utils;
|
||||
|
||||
namespace Learn.Config;
|
||||
|
||||
[ConfigItem("Proxy")]
|
||||
public class ProxyConfig : IConfigItem
|
||||
{
|
||||
public string HttpProxy = "";
|
||||
}
|
||||
1
Config/ProxyConfig.cs.uid
Normal file
1
Config/ProxyConfig.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://k75xslv0u3pm
|
||||
9
Config/TMDBConfig.cs
Normal file
9
Config/TMDBConfig.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Learn.Utils;
|
||||
|
||||
namespace Learn.Config;
|
||||
|
||||
[ConfigItem("TMDB")]
|
||||
public class TMDBConfig : IConfigItem
|
||||
{
|
||||
public string ApiKey = "";
|
||||
}
|
||||
1
Config/TMDBConfig.cs.uid
Normal file
1
Config/TMDBConfig.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://v07s3j12o0lw
|
||||
@ -6,5 +6,6 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="TMDbLib" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
54
Main.cs
54
Main.cs
@ -1,9 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Godot;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Learn.Component;
|
||||
using Learn.Parsers;
|
||||
using Learn.Utils;
|
||||
|
||||
public partial class Main : Node
|
||||
{
|
||||
@ -37,6 +41,8 @@ public partial class Main : Node
|
||||
|
||||
private bool _refreshPanels;
|
||||
|
||||
private Configs _configs;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_nodeInfoEditPanel.OnNodeInfoEdited += _mainTreePanel.UpdateColumns;
|
||||
@ -57,6 +63,7 @@ public partial class Main : Node
|
||||
_saveButton.Pressed += DoSave;
|
||||
_resetButton.Pressed += DoReset;
|
||||
_loadButton.Pressed += LoadData;
|
||||
_doParseButton.Text = "开始解析";
|
||||
|
||||
LoadData();
|
||||
|
||||
@ -64,6 +71,10 @@ public partial class Main : Node
|
||||
|
||||
FoldAll();
|
||||
_refreshPanels = true;
|
||||
|
||||
_configs = new Configs();
|
||||
_configs.ConfigPath = "config.json";
|
||||
_configs.Load(true);
|
||||
}
|
||||
|
||||
private void LoadData()
|
||||
@ -129,29 +140,54 @@ public partial class Main : Node
|
||||
_refreshPanels = true;
|
||||
}
|
||||
|
||||
private void DoParse()
|
||||
private async void DoParse()
|
||||
{
|
||||
var root = _mainTreePanel.GetRoot();
|
||||
if (root == null) return;
|
||||
|
||||
ItemParser parser = new NormalParser();
|
||||
var originName = _doParseButton.Text;
|
||||
_doParseButton.Disabled = true;
|
||||
|
||||
var queue = new Queue<TreeItem>();
|
||||
queue.Enqueue(root);
|
||||
while (queue.Count > 0)
|
||||
ItemParser parser = new TMDBParser(_configs);
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var stack = new Stack<TreeItem>();
|
||||
stack.Push(root);
|
||||
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var treeItem = queue.Dequeue();
|
||||
_doParseButton.Text = "解析中";
|
||||
if (stopwatch.ElapsedMilliseconds > 2000)
|
||||
{
|
||||
_mainTreePanel.UpdateColumns();
|
||||
stopwatch.Restart();
|
||||
}
|
||||
var treeItem = stack.Pop();
|
||||
foreach (var child in treeItem.GetChildren())
|
||||
{
|
||||
if(child == null) continue;
|
||||
if (_mainTreePanel.Query(child, out var node))
|
||||
{
|
||||
parser.DoParse(node);
|
||||
}
|
||||
queue.Enqueue(child);
|
||||
try
|
||||
{
|
||||
if (!await parser.DoParse(node))
|
||||
{
|
||||
GD.PrintErr($"解析{child.GetText(0)}失败");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"解析{child.GetText(0)}出现异常:" + ex);
|
||||
}
|
||||
}
|
||||
stack.Push(child);
|
||||
}
|
||||
}
|
||||
|
||||
_doParseButton.Text = originName;
|
||||
_doParseButton.Disabled = false;
|
||||
_mainTreePanel.UpdateColumns();
|
||||
GD.Print("Done");
|
||||
}
|
||||
|
||||
private const string DataPath = "data.json";
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Learn.Models;
|
||||
|
||||
namespace Learn.Parsers;
|
||||
|
||||
public static class ItemFieldExtension
|
||||
{
|
||||
#region 基础信息
|
||||
|
||||
public static string Name(this Item item)
|
||||
{
|
||||
var path = item.MainInfo["Path"];
|
||||
return Path.GetFileName(path);
|
||||
}
|
||||
|
||||
public static bool IsFolder(this Item item)
|
||||
{
|
||||
return item.MainInfo["IsDir"] == "True";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static void SetGroupIfNotExist(this Item item, string group)
|
||||
{
|
||||
item.Info.TryAdd("Group", group);
|
||||
}
|
||||
|
||||
public static void SetTitleIfNotExist(this Item item, string title)
|
||||
{
|
||||
item.Info.TryAdd("Title", title);
|
||||
}
|
||||
|
||||
public static void SetRawTitle(this Item item, string rawTitle)
|
||||
{
|
||||
item.Info.TryAdd("RawTitle", rawTitle);
|
||||
}
|
||||
|
||||
public static string RawTitle(this Item item)
|
||||
{
|
||||
return item.Info["RawTitle"];
|
||||
}
|
||||
|
||||
public static void SetSeasonIfNotExist(this Item item, string season)
|
||||
{
|
||||
item.Info.TryAdd("Season", season);
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
uid://fo70m114nwe7
|
||||
60
Parsers/ItemFields.cs
Normal file
60
Parsers/ItemFields.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Learn.Models;
|
||||
|
||||
namespace Learn.Parsers;
|
||||
|
||||
public static class ItemFields
|
||||
{
|
||||
#region 基础信息
|
||||
|
||||
public static string MainKey_Path => "Path";
|
||||
|
||||
public static string MainKey_IsDir => "IsDir";
|
||||
|
||||
public static string Name(this Item item)
|
||||
{
|
||||
var path = item.MainInfo[MainKey_Path];
|
||||
return Path.GetFileName(path);
|
||||
}
|
||||
|
||||
public static bool IsFolder(this Item item)
|
||||
{
|
||||
return item.MainInfo[MainKey_IsDir] == "True";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static string Key_Group => "Group";
|
||||
public static string Key_Title => "Title";
|
||||
public static string Key_RawTitle => "RawTitle";
|
||||
public static string Key_Season => "Season";
|
||||
public static string Key_Year => "Year";
|
||||
|
||||
|
||||
public static void SetGroupIfNotExist(this Item item, string group)
|
||||
{
|
||||
item.Info.TryAdd(Key_Group, group);
|
||||
}
|
||||
|
||||
public static void SetTitleIfNotExist(this Item item, string title)
|
||||
{
|
||||
item.Info.TryAdd(Key_Title, title);
|
||||
}
|
||||
|
||||
public static void SetRawTitleIfNotExist(this Item item, string rawTitle)
|
||||
{
|
||||
item.Info.TryAdd(Key_RawTitle, rawTitle);
|
||||
}
|
||||
|
||||
public static void SetSeasonIfNotExist(this Item item, string season)
|
||||
{
|
||||
item.Info.TryAdd(Key_Season, season);
|
||||
}
|
||||
|
||||
public static void SetYear(this Item item, int year)
|
||||
{
|
||||
item.Info[Key_Year] = year.ToString();
|
||||
}
|
||||
}
|
||||
1
Parsers/ItemFields.cs.uid
Normal file
1
Parsers/ItemFields.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://cavjlh7k1lb6m
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Learn.Models;
|
||||
|
||||
namespace Learn.Parsers;
|
||||
@ -15,5 +16,5 @@ namespace Learn.Parsers;
|
||||
/// </summary>
|
||||
public interface ItemParser
|
||||
{
|
||||
public bool DoParse(TreeNode node);
|
||||
public Task<bool> DoParse(TreeNode node);
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Learn.Models;
|
||||
|
||||
namespace Learn.Parsers;
|
||||
|
||||
public class NormalParser : ItemParser
|
||||
{
|
||||
private string ParseSeason(string season)
|
||||
{
|
||||
if (int.TryParse(season, out _)) return season;
|
||||
|
||||
switch (season)
|
||||
{
|
||||
case "零": return "0";
|
||||
case "一": return "1";
|
||||
case "二": return "2";
|
||||
case "三": return "3";
|
||||
case "四": return "4";
|
||||
case "五": return "5";
|
||||
case "六": return "6";
|
||||
case "七": return "7";
|
||||
case "八": return "8";
|
||||
case "九": return "9";
|
||||
}
|
||||
return season;
|
||||
}
|
||||
|
||||
public bool DoParse(TreeNode node)
|
||||
{
|
||||
var item = node.Info;
|
||||
var name = item.Name();
|
||||
var matches = Regex.Matches(name, @"[^\[\]_]+").Select(match => match.Value).ToArray();
|
||||
|
||||
if (matches.Length == 1)
|
||||
{
|
||||
node.Info.SetRawTitle(matches[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matches.Length >= 2)
|
||||
{
|
||||
node.Info.SetGroupIfNotExist(matches[0]);
|
||||
|
||||
var title = matches[1].Trim();
|
||||
var match = Regex.Match(title, "(.+)第(.+)季");
|
||||
if (match.Success)
|
||||
{
|
||||
node.Info.SetSeasonIfNotExist(ParseSeason(match.Groups[2].Value.Trim()));
|
||||
node.Info.SetRawTitle(match.Groups[1].Value.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Info.SetRawTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
uid://bfixayy5gpwd6
|
||||
141
Parsers/TMDBParser.cs
Normal file
141
Parsers/TMDBParser.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Godot;
|
||||
using Learn.Config;
|
||||
using Learn.Models;
|
||||
using Learn.Utils;
|
||||
using TMDbLib.Client;
|
||||
using TMDbLib.Objects.Search;
|
||||
|
||||
namespace Learn.Parsers;
|
||||
|
||||
public class TMDBParser(Configs configs) : ItemParser
|
||||
{
|
||||
private readonly Dictionary<string, SearchTv> _cache = new();
|
||||
|
||||
private TMDbClient _client;
|
||||
|
||||
private async Task<SearchTv> QueryTMDB(string title)
|
||||
{
|
||||
if (string.IsNullOrEmpty(title)) return null;
|
||||
|
||||
if (_cache.TryGetValue(title, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var results = (await GetTMDbClient().SearchTvShowAsync(title, language: "zh-CN")).Results;
|
||||
result = results.FirstOrDefault();
|
||||
_cache[title] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private TMDbClient GetTMDbClient()
|
||||
{
|
||||
if (_client != null) return _client;
|
||||
|
||||
var apiKey = configs.Get<TMDBConfig>().ApiKey;
|
||||
var proxy = configs.Get<ProxyConfig>().HttpProxy;
|
||||
|
||||
if (string.IsNullOrEmpty(proxy))
|
||||
{
|
||||
_client = new TMDbClient(apiKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
_client = new TMDbClient(apiKey , proxy: new WebProxy(proxy));
|
||||
}
|
||||
|
||||
return _client;
|
||||
}
|
||||
|
||||
private string ParseSeason(string season)
|
||||
{
|
||||
if (int.TryParse(season, out _)) return season;
|
||||
|
||||
switch (season)
|
||||
{
|
||||
case "零": return "0";
|
||||
case "一": return "1";
|
||||
case "二": return "2";
|
||||
case "三": return "3";
|
||||
case "四": return "4";
|
||||
case "五": return "5";
|
||||
case "六": return "6";
|
||||
case "七": return "7";
|
||||
case "八": return "8";
|
||||
case "九": return "9";
|
||||
}
|
||||
return season;
|
||||
}
|
||||
|
||||
private bool DoRawParse(TreeNode node)
|
||||
{
|
||||
var item = node.Info;
|
||||
var name = item.Name();
|
||||
var matches = Regex.Matches(name, @"[^\[\]_]+").Select(match => match.Value).ToArray();
|
||||
|
||||
if (matches.Length == 0) return false;
|
||||
|
||||
if (matches.Length == 1)
|
||||
{
|
||||
node.Info.SetRawTitleIfNotExist(matches[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matches.Length >= 2)
|
||||
{
|
||||
node.Info.SetGroupIfNotExist(matches[0]);
|
||||
|
||||
var title = matches[1].Trim();
|
||||
var match = Regex.Match(title, "(.+)第(.+)季");
|
||||
if (match.Success)
|
||||
{
|
||||
node.Info.SetSeasonIfNotExist(ParseSeason(match.Groups[2].Value.Trim()));
|
||||
node.Info.SetRawTitleIfNotExist(match.Groups[1].Value.Trim());
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Info.SetRawTitleIfNotExist(title);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> DoParse(TreeNode node)
|
||||
{
|
||||
if (!node.TryGetValue(ItemFields.Key_RawTitle, out var rawTitle, out _))
|
||||
{
|
||||
if (!DoRawParse(node))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
node.TryGetValue(ItemFields.Key_RawTitle, out rawTitle, out _);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(rawTitle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = await QueryTMDB(rawTitle);
|
||||
if (result == null)
|
||||
{
|
||||
GD.PrintErr($"找不到对应的TV:{rawTitle}");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result.FirstAirDate != null)
|
||||
{
|
||||
node.Info.SetYear(result.FirstAirDate.Value.Year);
|
||||
}
|
||||
|
||||
node.Info.SetTitleIfNotExist(result.Name);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
1
Parsers/TMDBParser.cs.uid
Normal file
1
Parsers/TMDBParser.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://bw1sbx8ay4qsw
|
||||
184
Utils/Configs.cs
Normal file
184
Utils/Configs.cs
Normal file
@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Learn.Utils;
|
||||
|
||||
public class ConfigItemAttribute(string name) : Attribute
|
||||
{
|
||||
public readonly string Name = name;
|
||||
}
|
||||
|
||||
public interface IConfigItem
|
||||
{
|
||||
public void OnBeforeSave()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnAfterLoad()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Configs
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, string> Cache = new();
|
||||
private readonly ConcurrentDictionary<string, IConfigItem> _configObjects = new();
|
||||
private readonly ConcurrentDictionary<string, JObject> _configs = new();
|
||||
|
||||
public string ConfigPath { get; set; } = string.Empty;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取配置项对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T">配置项类</typeparam>
|
||||
/// <remarks>获取的配置项对象是单例的</remarks>
|
||||
/// <returns>配置项对象</returns>
|
||||
public T Get<T>() 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<T>();
|
||||
result.OnAfterLoad();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new T();
|
||||
}
|
||||
_configObjects[name] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置某个配置项。重置完后再取就是一个新的配置项
|
||||
/// </summary>
|
||||
/// <typeparam name="T">配置项类</typeparam>
|
||||
public void Reset<T>() where T : class, IConfigItem, new()
|
||||
{
|
||||
var name = GetConfigItemName(typeof(T));
|
||||
_configs.TryRemove(name, out _);
|
||||
_configObjects.Remove(name, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空当前配置并重新从文件中加载配置
|
||||
/// </summary>
|
||||
/// <param name="createDefaultIfNotExist">当不存在配置文件路径创建默认配置</param>
|
||||
/// <returns>加载是否成功。无论是否加载成功,当前配置都会被清空</returns>
|
||||
public bool Load(bool createDefaultIfNotExist)
|
||||
{
|
||||
_configs.Clear();
|
||||
_configObjects.Clear();
|
||||
if (string.IsNullOrEmpty(ConfigPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!File.Exists(ConfigPath))
|
||||
{
|
||||
if (!createDefaultIfNotExist) return false;
|
||||
if (!CreateEmptyConfig(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<JObject>();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将当前配置保存到文件中
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Save()
|
||||
{
|
||||
if (string.IsNullOrEmpty(ConfigPath)) return false;
|
||||
try
|
||||
{
|
||||
foreach (var config in _configObjects)
|
||||
{
|
||||
config.Value.OnBeforeSave();
|
||||
_configs[config.Key] = JObject.FromObject(config.Value);
|
||||
}
|
||||
|
||||
File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(_configs, Formatting.Indented));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool CreateEmptyConfig(string filePath)
|
||||
{
|
||||
var configItemTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return assembly.GetTypes();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return Array.Empty<Type>();
|
||||
}
|
||||
})
|
||||
.Where(type => type.IsClass &&
|
||||
!type.IsAbstract &&
|
||||
typeof(IConfigItem).IsAssignableFrom(type))
|
||||
.ToList();
|
||||
|
||||
var configs = new Dictionary<string, IConfigItem>();
|
||||
foreach (var type in configItemTypes)
|
||||
{
|
||||
var name = GetConfigItemName(type);
|
||||
var item = (IConfigItem) Activator.CreateInstance(type);
|
||||
item.OnBeforeSave();
|
||||
configs[name] = item;
|
||||
|
||||
}
|
||||
try
|
||||
{
|
||||
File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
1
Utils/Configs.cs.uid
Normal file
1
Utils/Configs.cs.uid
Normal file
@ -0,0 +1 @@
|
||||
uid://b8ta3kj0ksopd
|
||||
Loading…
x
Reference in New Issue
Block a user