This commit is contained in:
limil 2026-01-02 23:35:05 +08:00
parent 3d58c7d497
commit 3525df1e95
20 changed files with 425 additions and 172 deletions

View File

@ -38,7 +38,7 @@ public partial class MainTreePanel : Tree
SetColumnTitlesVisible(true);
SetColumnTitle(0, "文件名");
SetColumnCustomMinimumWidth(0, 500);
SetColumnCustomMinimumWidth(0, 800);
SetColumnExpand(0, true);
MultiSelected += OnMultiSelected;

View File

@ -5,5 +5,5 @@ namespace Learn.Config;
[ConfigItem("APP")]
public class AppConfig : IConfigItem
{
public string ScanPath = "";
public string ScanPath { get; set; } = "";
}

1
Config/AppConfig.cs.uid Normal file
View File

@ -0,0 +1 @@
uid://bakkudpxylhe8

View File

@ -1,9 +0,0 @@
using Learn.Utils;
namespace Learn.Config;
[ConfigItem("Proxy")]
public class ProxyConfig : IConfigItem
{
public string HttpProxy = "";
}

View File

@ -1 +0,0 @@
uid://k75xslv0u3pm

58
Config/RawParserConfig.cs Normal file
View File

@ -0,0 +1,58 @@
using System.Collections.Generic;
using Learn.Utils;
namespace Learn.Config;
public class MatchGroupsRules
{
public List<string> Full { get; set; }
public List<string> Partial { get; set; }
}
public class MatchTypeExtra
{
public List<string> IfDirNameIs { get; set; }
public List<string> IfFileExtensionIs { get; set; }
}
public class MatchTypeSubtitle
{
public List<string> IfFileExtensionIs { get; set; }
}
public class MatchTypeEpisode
{
public List<string> IfFileExtensionIs { get; set; }
}
public class MatchTypeRules
{
public MatchTypeExtra Extra { get; set; }
public MatchTypeSubtitle Subtitle { get; set; }
public MatchTypeEpisode Episode { get; set; }
}
public class MatchSeasonRules
{
public List<string> Regexes { get; set; }
}
public class FilterTokenRules
{
public List<string> Regexes { get; set; }
}
[ConfigItem("RawParser")]
public class RawParserConfig : IConfigItem
{
public string SplitRegex { get; set; } = "";
public MatchTypeRules TypeMatchRules { get; set; }
public MatchGroupsRules GroupsMatchRules { get; set; }
public MatchSeasonRules SeasonMatchRules { get; set; }
public FilterTokenRules TokenFilterRules { get; set; }
}

View File

@ -0,0 +1 @@
uid://ccldbt2fp1mxn

View File

@ -1,9 +0,0 @@
using Learn.Utils;
namespace Learn.Config;
[ConfigItem("TMDB")]
public class TMDBConfig : IConfigItem
{
public string ApiKey = "";
}

View File

@ -1 +0,0 @@
uid://v07s3j12o0lw

View File

@ -0,0 +1,10 @@
using Learn.Utils;
namespace Learn.Config;
[ConfigItem("TMDBParser")]
public class TMDBParserConfig : IConfigItem
{
public string HttpProxy { get; set; } = "";
public string ApiKey { get; set; } = "";
}

View File

@ -0,0 +1 @@
uid://dp5xqvvuiclbg

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APath_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F94e5a9ba04d74002870fbeeec71ff78cca738_003F85_003Fce11ac0c_003FPath_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARawInfoPanel_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003Flianzefeng_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F9fdf5fe7bab299c9c5ee4ca6784782ae9851b9b_003FRawInfoPanel_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003AC_0021_003FUsers_003Flianzefeng_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa03380083db34a2faee436e29e06a72ae8e910_003Fa8_003Fec982e59_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATreeItem_002Ecs_002Fl_003AC_0021_003FUsers_003Flianzefeng_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F1c378f459c054fecaf4484a0fa6d44c055a800_003F1d_003Fbc7bd422_003FTreeItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>

View File

@ -21,6 +21,7 @@ public partial class Main : Node
[Export] private Button _saveButton;
[Export] private Button _resetButton;
[Export] private Button _loadButton;
[Export] private Button _reloadConfigButton;
[ExportGroup("编辑面板")]
[Export] private NodeInfoEditPanel _nodeInfoEditPanel;
@ -70,6 +71,7 @@ public partial class Main : Node
_saveButton.Pressed += DoSave;
_resetButton.Pressed += DoReset;
_loadButton.Pressed += LoadData;
_reloadConfigButton.Pressed += ReloadConfig;
_doParseButton.Text = "开始解析";
_configs = new Configs();
@ -82,6 +84,11 @@ public partial class Main : Node
_refreshPanels = true;
}
private void ReloadConfig()
{
_configs.Load(true);
}
private void LoadData()
{
if (File.Exists(DataPath))
@ -146,7 +153,7 @@ public partial class Main : Node
var originName = _doParseButton.Text;
_doParseButton.Disabled = true;
ItemParser parser = new RawParser();
ItemParser parser = new RawParser(_configs);
if (_mainTreePanel.Query(root, out var node))
{

View File

@ -17,7 +17,7 @@ grow_vertical = 2
[node name="FileDirDialog" type="FileDialog" parent="."]
script = ExtResource("1_d2g23")
[node name="Main" type="Node" parent="." node_paths=PackedStringArray("_dirSelector", "_openDirButton", "_doParseButton", "_saveButton", "_resetButton", "_loadButton", "_nodeInfoEditPanel", "_addKeyButton", "_removeKeyButton", "_inspectorPanel", "_mainTreePanel", "_columnIndexText", "_columnWidthText", "_columnText", "_addColumnButton", "_removeColumnButton", "_clearColumnButton", "_expandAllButton", "_foldAllButton")]
[node name="Main" type="Node" parent="." node_paths=PackedStringArray("_dirSelector", "_openDirButton", "_doParseButton", "_saveButton", "_resetButton", "_loadButton", "_reloadConfigButton", "_nodeInfoEditPanel", "_addKeyButton", "_removeKeyButton", "_inspectorPanel", "_mainTreePanel", "_columnIndexText", "_columnWidthText", "_columnText", "_addColumnButton", "_removeColumnButton", "_clearColumnButton", "_expandAllButton", "_foldAllButton")]
script = ExtResource("2_0727o")
_dirSelector = NodePath("../FileDirDialog")
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/文件夹操作/ScanDir")
@ -25,6 +25,7 @@ _doParseButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VB
_saveButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/保存操作/Save")
_resetButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/保存操作/Reset")
_loadButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/保存操作/Load")
_reloadConfigButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/保存操作/ReloadConfig")
_nodeInfoEditPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel")
_addKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/AddKey")
_removeKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/RemoveKey")
@ -85,9 +86,10 @@ layout_mode = 2
[node name="TabContainer" type="TabContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2"]
custom_minimum_size = Vector2(0, 200)
layout_mode = 2
current_tab = 0
current_tab = 1
[node name="文件夹操作" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 0
@ -102,7 +104,6 @@ size_flags_vertical = 4
text = "开始解析"
[node name="保存操作" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 1
@ -118,6 +119,10 @@ text = "加载树表"
layout_mode = 2
text = "重置树表"
[node name="ReloadConfig" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/保存操作"]
layout_mode = 2
text = "重载配置"
[node name="树表操作" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer"]
visible = false
layout_mode = 2

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Learn.Models;
@ -28,47 +29,45 @@ public class TreeNode(Item item)
public bool TryGetValue(string key, out string value, out bool isInherited)
{
value = null;
isInherited = false;
var curr = this;
bool valueExists = false;
while (curr.Info != null)
{
if (curr.Info.Info.TryGetValue(key, out value))
if (curr.Info.Info.TryGetValue(key, out var currValue))
{
isInherited = curr != this;
return true;
value = currValue;
valueExists = true;
isInherited = (curr != this);
}
curr = curr.Parent;
}
value = null;
isInherited = false;
return false;
return valueExists;
}
public IEnumerable<KeyValueInfo> GetKeyValueInfos()
{
var result = new List<KeyValueInfo>();
var keys = new HashSet<string>();
var dict = new Dictionary<string, KeyValueInfo>();
var curr = this;
while (curr.Info != null)
{
foreach (var kv in curr.Info.Info)
{
if(!keys.Add(kv.Key)) continue;
var keyValueInfo = new KeyValueInfo();
if (curr != this)
var keyValueInfo = new KeyValueInfo
{
keyValueInfo.IsInherited = true;
}
keyValueInfo.Key = kv.Key;
keyValueInfo.Value = kv.Value;
result.Add(keyValueInfo);
IsInherited = curr != this,
Key = kv.Key,
Value = kv.Value
};
dict[kv.Key] = keyValueInfo;
}
curr = curr.Parent;
}
return result;
return dict.Values.ToList();
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using Learn.Models;
@ -6,6 +7,14 @@ namespace Learn.Parsers;
public static class ItemFields
{
public enum ItemType
{
Unknown,
Extra,
Subtitle,
Episode
}
#region
public static string MainKey_Path => "Path";
@ -25,36 +34,27 @@ public static class ItemFields
#endregion
#region
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 string Key_Type => "Type";
public static string Key_SubtitleLanguage => "SubLang";
public static ItemType Type(this Item item)
{
if (item.Info.TryGetValue(Key_Type, out var typeName))
{
if(Enum.TryParse(typeName, out ItemType type))
{
return type;
}
}
return ItemType.Unknown;
}
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();
}
#endregion
}

View File

@ -12,7 +12,6 @@ namespace Learn.Parsers;
/// "集数"
/// "类型""额外内容", "字幕", "剧集"
/// "字幕语言"
/// "年份"
/// </summary>
public interface ItemParser
{

View File

@ -1,135 +1,321 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Learn.Config;
using Learn.Models;
using Learn.Utils;
namespace Learn.Parsers;
public class RawParser : ItemParser
public class RawParser(Configs configs) : ItemParser
{
private string ParseSeasonFromCN(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 (string, string) SplitTitleAndSeason(string rawTitle)
{
var match1 = Regex.Match(rawTitle, @"第(.+)季");
if (match1.Success)
{
var seasonStr = match1.Groups[0].Value.Trim();
var season = ParseSeasonFromCN(match1.Groups[1].Value.Trim());
var title = rawTitle.Replace(seasonStr, "").Trim();
return (title, season);
}
var match2 = Regex.Match(rawTitle, @"[Ss]eason *(\d+)");
if (match2.Success)
{
var seasonStr = match1.Groups[0].Value.Trim();
var season = int.Parse(match1.Groups[1].Value.Trim()).ToString();
var title = rawTitle.Replace(seasonStr, "").Trim();
return (title, season);
}
private RawParserConfig config => configs.Get<RawParserConfig>();
return (rawTitle, null);
private List<string> FilterParts(List<string> parts)
{
var result = parts.ToList();
foreach (var regex in config.TokenFilterRules.Regexes)
{
result.RemoveAll(part => Regex.Match(part.Trim(), regex).Success);
}
return result;
}
private void SimplifyMatches(List<string> matches)
private List<string> GetParts(Item item)
{
matches.RemoveAll(match => string.IsNullOrEmpty(match.Trim()));
matches.RemoveAll(match => Regex.Match(match.Trim(), @"\d+[Pp]$").Success);
var matches = Regex.Matches(item.Name(), config.SplitRegex).Select(match => match.Value)
.Select(match => match.Trim())
.Where(match => !string.IsNullOrEmpty(match))
.ToList();
return FilterParts(matches);
}
private List<string> GetParts(string name)
{
var matches = Regex.Matches(name, @"[^\[\]_【】]+").Select(match => match.Value).ToList();
SimplifyMatches(matches);
return matches;
}
private bool TryParseRawTitle(Item item, out string rawTitle)
{
rawTitle = null;
var name = item.Name();
var matches = GetParts(name);
if (matches.Count == 0) return false;
if (matches.Count == 1)
{
rawTitle = matches[0];
}
else
{
rawTitle = matches[1];
}
(rawTitle, _) = SplitTitleAndSeason(rawTitle);
return true;
}
private bool TryParseSeason(Item item, out string season)
private bool TryNormalizeSeason(string seasonPart, out string season)
{
season = null;
var name = item.Name();
var matches = GetParts(name);
if (matches.Count == 0) return false;
if (matches.Count == 1)
if (int.TryParse(seasonPart, out var seasonInt))
{
(_, season) = SplitTitleAndSeason(matches[0]);
if (!string.IsNullOrEmpty(season)) return true;
season = seasonInt.ToString();
return true;
}
else
switch (seasonPart)
{
(_, season) = SplitTitleAndSeason(matches[1]);
if (!string.IsNullOrEmpty(season)) return true;
case "零":
season = "0";
return true;
case "一":
season = "1";
return true;
case "二":
season = "2";
return true;
case "三":
season = "3";
return true;
case "四":
season = "4";
return true;
case "五":
season = "5";
return true;
case "六":
season = "6";
return true;
case "七":
season = "7";
return true;
case "八":
season = "8";
return true;
case "九":
season = "9";
return true;
}
return false;
}
private bool TryMatchSeason(string token, out string seasonPart, out string matchPart)
{
seasonPart = null;
matchPart = null;
var regexes = config.SeasonMatchRules?.Regexes;
if (regexes == null) return false;
token = token.Trim();
foreach (var regex in regexes)
{
var match = Regex.Match(token, regex);
if (!match.Success) continue;
matchPart = match.Value;
return TryNormalizeSeason(match.Groups[1].Value, out seasonPart);
}
return false;
}
private bool TryParseSeason(TreeNode node, out string season, out MatchInfo matchInfo)
{
season = null;
matchInfo = null;
var parts = GetParts(node.Info);
for (int i = 0; i < parts.Count; i++)
{
var part = parts[i];
var tokens = part.Split("-");
foreach (var token in tokens)
{
if (!TryMatchSeason(token, out season, out var content)) continue;
matchInfo = new MatchInfo
{
content = content,
partIndex = i
};
return true;
}
}
return false;
}
private bool TryParseGroup(Item item, out string group)
private bool IsFullMatch(string item, List<string> sequence)
{
if(sequence == null) return false;
for (int i = 0; i < sequence.Count; i++)
{
if (item.Equals(sequence[i], StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
private bool IsPartialMatch(string item, List<string> sequence)
{
if(sequence == null) return false;
for (int i = 0; i < sequence.Count; i++)
{
if (item.Contains(sequence[i], StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
private bool TryParseGroup(TreeNode node, out string group, out MatchInfo matchInfo)
{
group = null;
var name = item.Name();
var matches = GetParts(name);
matchInfo = null;
var parts = GetParts(node.Info);
for (int i = 0; i < parts.Count; i++)
{
if (IsFullMatch(parts[i], config.GroupsMatchRules?.Full))
{
group = parts[i];
matchInfo = new MatchInfo
{
content = parts[i],
partIndex = i
};
return true;
}
}
for (int i = 0; i < parts.Count; i++)
{
if (IsPartialMatch(parts[i], config.GroupsMatchRules?.Partial))
{
group = parts[i];
matchInfo = new MatchInfo
{
content = parts[i],
partIndex = i
};
return true;
}
}
return false;
}
if (matches.Count <= 1) return false;
group = matches[0];
private ItemFields.ItemType ParseItemType(TreeNode node)
{
// 1. 判断是否属于Extras
foreach (var extraMatchName in config.TypeMatchRules.Extra.IfDirNameIs)
{
if (node.Info.Name().Equals(extraMatchName, StringComparison.OrdinalIgnoreCase))
{
return ItemFields.ItemType.Extra;
}
}
if (node.Info.IsFolder())
{
return ItemFields.ItemType.Unknown;
}
var infoExt = Path.GetExtension(node.Info.Name());
if (string.IsNullOrEmpty(infoExt)) return ItemFields.ItemType.Extra;
foreach (var ext in config.TypeMatchRules.Extra.IfFileExtensionIs)
{
if (infoExt.Equals(ext, StringComparison.OrdinalIgnoreCase))
{
return ItemFields.ItemType.Extra;
}
}
// 2. 判断是不是字幕
foreach (var ext in config.TypeMatchRules.Subtitle.IfFileExtensionIs)
{
if (infoExt.Equals(ext, StringComparison.OrdinalIgnoreCase))
{
return ItemFields.ItemType.Subtitle;
}
}
// 3. 判断是不是剧集
foreach (var ext in config.TypeMatchRules.Episode.IfFileExtensionIs)
{
if (infoExt.Equals(ext, StringComparison.OrdinalIgnoreCase))
{
return ItemFields.ItemType.Episode;
}
}
// 4. 啥都不是,不知道
return ItemFields.ItemType.Unknown;
}
private bool TryParseType(TreeNode node, out string type, out MatchInfo matchInfo)
{
matchInfo = null;
type = null;
var typeEnum = ParseItemType(node);
if (typeEnum == ItemFields.ItemType.Unknown) return false;
type = typeEnum.ToString();
return true;
}
private bool TryParseSubtitleLanguage(TreeNode node, out string language, out MatchInfo matchInfo)
{
language = null;
matchInfo = null;
if (node.Info.Type() != ItemFields.ItemType.Subtitle)
{
return false;
}
var name = node.Info.Name();
var parts = name.Split(".");
if (parts.Length < 3) return false;
language = parts[^2];
return true;
}
private bool TryParseEpisode(TreeNode node, out string episode, out MatchInfo matchInfo)
{
episode = null;
matchInfo = null;
if (node.Info.Type() != ItemFields.ItemType.Episode)
{
return false;
}
var parts = GetParts(node.Info);
for (int i = 0; i < parts.Count; i++)
{
var part = parts[i];
var tokens = part.Split("-");
foreach (var token in tokens)
{
var match = Regex.Match(token.Trim(), @"^\d{1,2}$");
if (match.Success)
{
matchInfo = new MatchInfo
{
content = content,
partIndex = i
};
}
return true;
}
}
return false;
}
private delegate bool FieldParser(Item item, out string result);
//
// private bool TryParseRawTitle(TreeNode node, out string rawTitle, out MatchInfo matchInfo)
// {
//
// }
class MatchInfo
{
public string content;
public int partIndex;
}
private delegate bool FieldParser(TreeNode node, out string result, out MatchInfo matchInfo);
private bool TryParseField(TreeNode node, FieldParser fieldParser, out string result)
{
result = null;
if (node.Info == null) return false;
if (!fieldParser(node.Info, out var fieldValue)) return false;
if (!fieldParser(node, out var fieldValue, out _)) return false;
var parsed = new List<string>();
foreach (var child in node.Children)
{
if (fieldParser(child.Info, out var childFieldValue))
if (fieldParser(child, out var childFieldValue, out _))
{
parsed.Add(childFieldValue);
}
@ -162,6 +348,7 @@ public class RawParser : ItemParser
while (queue.Count > 0)
{
var current = queue.Dequeue();
if(current.Info.Info.ContainsKey(fieldName)) continue;
if (TryParseField(current, fieldParser, out var fieldValue))
{
current.Info.Info.TryAdd(fieldName, fieldValue);
@ -178,8 +365,10 @@ public class RawParser : ItemParser
public async Task Parse(TreeNode node)
{
DoParse(node, TryParseRawTitle, ItemFields.Key_RawTitle);
DoParse(node, TryParseSeason, ItemFields.Key_Season);
DoParse(node, TryParseGroup, ItemFields.Key_Group);
DoParse(node, TryParseType, ItemFields.Key_Type);
DoParse(node, TryParseSubtitleLanguage, ItemFields.Key_SubtitleLanguage);
}
}

View File

@ -14,6 +14,8 @@ namespace Learn.Parsers;
public class TMDBParser(Configs configs) : ItemParser
{
private TMDBParserConfig config => configs.Get<TMDBParserConfig>();
private readonly Dictionary<string, SearchTv> _cache = new();
private TMDbClient _client;
@ -37,8 +39,8 @@ public class TMDBParser(Configs configs) : ItemParser
{
if (_client != null) return _client;
var apiKey = configs.Get<TMDBConfig>().ApiKey;
var proxy = configs.Get<ProxyConfig>().HttpProxy;
var apiKey = config.ApiKey;
var proxy = config.HttpProxy;
if (string.IsNullOrEmpty(proxy))
{
@ -48,7 +50,7 @@ public class TMDBParser(Configs configs) : ItemParser
{
_client = new TMDbClient(apiKey , proxy: new WebProxy(proxy));
}
return _client;
}

View File

@ -17,8 +17,8 @@ config/icon="res://icon.svg"
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/size/viewport_width=1600
window/size/viewport_height=900
[dotnet]