using System.Collections.Generic; using System.IO; using System.Linq; using Learn.Models; using Learn.Parsers; namespace Learn; public class FileMover(string targetPath, bool preview) { private readonly HashSet _visited = new (); private string NumToString(int n) { if (n < 10) return "0" + n; return n.ToString(); } private bool TryGetPath(TreeNode node, out string path) { path = null; if (!node.TryGetValue(ItemFields.Key_Title, out var title, out _)) return false; if (!node.TryGetValue(ItemFields.Key_Season, out var season, out _)) return false; if (!node.TryGetValue(ItemFields.Key_Year, out var year, out _)) return false; path = $"{title} ({year})/"; if (node.TryGetValue(ItemFields.Key_SeasonOffsetBase, out var seasonBase, out _)) { season = seasonBase; } if (int.TryParse(season, out var seasonNum)) { path += $"Season {seasonNum}"; } else { path += season; } return true; } private void MoveFile(TreeNode node) { var path = node.Info.MainInfo[ItemFields.MainKey_Path]; if (!node.TryGetValue(ItemFields.Key_Type, out var type, out _)) return; if (!node.TryGetValue(ItemFields.Key_Title, out var title, out _)) return; if (!node.TryGetValue(ItemFields.Key_Episode, out var episode, out _)) return; if (!node.TryGetValue(ItemFields.Key_Season, out var season, out _)) return; if (!node.TryGetValue(ItemFields.Key_Year, out var year, out _)) return; if (!TryGetPath(node, out var relativePath)) return; var filenameParts = new List(); var metaParts = new List(); filenameParts.Add(title); filenameParts.Add($"({year})"); var seasonAndEpisodePart = ""; if (node.TryGetValue(ItemFields.Key_SeasonOffsetBase, out var seasonBase, out _)) { season = seasonBase; } if (int.TryParse(season, out var seasonNum)) { seasonAndEpisodePart += $"S{NumToString(seasonNum)}"; } if (!node.TryGetValue(ItemFields.Key_EpisodeOffset, out var episodeOffset, out _) || !int.TryParse(episodeOffset, out var episodeOffsetNum)) { episodeOffsetNum = 0; } var episodeNum = int.Parse(episode) + episodeOffsetNum; seasonAndEpisodePart += $"E{NumToString(episodeNum)}"; filenameParts.Add(seasonAndEpisodePart); if (node.TryGetValue(ItemFields.Key_Group, out var group, out _)) { metaParts.Add(group); } if (node.TryGetValue(ItemFields.Key_TMDBID, out var tmdbid, out _)) { metaParts.Add($"tmdbid-{tmdbid}"); } if (node.TryGetValue(ItemFields.Key_ExtraMeta, out var extraMeta, out _)) { metaParts.Add(extraMeta); } var filename = string.Join(" ", string.Join(" ", filenameParts), string.Join("", metaParts.Select(part => $"[{part}]"))); if (type == ItemFields.ItemType.Subtitle.ToString()) { if (node.TryGetValue(ItemFields.Key_SubtitleLanguage, out var subLang, out _)) { filename += "." + subLang; } } filename += Path.GetExtension(path); var target = string.Join("/", targetPath, relativePath, filename); MoveIt(node, target); } private void MoveExtra(TreeNode node) { if (!TryGetPath(node, out var relativePath)) return; if (!node.TryGetValue(ItemFields.Key_Season, out var season, out _)) return; var path = node.Info.MainInfo[ItemFields.MainKey_Path]; var name = Path.GetFileName(path); var target = string.Join("/", targetPath, relativePath, "extras", $"Season {season}", name); MoveIt(node, target); } private void MoveIt(TreeNode node, string targetPath) { node.Info.Info["TargetPath"] = targetPath; if (preview) return; var path = node.Info.MainInfo[ItemFields.MainKey_Path]; if (File.Exists(targetPath)) return; if (Directory.Exists(path)) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); Directory.Move(path, targetPath); } else { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); File.Move(path, targetPath); } } public void DoMove(TreeNode node) { if (_visited.Contains(node)) return; string type; if (!node.TryGetValue(ItemFields.Key_Type, out type, out _)) { type = ItemFields.ItemType.Unknown.ToString(); } if (type == ItemFields.ItemType.Extra.ToString()) { MoveExtra(node); _visited.Add(node); return; } if (node.Info.IsFolder()) { foreach (var child in node.Children) { DoMove(child); } } else { MoveFile(node); } _visited.Add(node); } }