diff --git a/src/Service/Jobs/ChineseNfoRegistry.cs b/src/Service/Jobs/ChineseNfoRegistry.cs index 3706d5c..193396b 100644 --- a/src/Service/Jobs/ChineseNfoRegistry.cs +++ b/src/Service/Jobs/ChineseNfoRegistry.cs @@ -64,15 +64,6 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry var failedCount = 0; var skippedCount = 0; - // 使用 root 角色执行 chmod -R 666 设置全部文件的读写权限 - var permission = new ProcessStartInfo("chmod", "-R 777 " + tvFolder) - { - CreateNoWindow = true, - UseShellExecute = false - }; - Process.Start(permission); - - // 扫描 tvshow.nfo 文件 var tvShowFiles = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories); @@ -96,6 +87,10 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry continue; } + await SetTvInfo(tvShowFile, tvXml, tmdbId); + + await Task.Delay(10000); + // 获取 tvShowFile 的文件夹 var folderPath = Path.GetDirectoryName(tvShowFile); @@ -112,155 +107,347 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry foreach (var episodeFile in seasonFiles) { - var episodeContent = await File.ReadAllTextAsync(episodeFile); - var episodeXml = new XmlDocument(); - episodeXml.LoadXml(episodeContent); - - // 判断有无 completed 节点 - var completedNode = episodeXml.SelectSingleNode("//completed"); - if (completedNode != null && ignoreCompleted == false) - { - skippedCount++; - Console.WriteLine($"{episodeFile} & 已完成"); - continue; - } - - // 判断 locked == true - var lockedNode = episodeXml.SelectSingleNode("//lockdata"); - if (lockedNode != null && lockedNode.InnerText == "true" && ignoreLocked == false) - { - skippedCount++; - Console.WriteLine($"{episodeFile} & 已锁定"); - continue; - } - - // 读取 1 - var seasonNode = episodeXml.SelectSingleNode("//season"); - if (seasonNode == null) - { - failedCount++; - Console.WriteLine($"{episodeFile} & 未找到 season"); - continue; - } - - // 读取 1 - var episodeNode = episodeXml.SelectSingleNode("//episode"); - if (episodeNode == null) - { - failedCount++; - Console.WriteLine($"{episodeFile} & 未找到 episode"); - continue; - } - - if (!int.TryParse(seasonNode.InnerText, out var season)) - { - failedCount++; - Console.WriteLine($"{episodeFile} & season 不是数字"); - continue; - } - - if (!int.TryParse(episodeNode.InnerText, out var episode)) - { - failedCount++; - Console.WriteLine($"{episodeFile} & episode 不是数字"); - continue; - } - - // 设置 title - var titleNode = episodeXml.SelectSingleNode("//title"); - if (titleNode == null) - { - failedCount++; - Console.WriteLine($"{episodeFile} & 未找到 title"); - continue; - } - - var json = await GetTmdbEpisode( - episodeFile, - tmdbId, - season, - episode); - - if (json == null) - { - failedCount++; - continue; - } - - var title = json["name"]?.ToString(); - var overview = json["overview"]?.ToString(); - - var isUpdate = false; - if (!string.IsNullOrEmpty(title)) - { - title = $""; - - if (titleNode.InnerXml != title) - { - isUpdate = true; - // 写入且不转义 - titleNode.InnerXml = title; - } - } - - var plotNode = episodeXml.SelectSingleNode("//plot"); - - if (!string.IsNullOrEmpty(overview) && plotNode != null) - { - overview = $""; - if (plotNode.InnerXml != overview) - { - isUpdate = true; - plotNode.InnerXml = overview; - } - } - - if (!isUpdate) - { - skippedCount++; - Console.WriteLine($"{episodeFile} & 无更新"); - continue; - } - - successCount++; - - // 添加一个已完成节点 - if (completedNode == null) - { - episodeXml.DocumentElement?.AppendChild(episodeXml.CreateElement("completed")); - } - - // 锁定 - if (lockedNode == null) - { - lockedNode = episodeXml.CreateElement("lockdata"); - episodeXml.DocumentElement?.AppendChild(lockedNode); - lockedNode.InnerText = "true"; - } - else - { - lockedNode.InnerText = "true"; - } - - try - { - episodeXml.Save(episodeFile); - } - catch (Exception e) - { - Console.WriteLine(e); - continue; - } - - Console.WriteLine($"{episodeFile} & {title} & {overview}"); + await SetEpisodeInfo(episodeFile, tmdbId); await Task.Delay(10000); } } await WxNotify.SendCommonAsync($"ChineseNfoRegistry.Job() success: {successCount}, failed: {failedCount}, skipped: {skippedCount}"); + + async Task SetTvInfo(string tvShowFile,XmlDocument tvXml, int tmdbId) + { + // 检查 lockdata + var lockedNode = tvXml.SelectSingleNode("//lockdata"); + if (lockedNode != null && lockedNode.InnerText == "true" && ignoreLocked == false) + { + skippedCount++; + Console.WriteLine($"{tvShowFile} & 已锁定"); + return; + } + + // 获取tv info + var tvJson = await GetTmdbTv(tvShowFile, tmdbId); + + if (tvJson == null) + { + failedCount++; + return; + } + + var title = tvJson["name"]?.ToString(); + var overview = tvJson["overview"]?.ToString(); + var poster =tvJson["poster_path"]?.ToString(); + var genres = tvJson["genres"] + ?.AsArray() + .Select(x => x?["name"]?.ToString()) + .Where(x=> !string.IsNullOrEmpty(x)) + .ToList(); + + if (!string.IsNullOrEmpty(title)) + { + title = $""; + var titleNode = tvXml.SelectSingleNode("//title"); + if (titleNode != null) + { + if (titleNode.InnerXml != title) + { + titleNode.InnerXml = title; + successCount++; + } + } + + var sorttitleNode = tvXml.SelectSingleNode("//sorttitle"); + if (sorttitleNode != null) + { + if (sorttitleNode.InnerXml != title) + { + sorttitleNode.InnerXml = title; + successCount++; + } + } + } + + if (!string.IsNullOrEmpty(overview)) + { + overview = $""; + var plotNode = tvXml.SelectSingleNode("//plot"); + if (plotNode != null) + { + if (plotNode.InnerXml != overview) + { + plotNode.InnerXml = overview; + successCount++; + } + } + + var outlineNode = tvXml.SelectSingleNode("//outline"); + if (outlineNode != null) + { + if (outlineNode.InnerXml != overview) + { + outlineNode.InnerXml = overview; + successCount++; + } + } + } + + if(!string.IsNullOrEmpty(poster)) + { + poster = $"https://image.tmdb.org/t/p/w1280/{poster}"; + // 下载并覆盖海报 + var posterPath = tvShowFile.Replace("tvshow.nfo", $"poster.{poster.Split('.').Last()}"); + + if (File.Exists(posterPath)) + { + File.Delete(posterPath); + } + + using var client = new HttpClient(); + var response = await client.GetAsync(poster); + if (response.IsSuccessStatusCode) + { + var bytes = await response.Content.ReadAsByteArrayAsync(); + await File.WriteAllBytesAsync(posterPath, bytes); + successCount++; + } + } + + + if (genres?.Any() == true) + { + // 删除原有的 节点 + var genreNodes = tvXml.SelectNodes("//genre"); + if (genreNodes != null) + { + foreach (XmlNode genreNode in genreNodes) + { + tvXml.DocumentElement?.RemoveChild(genreNode); + } + } + + // 添加新的 节点 + foreach (var genre in genres) + { + var genreNode = tvXml.CreateElement("genre"); + genreNode.InnerText = genre!; + tvXml.DocumentElement?.AppendChild(genreNode); + } + successCount++; + } + + if (successCount == 0) + { + skippedCount++; + Console.WriteLine($"{tvShowFile} & 无更新"); + return; + } + + // 锁定节点 + if(lockedNode == null) + { + lockedNode = tvXml.CreateElement("lockdata"); + tvXml.DocumentElement?.AppendChild(lockedNode); + lockedNode.InnerText = "true"; + } + else + { + lockedNode.InnerText = "true"; + } + + // 添加一个已完成节点 + var completedNode = tvXml.SelectSingleNode("//completed"); + if (completedNode == null) + { + completedNode = tvXml.CreateElement("completed"); + tvXml.DocumentElement?.AppendChild(completedNode); + } + completedNode.InnerText = "true"; + + try + { + tvXml.Save(tvShowFile); + } + catch (Exception e) + { + Console.WriteLine(e); + failedCount++; + } + } + + async Task SetEpisodeInfo(string episodeFile, int tmdbId) + { + var episodeContent = await File.ReadAllTextAsync(episodeFile); + var episodeXml = new XmlDocument(); + episodeXml.LoadXml(episodeContent); + + // 判断有无 completed 节点 + var completedNode = episodeXml.SelectSingleNode("//completed"); + if (completedNode != null && ignoreCompleted == false) + { + skippedCount++; + Console.WriteLine($"{episodeFile} & 已完成"); + return; + } + + // 判断 locked == true + var lockedNode = episodeXml.SelectSingleNode("//lockdata"); + if (lockedNode != null && lockedNode.InnerText == "true" && ignoreLocked == false) + { + skippedCount++; + Console.WriteLine($"{episodeFile} & 已锁定"); + return; + } + + // 读取 1 + var seasonNode = episodeXml.SelectSingleNode("//season"); + if (seasonNode == null) + { + failedCount++; + Console.WriteLine($"{episodeFile} & 未找到 season"); + return; + } + + // 读取 1 + var episodeNode = episodeXml.SelectSingleNode("//episode"); + if (episodeNode == null) + { + failedCount++; + Console.WriteLine($"{episodeFile} & 未找到 episode"); + return; + } + + if (!int.TryParse(seasonNode.InnerText, out var season)) + { + failedCount++; + Console.WriteLine($"{episodeFile} & season 不是数字"); + return; + } + + if (!int.TryParse(episodeNode.InnerText, out var episode)) + { + failedCount++; + Console.WriteLine($"{episodeFile} & episode 不是数字"); + return; + } + + // 设置 title + var titleNode = episodeXml.SelectSingleNode("//title"); + if (titleNode == null) + { + failedCount++; + Console.WriteLine($"{episodeFile} & 未找到 title"); + return; + } + + var json = await GetTmdbEpisode( + episodeFile, + tmdbId, + season, + episode); + + if (json == null) + { + failedCount++; + return; + } + + var title = json["name"]?.ToString(); + var overview = json["overview"]?.ToString(); + + var isUpdate = false; + if (!string.IsNullOrEmpty(title)) + { + title = $""; + + if (titleNode.InnerXml != title) + { + isUpdate = true; + // 写入且不转义 + titleNode.InnerXml = title; + } + } + + var plotNode = episodeXml.SelectSingleNode("//plot"); + + if (!string.IsNullOrEmpty(overview) && plotNode != null) + { + overview = $""; + if (plotNode.InnerXml != overview) + { + isUpdate = true; + plotNode.InnerXml = overview; + } + } + + if (!isUpdate) + { + skippedCount++; + Console.WriteLine($"{episodeFile} & 无更新"); + return; + } + + successCount++; + + // 添加一个已完成节点 + if (completedNode == null) + { + episodeXml.DocumentElement?.AppendChild(episodeXml.CreateElement("completed")); + } + + // 锁定 + if (lockedNode == null) + { + lockedNode = episodeXml.CreateElement("lockdata"); + episodeXml.DocumentElement?.AppendChild(lockedNode); + lockedNode.InnerText = "true"; + } + else + { + lockedNode.InnerText = "true"; + } + + try + { + episodeXml.Save(episodeFile); + } + catch (Exception e) + { + Console.WriteLine(e); + return; + } + + Console.WriteLine($"{episodeFile} & {title} & {overview}"); + } } + private async Task GetTmdbTv( + string path, + int tmdbId) + { + const string tvUrl = "/3/tv/{0}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN"; + var requestUrl = string.Format(tvUrl, tmdbId); + + try + { + var response = await _client.GetAsync(requestUrl); + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; + } + + var content = await response.Content.ReadAsStringAsync(); + var json = JsonNode.Parse(content); + return json as JsonObject; + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } + private async Task GetTmdbEpisode( string path, int tmdbId,