实现RawParser
This commit is contained in:
parent
cf128159d1
commit
9cf948ec9c
@ -13,14 +13,19 @@ namespace Learn.Component;
|
|||||||
|
|
||||||
public partial class MainTreePanel : Tree
|
public partial class MainTreePanel : Tree
|
||||||
{
|
{
|
||||||
|
public class ColumnView
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Width { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class MainTreeData
|
public class MainTreeData
|
||||||
{
|
{
|
||||||
public List<string> Columns { get; set; }
|
public List<ColumnView> Columns { get; set; }
|
||||||
public Dictionary<string, Item> Items { get; set; }
|
public Dictionary<string, Item> Items { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly List<ColumnView> _columns = new();
|
||||||
private readonly List<string> _columns = new();
|
|
||||||
private readonly HashSet<TreeNode> _selectingNodes = new();
|
private readonly HashSet<TreeNode> _selectingNodes = new();
|
||||||
private readonly Dictionary<TreeItem, TreeNode> _mapper = new();
|
private readonly Dictionary<TreeItem, TreeNode> _mapper = new();
|
||||||
private readonly Dictionary<string, Item> _items = new();
|
private readonly Dictionary<string, Item> _items = new();
|
||||||
@ -41,22 +46,28 @@ public partial class MainTreePanel : Tree
|
|||||||
UpdateColumns();
|
UpdateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddColumn(string columnName, int index)
|
public void AddColumn(string columnName, int index, int width)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(columnName)) return;
|
if (string.IsNullOrEmpty(columnName)) return;
|
||||||
if (_columns.Contains(columnName)) return;
|
var targets = _columns.Where(column => column.Name == columnName).ToList();
|
||||||
if (index < 0)
|
|
||||||
|
if (index < 0) index = _columns.Count;
|
||||||
|
if (width < 0) width = 400;
|
||||||
|
if (targets.Any())
|
||||||
{
|
{
|
||||||
_columns.Add(columnName);
|
targets.First().Width = width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_columns.Insert(index, new ColumnView { Name = columnName, Width = width });
|
||||||
}
|
}
|
||||||
_columns.Insert(index, columnName);
|
|
||||||
UpdateColumns();
|
UpdateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveColumn(string columnName)
|
public void RemoveColumn(string columnName)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(columnName)) return;
|
if (string.IsNullOrEmpty(columnName)) return;
|
||||||
_columns.Remove(columnName);
|
_columns.RemoveAll(column => column.Name == columnName);
|
||||||
UpdateColumns();
|
UpdateColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +83,8 @@ public partial class MainTreePanel : Tree
|
|||||||
int index = 1;
|
int index = 1;
|
||||||
foreach (var column in _columns)
|
foreach (var column in _columns)
|
||||||
{
|
{
|
||||||
SetColumnTitle(index, column);
|
SetColumnTitle(index, column.Name);
|
||||||
SetColumnCustomMinimumWidth(index, 400);
|
SetColumnCustomMinimumWidth(index, column.Width);
|
||||||
SetColumnExpand(index, true);
|
SetColumnExpand(index, true);
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
@ -83,14 +94,12 @@ public partial class MainTreePanel : Tree
|
|||||||
index = 1;
|
index = 1;
|
||||||
foreach (var column in _columns)
|
foreach (var column in _columns)
|
||||||
{
|
{
|
||||||
if (kv.Value.TryGetValue(column, out var value, out _))
|
if (!kv.Value.TryGetValue(column.Name, out var value, out _))
|
||||||
{
|
{
|
||||||
kv.Key.SetText(index, value);
|
value = "";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kv.Key.SetText(index, "");
|
|
||||||
}
|
}
|
||||||
|
kv.Key.SetText(index, value);
|
||||||
|
kv.Key.SetTextAlignment(index, HorizontalAlignment.Center);
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
Config/AppConfig.cs
Normal file
9
Config/AppConfig.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Learn.Utils;
|
||||||
|
|
||||||
|
namespace Learn.Config;
|
||||||
|
|
||||||
|
[ConfigItem("APP")]
|
||||||
|
public class AppConfig : IConfigItem
|
||||||
|
{
|
||||||
|
public string ScanPath = "";
|
||||||
|
}
|
||||||
71
Main.cs
71
Main.cs
@ -6,6 +6,7 @@ using Godot;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Learn.Component;
|
using Learn.Component;
|
||||||
|
using Learn.Config;
|
||||||
using Learn.Parsers;
|
using Learn.Parsers;
|
||||||
using Learn.Utils;
|
using Learn.Utils;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ public partial class Main : Node
|
|||||||
[ExportGroup("主展示面板")]
|
[ExportGroup("主展示面板")]
|
||||||
[Export] private MainTreePanel _mainTreePanel;
|
[Export] private MainTreePanel _mainTreePanel;
|
||||||
[Export] private LineEdit _columnIndexText;
|
[Export] private LineEdit _columnIndexText;
|
||||||
|
[Export] private LineEdit _columnWidthText;
|
||||||
[Export] private LineEdit _columnText;
|
[Export] private LineEdit _columnText;
|
||||||
[Export] private Button _addColumnButton;
|
[Export] private Button _addColumnButton;
|
||||||
[Export] private Button _removeColumnButton;
|
[Export] private Button _removeColumnButton;
|
||||||
@ -50,7 +52,12 @@ public partial class Main : Node
|
|||||||
_removeKeyButton.Pressed += _nodeInfoEditPanel.RemoveKeyValue;
|
_removeKeyButton.Pressed += _nodeInfoEditPanel.RemoveKeyValue;
|
||||||
|
|
||||||
_mainTreePanel.MultiSelected += (_, _, _) => { _refreshPanels = true; };
|
_mainTreePanel.MultiSelected += (_, _, _) => { _refreshPanels = true; };
|
||||||
_addColumnButton.Pressed += () => _mainTreePanel.AddColumn(_columnText.Text, int.TryParse(_columnIndexText.Text, out var index) ? index : -1);
|
_addColumnButton.Pressed += () =>
|
||||||
|
{
|
||||||
|
_mainTreePanel.AddColumn(_columnText.Text,
|
||||||
|
int.TryParse(_columnIndexText.Text, out var index) ? index : -1,
|
||||||
|
int.TryParse(_columnWidthText.Text, out var width) ? width : -1);
|
||||||
|
};
|
||||||
_removeColumnButton.Pressed += () => _mainTreePanel.RemoveColumn(_columnText.Text);
|
_removeColumnButton.Pressed += () => _mainTreePanel.RemoveColumn(_columnText.Text);
|
||||||
_clearColumnButton.Pressed += () => _mainTreePanel.ClearColumns();
|
_clearColumnButton.Pressed += () => _mainTreePanel.ClearColumns();
|
||||||
|
|
||||||
@ -64,17 +71,15 @@ public partial class Main : Node
|
|||||||
_resetButton.Pressed += DoReset;
|
_resetButton.Pressed += DoReset;
|
||||||
_loadButton.Pressed += LoadData;
|
_loadButton.Pressed += LoadData;
|
||||||
_doParseButton.Text = "开始解析";
|
_doParseButton.Text = "开始解析";
|
||||||
|
|
||||||
LoadData();
|
|
||||||
|
|
||||||
_mainTreePanel.Scan("C:/Users/15401/Desktop/2025-up7"); // todo: 弄好后删掉
|
|
||||||
|
|
||||||
FoldAll();
|
|
||||||
_refreshPanels = true;
|
|
||||||
|
|
||||||
_configs = new Configs();
|
_configs = new Configs();
|
||||||
_configs.ConfigPath = "config.json";
|
_configs.ConfigPath = "config.json";
|
||||||
_configs.Load(true);
|
_configs.Load(true);
|
||||||
|
|
||||||
|
LoadData();
|
||||||
|
ScanDir();
|
||||||
|
FoldAll();
|
||||||
|
_refreshPanels = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadData()
|
private void LoadData()
|
||||||
@ -101,17 +106,9 @@ public partial class Main : Node
|
|||||||
{
|
{
|
||||||
var root = _mainTreePanel.GetRoot();
|
var root = _mainTreePanel.GetRoot();
|
||||||
if (root == null) return;
|
if (root == null) return;
|
||||||
var queue = new Queue<TreeItem>();
|
foreach (var child in root.GetChildren())
|
||||||
queue.Enqueue(root);
|
|
||||||
while (queue.Count > 0)
|
|
||||||
{
|
{
|
||||||
var treeItem = queue.Dequeue();
|
child.SetCollapsedRecursive(collapsed);
|
||||||
foreach (var child in treeItem.GetChildren())
|
|
||||||
{
|
|
||||||
if(child == null) continue;
|
|
||||||
child.Collapsed = collapsed;
|
|
||||||
queue.Enqueue(child);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +127,8 @@ public partial class Main : Node
|
|||||||
|
|
||||||
private async void ScanDir()
|
private async void ScanDir()
|
||||||
{
|
{
|
||||||
var path = await _dirSelector.SelectFolderAsync();
|
// var path = await _dirSelector.SelectFolderAsync();
|
||||||
|
var path = _configs.Get<AppConfig>().ScanPath;
|
||||||
if (string.IsNullOrEmpty(path))
|
if (string.IsNullOrEmpty(path))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -148,40 +146,11 @@ public partial class Main : Node
|
|||||||
var originName = _doParseButton.Text;
|
var originName = _doParseButton.Text;
|
||||||
_doParseButton.Disabled = true;
|
_doParseButton.Disabled = true;
|
||||||
|
|
||||||
ItemParser parser = new TMDBParser(_configs);
|
ItemParser parser = new RawParser();
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
if (_mainTreePanel.Query(root, out var node))
|
||||||
var stack = new Stack<TreeItem>();
|
|
||||||
stack.Push(root);
|
|
||||||
|
|
||||||
while (stack.Count > 0)
|
|
||||||
{
|
{
|
||||||
_doParseButton.Text = "解析中";
|
await parser.Parse(node);
|
||||||
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))
|
|
||||||
{
|
|
||||||
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.Text = originName;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ grow_vertical = 2
|
|||||||
[node name="FileDirDialog" type="FileDialog" parent="."]
|
[node name="FileDirDialog" type="FileDialog" parent="."]
|
||||||
script = ExtResource("1_d2g23")
|
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", "_columnText", "_addColumnButton", "_removeColumnButton", "_clearColumnButton", "_expandAllButton", "_foldAllButton")]
|
[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")]
|
||||||
script = ExtResource("2_0727o")
|
script = ExtResource("2_0727o")
|
||||||
_dirSelector = NodePath("../FileDirDialog")
|
_dirSelector = NodePath("../FileDirDialog")
|
||||||
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/文件夹操作/ScanDir")
|
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/文件夹操作/ScanDir")
|
||||||
@ -31,6 +31,7 @@ _removeKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/
|
|||||||
_inspectorPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer2/InspectorPanel")
|
_inspectorPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer2/InspectorPanel")
|
||||||
_mainTreePanel = NodePath("../MarginContainer/HSplitContainer/MainTreePanel")
|
_mainTreePanel = NodePath("../MarginContainer/HSplitContainer/MainTreePanel")
|
||||||
_columnIndexText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer2/ColumnIndex")
|
_columnIndexText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer2/ColumnIndex")
|
||||||
|
_columnWidthText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer3/ColumnWidth")
|
||||||
_columnText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/ColunmText")
|
_columnText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/ColunmText")
|
||||||
_addColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/AddColumn")
|
_addColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/AddColumn")
|
||||||
_removeColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/RemoveColumn")
|
_removeColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer/RemoveColumn")
|
||||||
@ -137,6 +138,17 @@ layout_mode = 2
|
|||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "行"
|
text = "行"
|
||||||
|
|
||||||
|
[node name="HBoxContainer3" type="HBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label2" type="Label" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer3"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "宽度:"
|
||||||
|
|
||||||
|
[node name="ColumnWidth" type="LineEdit" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作/HBoxContainer3"]
|
||||||
|
custom_minimum_size = Vector2(50, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作"]
|
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/VBoxContainer2/TabContainer/树表操作"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
|||||||
@ -16,5 +16,5 @@ namespace Learn.Parsers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ItemParser
|
public interface ItemParser
|
||||||
{
|
{
|
||||||
public Task<bool> DoParse(TreeNode node);
|
public Task Parse(TreeNode node);
|
||||||
}
|
}
|
||||||
171
Parsers/RawParser.cs
Normal file
171
Parsers/RawParser.cs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Learn.Models;
|
||||||
|
|
||||||
|
namespace Learn.Parsers;
|
||||||
|
|
||||||
|
public class RawParser : 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rawTitle, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryParseRawTitle(Item item, out string rawTitle)
|
||||||
|
{
|
||||||
|
rawTitle = null;
|
||||||
|
var name = item.Name();
|
||||||
|
var matches = Regex.Matches(name, @"[^\[\]_]+").Select(match => match.Value).ToList();
|
||||||
|
matches.RemoveAll(match => string.IsNullOrEmpty(match.Trim()));
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
season = null;
|
||||||
|
var name = item.Name();
|
||||||
|
var matches = Regex.Matches(name, @"[^\[\]_]+").Select(match => match.Value).ToArray();
|
||||||
|
if (matches.Length == 0) return false;
|
||||||
|
|
||||||
|
if (matches.Length == 1)
|
||||||
|
{
|
||||||
|
(_, season) = SplitTitleAndSeason(matches[0]);
|
||||||
|
if (!string.IsNullOrEmpty(season)) return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(_, season) = SplitTitleAndSeason(matches[1]);
|
||||||
|
if (!string.IsNullOrEmpty(season)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryParseGroup(Item item, out string group)
|
||||||
|
{
|
||||||
|
group = null;
|
||||||
|
var name = item.Name();
|
||||||
|
var matches = Regex.Matches(name, @"[^\[\]_《》【】]+").Select(match => match.Value).ToArray();
|
||||||
|
if (matches.Length <= 1) return false;
|
||||||
|
group = matches[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate bool FieldParser(Item item, out string result);
|
||||||
|
|
||||||
|
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;
|
||||||
|
var parsed = new List<string>();
|
||||||
|
foreach (var child in node.Children)
|
||||||
|
{
|
||||||
|
if (fieldParser(child.Info, out var childFieldValue))
|
||||||
|
{
|
||||||
|
parsed.Add(childFieldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = parsed.Count;
|
||||||
|
if (totalCount == 0)
|
||||||
|
{
|
||||||
|
result = fieldValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxGroupCount = parsed.GroupBy(value => value)
|
||||||
|
.Select(group => group.Count())
|
||||||
|
.Max();
|
||||||
|
|
||||||
|
if (maxGroupCount > totalCount / 2)
|
||||||
|
{
|
||||||
|
result = fieldValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DoParse(TreeNode node, FieldParser fieldParser, string fieldName)
|
||||||
|
{
|
||||||
|
var queue = new Queue<TreeNode>();
|
||||||
|
queue.Enqueue(node);
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
var current = queue.Dequeue();
|
||||||
|
if (TryParseField(current, fieldParser, out var fieldValue))
|
||||||
|
{
|
||||||
|
current.Info.Info.TryAdd(fieldName, fieldValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var child in current.Children)
|
||||||
|
{
|
||||||
|
queue.Enqueue(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Parse(TreeNode node)
|
||||||
|
{
|
||||||
|
DoParse(node, TryParseRawTitle, ItemFields.Key_RawTitle);
|
||||||
|
DoParse(node, TryParseSeason, ItemFields.Key_Season);
|
||||||
|
DoParse(node, TryParseGroup, ItemFields.Key_Group);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Parsers/RawParser.cs.uid
Normal file
1
Parsers/RawParser.cs.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://w0q201bv7vj8
|
||||||
@ -52,90 +52,38 @@ public class TMDBParser(Configs configs) : ItemParser
|
|||||||
return _client;
|
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)
|
|
||||||
|
public async Task Parse(TreeNode node)
|
||||||
{
|
{
|
||||||
if (!node.TryGetValue(ItemFields.Key_RawTitle, out var rawTitle, out _))
|
// if (!node.TryGetValue(ItemFields.Key_RawTitle, out var rawTitle, out _))
|
||||||
{
|
// {
|
||||||
if (!DoRawParse(node))
|
// if (!DoRawParse(node))
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
node.TryGetValue(ItemFields.Key_RawTitle, out rawTitle, out _);
|
// node.TryGetValue(ItemFields.Key_RawTitle, out rawTitle, out _);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (string.IsNullOrEmpty(rawTitle))
|
// if (string.IsNullOrEmpty(rawTitle))
|
||||||
{
|
// {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
var result = await QueryTMDB(rawTitle);
|
// var result = await QueryTMDB(rawTitle);
|
||||||
if (result == null)
|
// if (result == null)
|
||||||
{
|
// {
|
||||||
GD.PrintErr($"找不到对应的TV:{rawTitle}");
|
// GD.PrintErr($"找不到对应的TV:{rawTitle}");
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (result.FirstAirDate != null)
|
// if (result.FirstAirDate != null)
|
||||||
{
|
// {
|
||||||
node.Info.SetYear(result.FirstAirDate.Value.Year);
|
// node.Info.SetYear(result.FirstAirDate.Value.Year);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
node.Info.SetTitleIfNotExist(result.Name);
|
// node.Info.SetTitleIfNotExist(result.Name);
|
||||||
|
//
|
||||||
return true;
|
// return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user