diff --git a/docker-compose.yml b/docker-compose.yml index d865940..a29ae4b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,6 +16,7 @@ - /wd/volc/media/tv:/data/media/tv:rw - /wd/volc/media/anime:/data/media/anime:rw - /wd/volc/media/anime-other:/data/media/anime-other:rw + - /wd/apps/vols/nas_robot:/app/data:rw - /wd:/host/wd:ro - /proc/mounts:/host/proc/mounts:ro diff --git a/src/Service/Jobs/ChineseNfoRegistry.Bak.cs b/src/Service/Jobs/ChineseNfoRegistry.Bak.cs new file mode 100644 index 0000000..d641922 --- /dev/null +++ b/src/Service/Jobs/ChineseNfoRegistry.Bak.cs @@ -0,0 +1,482 @@ +// using System.Diagnostics; +// using System.Net; +// using System.Text.Json.Nodes; +// using System.Xml; +// using Core; +// using FluentScheduler; +// using Interface.Jobs; +// using Microsoft.Extensions.Configuration; +// using Microsoft.Extensions.Logging; +// +// namespace Service.Jobs; +// +// public class ChineseNfoRegistry : Registry, IChineseNfoRegistry +// { +// private readonly IConfiguration _configuration; +// private readonly ILogger _logger; +// private readonly HttpClient _client; +// +// public ChineseNfoRegistry(IConfiguration configuration, ILogger logger) +// { +// _configuration = configuration; +// _logger = logger; +// +// var httpClientHandler = new HttpClientHandler(); +// +// var proxyAddress = _configuration["ChineseNfo:HttpProxy"]; +// +// if (string.IsNullOrEmpty(proxyAddress) == false) +// { +// httpClientHandler.Proxy = string.IsNullOrEmpty(proxyAddress) ? null : new WebProxy(proxyAddress, false); +// httpClientHandler.UseProxy = !string.IsNullOrEmpty(proxyAddress); +// } +// +// _client = new HttpClient(httpClientHandler); +// _client.BaseAddress = new Uri("http://api.themoviedb.org"); +// +// Schedule(() => Job(true, true)).ToRunEvery(1).Days(); +// } +// +// public async void Job(bool ignoreLocked, bool ignoreCompleted) +// { +// try +// { +// await JobExecute(ignoreLocked, ignoreCompleted); +// } +// catch (Exception e) +// { +// _logger.LogError(e, "ChineseNfoRegistry.Job() error"); +// } +// } +// +// +// private async Task JobExecute(bool ignoreLocked, bool ignoreCompleted) +// { +// // 读取环境变量 tv folder +// var tvFolder = _configuration["ChineseNfo:TvFolder"]; +// if (string.IsNullOrEmpty(tvFolder)) +// { +// Console.WriteLine("请设置环境变量 tv_folder"); +// return; +// } +// +// var successCount = 0; +// var failedCount = 0; +// var skippedCount = 0; +// +// // 扫描 tvshow.nfo 文件 +// var tvShowFiles = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories); +// +// foreach (var tvShowFile in tvShowFiles) +// { +// var nfoContent = File.ReadAllText(tvShowFile); +// +// // 读取 使用XML解析器 读取 60059 +// var tvXml = new XmlDocument(); +// tvXml.LoadXml(nfoContent); +// var uniqueIdNode = tvXml.SelectSingleNode("//uniqueid[@type='tmdb']"); +// if (uniqueIdNode == null) +// { +// Console.WriteLine($"{tvShowFile} & 未找到 tmdb id"); +// continue; +// } +// +// if (!int.TryParse(uniqueIdNode.InnerText, out var tmdbId)) +// { +// Console.WriteLine($"{tvShowFile} & tmdb id 不是数字"); +// continue; +// } +// +// await SetTvInfo(tvShowFile, tvXml, tmdbId); +// +// // 获取 tvShowFile 的文件夹 +// var folderPath = Path.GetDirectoryName(tvShowFile); +// +// if (folderPath == null) +// { +// Console.WriteLine($"{tvShowFile} & 未找到文件夹"); +// continue; +// } +// +// // 扫描文件夹下其他 nfo 文件 +// var seasonFiles = Directory.GetFiles(folderPath, "*.nfo", SearchOption.AllDirectories); +// +// seasonFiles = seasonFiles.Where(x => !x.EndsWith("tvshow.nfo")).ToArray(); +// +// foreach (var episodeFile in seasonFiles) +// { +// await SetEpisodeInfo(episodeFile, tmdbId); +// } +// } +// +// 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 = $"http://image.tmdb.org/t/p/w1280/{poster}"; +// // 下载并覆盖海报 +// var posterPath = tvShowFile.Replace("tvshow.nfo", $"poster.{poster.Split('.').Last()}"); +// +// using var client = new HttpClient(); +// var response = await client.GetAsync(poster); +// if (response.IsSuccessStatusCode) +// { +// var bytes = await response.Content.ReadAsByteArrayAsync(); +// +// if (File.Exists(posterPath)) +// { +// File.Delete(posterPath); +// } +// +// 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; +// } +// +// await Task.Delay(10000); +// +// 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, +// int season, +// int episode) +// { +// const string episodeUrl = "/3/tv/{0}/season/{1}/episode/{2}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN"; +// var requestUrl = string.Format(episodeUrl, tmdbId, season, episode); +// +// try +// { +// var response = await _client.GetAsync(requestUrl); +// +// await Task.Delay(10000); +// +// 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; +// } +// } +// } \ No newline at end of file diff --git a/src/Service/Jobs/ChineseNfoRegistry.cs b/src/Service/Jobs/ChineseNfoRegistry.cs index cae264d..7621d4c 100644 --- a/src/Service/Jobs/ChineseNfoRegistry.cs +++ b/src/Service/Jobs/ChineseNfoRegistry.cs @@ -1,20 +1,22 @@ -using System.Diagnostics; -using System.Net; -using System.Text.Json.Nodes; +using System.Net; using System.Xml; -using Core; using FluentScheduler; +using FreeSql; +using FreeSql.DataAnnotations; using Interface.Jobs; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; namespace Service.Jobs; public class ChineseNfoRegistry : Registry, IChineseNfoRegistry { + private readonly HttpClient _apiClient; + private readonly HttpClient _imageClient; private readonly IConfiguration _configuration; private readonly ILogger _logger; - private readonly HttpClient _client; + private readonly IFreeSql _freeSql; public ChineseNfoRegistry(IConfiguration configuration, ILogger logger) { @@ -31,8 +33,16 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry httpClientHandler.UseProxy = !string.IsNullOrEmpty(proxyAddress); } - _client = new HttpClient(httpClientHandler); - _client.BaseAddress = new Uri("http://api.themoviedb.org"); + _apiClient = new HttpClient(httpClientHandler); + _apiClient.BaseAddress = new Uri("http://api.themoviedb.org"); + + _imageClient = new HttpClient(httpClientHandler); + _imageClient.BaseAddress = new Uri("http://image.tmdb.org"); + + _freeSql = new FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Sqlite, _configuration["ChineseNfo:ConnectionString"]) + .UseAutoSyncStructure(true) + .Build(); Schedule(() => Job(true, true)).ToRunEvery(1).Days(); } @@ -49,397 +59,134 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry } } - - private async Task JobExecute(bool ignoreLocked, bool ignoreCompleted) + private async Task JobExecute( + bool ignoreLocked, + bool ignoreCompleted, + string[]? includeFields = null) { - // 读取环境变量 tv folder var tvFolder = _configuration["ChineseNfo:TvFolder"]; + if (string.IsNullOrEmpty(tvFolder)) { - Console.WriteLine("请设置环境变量 tv_folder"); + _logger.LogError("ChineseNfoRegistry.Job() tvFolder is null or empty"); return; } - var successCount = 0; - var failedCount = 0; - var skippedCount = 0; + /* + * 1. 支持指定字段 + * 2. 接口数据保留 + * 3. 支持语言降级到繁体 + * 4. 支持演员名称翻译 + */ - // 扫描 tvshow.nfo 文件 - var tvShowFiles = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories); + var fields = + includeFields ?? + [ + "tv.title", + "tv.plot", + "tv.outline", + "tv.poster", + "tv.genre", + "tv.actor.name", + "tv.actor.role", + "season.title", + "season.plot", + "episode.title", + "episode.plot", + "episode.actor.name", + ]; - foreach (var tvShowFile in tvShowFiles) + var tvNfos = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories); + + if (tvNfos.Length == 0) { - var nfoContent = File.ReadAllText(tvShowFile); + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is null or empty"); + return; + } + + foreach (var tv in tvNfos) + { + await HandleTv(tv); + } + + + async Task HandleTv(string tvNfo) + { + var nfoContent = File.ReadAllText(tvNfo); - // 读取 使用XML解析器 读取 60059 var tvXml = new XmlDocument(); tvXml.LoadXml(nfoContent); var uniqueIdNode = tvXml.SelectSingleNode("//uniqueid[@type='tmdb']"); + if (uniqueIdNode == null) { - Console.WriteLine($"{tvShowFile} & 未找到 tmdb id"); - continue; + _logger.LogError("ChineseNfoRegistry.Job() uniqueIdNode is null"); + return null; } if (!int.TryParse(uniqueIdNode.InnerText, out var tmdbId)) { - Console.WriteLine($"{tvShowFile} & tmdb id 不是数字"); - continue; + _logger.LogError("ChineseNfoRegistry.Job() tmdbId is null"); + return null; } - await SetTvInfo(tvShowFile, tvXml, tmdbId); + var a = await GetTmdbTv(tvNfo, tmdbId); - // 获取 tvShowFile 的文件夹 - var folderPath = Path.GetDirectoryName(tvShowFile); - - if (folderPath == null) - { - Console.WriteLine($"{tvShowFile} & 未找到文件夹"); - continue; - } - - // 扫描文件夹下其他 nfo 文件 - var seasonFiles = Directory.GetFiles(folderPath, "*.nfo", SearchOption.AllDirectories); - - seasonFiles = seasonFiles.Where(x => !x.EndsWith("tvshow.nfo")).ToArray(); - - foreach (var episodeFile in seasonFiles) - { - await SetEpisodeInfo(episodeFile, tmdbId); - } - } - - 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 = $"http://image.tmdb.org/t/p/w1280/{poster}"; - // 下载并覆盖海报 - var posterPath = tvShowFile.Replace("tvshow.nfo", $"poster.{poster.Split('.').Last()}"); - - using var client = new HttpClient(); - var response = await client.GetAsync(poster); - if (response.IsSuccessStatusCode) - { - var bytes = await response.Content.ReadAsByteArrayAsync(); - - if (File.Exists(posterPath)) - { - File.Delete(posterPath); - } - - 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}"); + _logger.LogInformation("ChineseNfoRegistry.Job() tmdbId: {tmdbId}, name: {name}", tmdbId,a?["name"]?.ToString()); + return []; } } - private async Task GetTmdbTv( + private async Task GetTmdbTv( string path, - int tmdbId) + int tmdbId, + TheMovieDbLanguage language = TheMovieDbLanguage.ZhCn) { + var record = await _freeSql.Select() + .Where(x => x.UniqueId == tmdbId.ToString()) + .FirstAsync(); + + if (record != null) + { + return JObject.Parse(record.Json); + } + + record = new TheMovieDbRecord + { + Type = TheMovieDbType.Tv, + UniqueId = tmdbId.ToString(), + Language = language + }; + 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); - + var response = await _apiClient.GetAsync(requestUrl); + if (!response.IsSuccessStatusCode) { Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); return null; } - - await Task.Delay(10000); - var content = await response.Content.ReadAsStringAsync(); - var json = JsonNode.Parse(content); - return json as JsonObject; + var str = await response.Content.ReadAsStringAsync(); + + var json = JObject.Parse(str); + var name = json["name"]; + // 判断是否包含中文字符 + var isChinese = name != null && name.ToString().Any(c => c >= 0x4E00 && c <= 0x9FA5); + if (language == TheMovieDbLanguage.ZhCn && !isChinese) + { + // 降级到繁体 + return await GetTmdbTv(path, tmdbId, TheMovieDbLanguage.ZhTw); + } + + record.Json = str; + _freeSql.Insert(record); + + return json; } catch (Exception e) { @@ -447,36 +194,30 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry return null; } } - - private async Task GetTmdbEpisode( - string path, - int tmdbId, - int season, - int episode) - { - const string episodeUrl = "/3/tv/{0}/season/{1}/episode/{2}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN"; - var requestUrl = string.Format(episodeUrl, tmdbId, season, episode); +} - try - { - var response = await _client.GetAsync(requestUrl); - - await Task.Delay(10000); - - if (!response.IsSuccessStatusCode) - { - Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); - return null; - } +public class TheMovieDbRecord +{ + public long Id { get; set; } - 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; - } - } + public TheMovieDbType Type { get; set; } + + public string UniqueId { get; set; } = string.Empty; + + public TheMovieDbLanguage Language { get; set; } + + [Column(DbType = "varchar(max)")] public string Json { get; set; } = string.Empty; +} + +public enum TheMovieDbType +{ + Tv = 1, + Season = 2, + Episode = 3, +} + +public enum TheMovieDbLanguage +{ + ZhCn = 1, + ZhTw = 2 } \ No newline at end of file diff --git a/src/Service/Service.csproj b/src/Service/Service.csproj index c5e7e32..26b12ef 100644 --- a/src/Service/Service.csproj +++ b/src/Service/Service.csproj @@ -12,6 +12,8 @@ + + diff --git a/src/WebApi/appsettings.json b/src/WebApi/appsettings.json index 5361256..4281461 100644 --- a/src/WebApi/appsettings.json +++ b/src/WebApi/appsettings.json @@ -60,6 +60,7 @@ ], "ChineseNfo": { "TvFolder": "/data/media", - "HttpProxy": "" + "HttpProxy": "", + "ConnectionString": "Data Source=/app/data/chinesenfo.db;" } }