From bf4faca1a76d5cf49c8d07dd26fb2bc39b94f48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E8=AF=9A?= Date: Wed, 16 Apr 2025 18:26:31 +0800 Subject: [PATCH] Enhance ChineseNfoRegistry job method to support optional parameters for TMDB ID, season, and episode; update configuration for HTTP proxy and connection string --- .vscode/launch.json | 35 + .vscode/tasks.json | 41 + src/Interface/Jobs/IChineseNfoRegistry.cs | 8 +- src/Service/Jobs/ChineseNfoRegistry.cs | 754 ++++++++++++++++-- .../Controllers/JobTriggerController.cs | 48 +- src/WebApi/appsettings.Development.json | 3 +- 6 files changed, 817 insertions(+), 72 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1bcc804 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,35 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // 使用 IntelliSense 找出 C# 调试存在哪些属性 + // 将悬停用于现有属性的说明 + // 有关详细信息,请访问 https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md。 + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // 如果已更改目标框架,请确保更新程序路径。 + "program": "${workspaceFolder}/src/WebApi/bin/Debug/net8.0/WebApi.dll", + "args": [], + "cwd": "${workspaceFolder}/src/WebApi", + "stopAtEntry": false, + // 启用在启动 ASP.NET Core 时启动 Web 浏览器。有关详细信息: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..75d4c67 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/NasRobot.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/NasRobot.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/NasRobot.sln" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/src/Interface/Jobs/IChineseNfoRegistry.cs b/src/Interface/Jobs/IChineseNfoRegistry.cs index 9c9b544..95bfdfe 100644 --- a/src/Interface/Jobs/IChineseNfoRegistry.cs +++ b/src/Interface/Jobs/IChineseNfoRegistry.cs @@ -2,5 +2,11 @@ namespace Interface.Jobs; public interface IChineseNfoRegistry { - void Job(bool ignoreLocked, bool ignoreCompleted); + void Job( + string? tmdbId = null, + string? seasonNumber = null, + string? episodeNumber = null, + bool ignoreLocked = false, + bool ignoreCompleted = false + ); } \ No newline at end of file diff --git a/src/Service/Jobs/ChineseNfoRegistry.cs b/src/Service/Jobs/ChineseNfoRegistry.cs index 76f28c3..808834c 100644 --- a/src/Service/Jobs/ChineseNfoRegistry.cs +++ b/src/Service/Jobs/ChineseNfoRegistry.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Text.RegularExpressions; using System.Xml; using FluentScheduler; using FreeSql; @@ -44,10 +45,16 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry .UseAutoSyncStructure(true) .Build(); - Schedule(() => Job(true, true)).ToRunEvery(1).Days(); + Schedule(() => Job(ignoreLocked: true, ignoreCompleted: true)).ToRunEvery(1).Days(); } - public async void Job(bool ignoreLocked, bool ignoreCompleted) + public async void Job( + string? tmdbId = null, + string? seasonNumber = null, + string? episodeNumber = null, + bool ignoreLocked = false, + bool ignoreCompleted = false + ) { try { @@ -61,8 +68,7 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry private async Task JobExecute( bool ignoreLocked, - bool ignoreCompleted, - string[]? includeFields = null) + bool ignoreCompleted) { var tvFolder = _configuration["ChineseNfo:TvFolder"]; @@ -73,29 +79,11 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry } /* - * 1. 支持指定字段 * 2. 接口数据保留 * 3. 支持语言降级到繁体 * 4. 支持演员名称翻译 */ - 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", - ]; - var tvNfos = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories); if (tvNfos.Length == 0) @@ -107,42 +95,472 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry foreach (var tv in tvNfos) { await HandleTv(tv); + + var seasonNfos = Directory.GetFiles(Path.GetDirectoryName(tv) ?? string.Empty, "season.nfo", SearchOption.AllDirectories); + + foreach (var season in seasonNfos) + { + await HandleSeason(tv, season); + + var episodeNfos = Directory + .GetFiles(Path.GetDirectoryName(season) ?? string.Empty, "*.nfo", SearchOption.AllDirectories) + .Where(x => !x.EndsWith("season.nfo")) + .ToList(); + + foreach (var episode in episodeNfos) + { + await HandleEpisode(tv, season, episode); + } + } } - async Task HandleTv(string tvNfo) + async Task HandleTv(string tvNfo) { var nfoContent = File.ReadAllText(tvNfo); var tvXml = new XmlDocument(); tvXml.LoadXml(nfoContent); + + var isLockedNode = tvXml.SelectSingleNode("//locked"); + + if (isLockedNode != null && isLockedNode.InnerText == "true" && ignoreLocked) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is locked"); + return; + } + + var isCompletedNode = tvXml.SelectSingleNode("//completed"); + + if (isCompletedNode != null && isCompletedNode.InnerText == "true" && ignoreCompleted) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is completed"); + return; + } + var uniqueIdNode = tvXml.SelectSingleNode("//uniqueid[@type='tmdb']"); if (uniqueIdNode == null) { _logger.LogError("ChineseNfoRegistry.Job() uniqueIdNode is null"); - return null; + return; } if (!int.TryParse(uniqueIdNode.InnerText, out var tmdbId)) { _logger.LogError("ChineseNfoRegistry.Job() tmdbId is null"); - return null; + return; } - var a = await GetTmdbTv(tvNfo, tmdbId); - - _logger.LogInformation("ChineseNfoRegistry.Job() tmdbId: {tmdbId}, name: {name}", tmdbId,a?["name"]?.ToString()); - return []; + var tvInfo = await GetTmdbTv(tvNfo, tmdbId); + + if (tvInfo == null) + { + _logger.LogError("ChineseNfoRegistry.Job() tvInfo is null"); + return; + } + + if (tvInfo["name"] != null) + { + var titleNode = tvXml.SelectSingleNode("//title"); + if (titleNode != null) + { + titleNode.InnerXml = $""; + } + + var sorttitleNode = tvXml.SelectSingleNode("//sorttitle"); + if (sorttitleNode != null) + { + sorttitleNode.InnerXml = $""; + } + } + + if (tvInfo["overview"] != null) + { + var plotNode = tvXml.SelectSingleNode("//plot"); + if (plotNode != null) + { + plotNode.InnerXml = $""; + } + + var outlineNode = tvXml.SelectSingleNode("//outline"); + if (outlineNode != null) + { + outlineNode.InnerXml = $""; + } + } + + if (tvInfo["poster_path"] != null) + { + var posterPath = tvInfo["poster_path"]!.ToString(); + var image = await GetTmdbImage(tvNfo, posterPath); + if (image != null) + { + var imagePath = Path.Combine(Path.GetDirectoryName(tvNfo) ?? string.Empty, "poster" + Path.GetExtension(posterPath)); + await File.WriteAllBytesAsync(imagePath, image); + } + } + + var actors = tvXml.SelectNodes("//actor"); + if (actors != null) + { + foreach (XmlNode actor in actors) + { + await HandleActor(actor); + } + } + + _logger.LogInformation("ChineseNfoRegistry.Job() tmdbId: {tmdbId}, name: {name}", tmdbId, tvInfo["name"]?.ToString()); + + if (isLockedNode != null) + { + isLockedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("locked"); + isLockedNode = tvXml.SelectSingleNode("//locked"); + isLockedNode!.InnerText = "true"; + } + + if (isCompletedNode != null) + { + isCompletedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("completed"); + isCompletedNode = tvXml.SelectSingleNode("//completed"); + isCompletedNode!.InnerText = "true"; + } + + // 保存 + tvXml.Save(tvNfo); + } + + async Task HandleSeason(string tvNfo, string seasonNfo) + { + var tvNfoContent = File.ReadAllText(tvNfo); + + var tvXml = new XmlDocument(); + tvXml.LoadXml(tvNfoContent); + + var uniqueIdNode = tvXml.SelectSingleNode("//uniqueid[@type='tmdb']"); + + if (uniqueIdNode == null) + { + _logger.LogError("ChineseNfoRegistry.Job() uniqueIdNode is null"); + return; + } + + if (!int.TryParse(uniqueIdNode.InnerText, out var tmdbId)) + { + _logger.LogError("ChineseNfoRegistry.Job() tmdbId is null"); + return; + } + + var nfoContent = File.ReadAllText(seasonNfo); + + var seasonXml = new XmlDocument(); + seasonXml.LoadXml(nfoContent); + + var isLockedNode = seasonXml.SelectSingleNode("//locked"); + + if (isLockedNode != null && isLockedNode.InnerText == "true" && ignoreLocked) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is locked"); + return; + } + + var isCompletedNode = seasonXml.SelectSingleNode("//completed"); + + if (isCompletedNode != null && isCompletedNode.InnerText == "true" && ignoreCompleted) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is completed"); + return; + } + + var seasonNumberNode = seasonXml.SelectSingleNode("//seasonnumber"); + + if (seasonNumberNode == null) + { + _logger.LogError("ChineseNfoRegistry.Job() seasonNumberNode is null"); + return; + } + + if (!int.TryParse(seasonNumberNode.InnerText, out var seasonNumber)) + { + _logger.LogError("ChineseNfoRegistry.Job() seasonNumber is null"); + return; + } + + var seasonInfo = await GetTmdbSeason(seasonNfo, tmdbId, seasonNumber); + + if (seasonInfo == null) + { + _logger.LogError("ChineseNfoRegistry.Job() seasonInfo is null"); + return; + } + + var titleNode = seasonXml.SelectSingleNode("//sorttitle"); + if (titleNode != null && seasonInfo["name"] != null) + { + titleNode.InnerXml = $""; + } + + var plotNode = seasonXml.SelectSingleNode("//plot"); + if (plotNode != null && seasonInfo["overview"] != null) + { + plotNode.InnerXml = $""; + } + + var outlineNode = seasonXml.SelectSingleNode("//outline"); + if (outlineNode != null && seasonInfo["overview"] != null) + { + outlineNode.InnerXml = $""; + } + + var poster_path = seasonInfo["poster_path"]?.ToString(); + if (poster_path != null) + { + var image = await GetTmdbImage(seasonNfo, poster_path); + if (image != null) + { + // season01-poster.jpg + var imagePath = Path.Combine(Path.GetDirectoryName(tvNfo) ?? string.Empty, "season" + seasonNumber.ToString("D2") + "-poster" + Path.GetExtension(poster_path)); + await File.WriteAllBytesAsync(imagePath, image); + } + } + + if (isLockedNode != null) + { + isLockedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("locked"); + isLockedNode = tvXml.SelectSingleNode("//locked"); + isLockedNode!.InnerText = "true"; + } + + if (isCompletedNode != null) + { + isCompletedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("completed"); + isCompletedNode = tvXml.SelectSingleNode("//completed"); + isCompletedNode!.InnerText = "true"; + } + + seasonXml.Save(seasonNfo); + } + + async Task HandleEpisode(string tvNfo, string seasonNfo, string episodeNfo) + { + var tvNfoContent = File.ReadAllText(tvNfo); + + var tvXml = new XmlDocument(); + tvXml.LoadXml(tvNfoContent); + + var uniqueIdNode = tvXml.SelectSingleNode("//uniqueid[@type='tmdb']"); + + if (uniqueIdNode == null) + { + _logger.LogError("ChineseNfoRegistry.Job() uniqueIdNode is null"); + return; + } + + if (!int.TryParse(uniqueIdNode.InnerText, out var tmdbId)) + { + _logger.LogError("ChineseNfoRegistry.Job() tmdbId is null"); + return; + } + + var seasonNfoContent = File.ReadAllText(seasonNfo); + + var seasonXml = new XmlDocument(); + seasonXml.LoadXml(seasonNfoContent); + + var seasonNumberNode = seasonXml.SelectSingleNode("//seasonnumber"); + + if (seasonNumberNode == null) + { + _logger.LogError("ChineseNfoRegistry.Job() seasonNumberNode is null"); + return; + } + + if (!int.TryParse(seasonNumberNode.InnerText, out var seasonNumber)) + { + _logger.LogError("ChineseNfoRegistry.Job() seasonNumber is null"); + return; + } + + var nfoContent = File.ReadAllText(episodeNfo); + + var episodeXml = new XmlDocument(); + episodeXml.LoadXml(nfoContent); + + var isLockedNode = episodeXml.SelectSingleNode("//locked"); + + if (isLockedNode != null && isLockedNode.InnerText == "true" && ignoreLocked) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is locked"); + return; + } + + var isCompletedNode = episodeXml.SelectSingleNode("//completed"); + + if (isCompletedNode != null && isCompletedNode.InnerText == "true" && ignoreCompleted) + { + _logger.LogError("ChineseNfoRegistry.Job() tvNfo is completed"); + return; + } + + + var episodeNumberNode = episodeXml.SelectSingleNode("//episode"); + + if (episodeNumberNode == null) + { + _logger.LogError("ChineseNfoRegistry.Job() episodeNumberNode is null"); + return; + } + + if (!int.TryParse(episodeNumberNode.InnerText, out var episodeNumber)) + { + _logger.LogError("ChineseNfoRegistry.Job() episodeNumber is null"); + return; + } + + var episodeInfo = await GetTmdbEpisode(episodeNfo, tmdbId, seasonNumber, episodeNumber); + + if (episodeInfo == null) + { + _logger.LogError("ChineseNfoRegistry.Job() episodeInfo is null"); + return; + } + + var titleNode = episodeXml.SelectSingleNode("//title"); + if (titleNode != null && episodeInfo["name"] != null) + { + // 特殊符号保留 + titleNode.InnerXml = $""; + } + + var plotNode = episodeXml.SelectSingleNode("//plot"); + if (plotNode != null && episodeInfo["overview"] != null) + { + plotNode.InnerXml = $""; + } + + var outlineNode = episodeXml.SelectSingleNode("//outline"); + if (outlineNode != null && episodeInfo["overview"] != null) + { + outlineNode.InnerXml = $""; + } + + var actors = episodeXml.SelectNodes("//actor"); + if (actors != null) + { + foreach (XmlNode actor in actors) + { + await HandleActor(actor); + } + } + + _logger.LogInformation("ChineseNfoRegistry.Job() tmdbId: {tmdbId}, name: {name}", tmdbId, episodeInfo["name"]?.ToString()); + + if (isLockedNode != null) + { + isLockedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("locked"); + isLockedNode = tvXml.SelectSingleNode("//locked"); + isLockedNode!.InnerText = "true"; + } + + if (isCompletedNode != null) + { + isCompletedNode.InnerText = "true"; + } + else + { + tvXml.CreateElement("completed"); + isCompletedNode = tvXml.SelectSingleNode("//completed"); + isCompletedNode!.InnerText = "true"; + } + + // 保存 + episodeXml.Save(episodeNfo); + } + + async Task GetTmdbPersonName( + string path, + int? tmdbId = null, + string? name = null + ) + { + if (tmdbId != null) + { + var person = await GetTmdbPerson(path, tmdbId.Value); + return person?["name"]?.ToString() ?? name; + } + + if (string.IsNullOrEmpty(name) == false) + { + // 如果名称是中文直接返回 + if (Regex.IsMatch(name, "^[\u4e00-\u9fa5]+$")) + { + return name; + } + + var person = await GetTmdbPersonSearch(path, name); + return person?["name"]?.ToString() ?? name; + } + + return null; + } + + async Task HandleActor(XmlNode actor) + { + var nameNode = actor.SelectSingleNode("name"); + var tmdbIdNode = actor.SelectSingleNode("tmdbid"); + if (nameNode != null || tmdbIdNode != null) + { + var name = await GetTmdbPersonName( + tvFolder, + int.TryParse(tmdbIdNode?.InnerText, out var actorTmdbId) ? actorTmdbId : null, + nameNode?.InnerText + ); + + if (name == null) + { + return; + } + + if (nameNode != null) + { + nameNode.InnerXml = $""; + } + else + { + actor.AppendChild(new XmlDocument().CreateElement("name")); + nameNode = actor.SelectSingleNode("name"); + nameNode!.InnerXml = $""; + } + } } } private async Task GetTmdbTv( string path, - int tmdbId, - TheMovieDbLanguage language = TheMovieDbLanguage.ZhCn) + int tmdbId) { var record = await _freeSql.Select() + .Where(x => x.Type == TheMovieDbType.Tv) .Where(x => x.UniqueId == tmdbId.ToString()) .FirstAsync(); @@ -154,21 +572,10 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry record = new TheMovieDbRecord { Type = TheMovieDbType.Tv, - UniqueId = tmdbId.ToString(), - Language = language + UniqueId = tmdbId.ToString() }; - - string tvUrl = "/3/tv/{0}?api_key=e28e1bc408db7adefc8bacce225c5085&language="; - - if(language == TheMovieDbLanguage.ZhCn) - { - tvUrl += "zh-CN"; - } - else - { - tvUrl += "zh-TW"; - } - + + string tvUrl = "/3/tv/{0}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN"; var requestUrl = string.Format(tvUrl, tmdbId); try @@ -184,22 +591,64 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry 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) + record.Json = str; + await _freeSql.Insert(record).ExecuteIdentityAsync(); + + _logger.LogInformation("ChineseNfoRegistry.GetTmdbTv() 接口调用, 休眠 5S"); + await Task.Delay(5000); + + return json; + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } + + private async Task GetTmdbPerson( + string path, + int tmdbId) + { + var record = await _freeSql.Select() + .Where(x => x.Type == TheMovieDbType.Person) + .Where(x => x.UniqueId == tmdbId.ToString()) + .FirstAsync(); + + if (record != null) + { + return JObject.Parse(record.Json); + } + + record = new TheMovieDbRecord + { + Type = TheMovieDbType.Person, + UniqueId = tmdbId.ToString(), + Language = TheMovieDbLanguage.ZhCn + }; + + var requestUrl = string.Format("/3/person/{0}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN", tmdbId); + + try + { + var response = await _apiClient.GetAsync(requestUrl); + + if (!response.IsSuccessStatusCode) { - _logger.LogWarning("ChineseNfoRegistry.GetTmdbTv() name: {name}, 无中文文字, 降级到繁体字", name); - // 降级到繁体 - return await GetTmdbTv(path, tmdbId, TheMovieDbLanguage.ZhTw); + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; } + var str = await response.Content.ReadAsStringAsync(); + + var json = JObject.Parse(str); + record.Json = str; await _freeSql.Insert(record).ExecuteIdentityAsync(); - - _logger.LogInformation("ChineseNfoRegistry.GetTmdbTv() 接口调用, 休眠 5S"); + + _logger.LogInformation("ChineseNfoRegistry.GetTmdbPerson() 接口调用, 休眠 5S"); await Task.Delay(5000); - + return json; } catch (Exception e) @@ -208,6 +657,197 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry return null; } } + + private async Task GetTmdbPersonSearch( + string path, + string name) + { + var record = await _freeSql.Select() + .Where(x => x.Type == TheMovieDbType.Person) + .Where(x => x.UniqueId == name) + .FirstAsync(); + + if (record != null) + { + return JObject.Parse(record.Json); + } + + record = new TheMovieDbRecord + { + Type = TheMovieDbType.Person, + UniqueId = name + }; + + var requestUrl = string.Format("/3/search/person?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN&query={0}", name); + + try + { + var response = await _apiClient.GetAsync(requestUrl); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; + } + + var str = await response.Content.ReadAsStringAsync(); + + var json = JObject.Parse(str); + + var results = json["results"]; + + if (results != null) + { + foreach (var result in results.Cast()) + { + record.Json = result.ToString(); + await _freeSql.Insert(record).ExecuteIdentityAsync(); + + _logger.LogInformation("ChineseNfoRegistry.GetTmdbPersonSearch() 接口调用, 休眠 5S"); + await Task.Delay(5000); + + return result; + } + } + + return null; + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } + + private async Task GetTmdbImage( + string path, + string posterPath) + { + var requestUrl = string.Format("/t/p/w1280/{0}", posterPath); + + try + { + var response = await _imageClient.GetAsync(requestUrl); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; + } + + return await response.Content.ReadAsByteArrayAsync(); + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } + + private async Task GetTmdbSeason( + string path, + int tmdbId, + int seasonNumber) + { + var uniqueId = $"{tmdbId}-{seasonNumber}"; + + var record = await _freeSql.Select() + .Where(x => x.Type == TheMovieDbType.Season) + .Where(x => x.UniqueId == uniqueId) + .FirstAsync(); + + if (record != null) + { + return JObject.Parse(record.Json); + } + + record = new TheMovieDbRecord + { + Type = TheMovieDbType.Season, + UniqueId = uniqueId + }; + + var requestUrl = string.Format("/3/tv/{0}/season/{1}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN", tmdbId, seasonNumber); + + try + { + var response = await _apiClient.GetAsync(requestUrl); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; + } + + var str = await response.Content.ReadAsStringAsync(); + + record.Json = str; + await _freeSql.Insert(record).ExecuteIdentityAsync(); + + _logger.LogInformation("ChineseNfoRegistry.GetTmdbSeason() 接口调用, 休眠 5S"); + await Task.Delay(5000); + + return JObject.Parse(str); + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } + + private async Task GetTmdbEpisode( + string path, + int tmdbId, + int seasonNumber, + int episodeNumber) + { + var uniqueId = $"{tmdbId}-{seasonNumber}-{episodeNumber}"; + + var record = await _freeSql.Select() + .Where(x => x.Type == TheMovieDbType.Episode) + .Where(x => x.UniqueId == uniqueId) + .FirstAsync(); + + if (record != null) + { + return JObject.Parse(record.Json); + } + + record = new TheMovieDbRecord + { + Type = TheMovieDbType.Episode, + UniqueId = uniqueId + }; + + var requestUrl = string.Format("/3/tv/{0}/season/{1}/episode/{2}?api_key=e28e1bc408db7adefc8bacce225c5085&language=zh-CN", tmdbId, seasonNumber, episodeNumber); + + try + { + var response = await _apiClient.GetAsync(requestUrl); + + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($"{requestUrl} & {path} & {response.StatusCode}"); + return null; + } + + var str = await response.Content.ReadAsStringAsync(); + + record.Json = str; + await _freeSql.Insert(record).ExecuteIdentityAsync(); + + _logger.LogInformation("ChineseNfoRegistry.GetTmdbEpisode() 接口调用, 休眠 5S"); + await Task.Delay(5000); + + return JObject.Parse(str); + } + catch (Exception e) + { + Console.WriteLine($"{requestUrl} & {path} \r {e}"); + return null; + } + } } public class TheMovieDbRecord @@ -221,8 +861,7 @@ public class TheMovieDbRecord public TheMovieDbLanguage Language { get; set; } - [Column(DbType = "text")] - public string Json { get; set; } = string.Empty; + [Column(DbType = "text")] public string Json { get; set; } = string.Empty; } public enum TheMovieDbType @@ -230,6 +869,7 @@ public enum TheMovieDbType Tv = 1, Season = 2, Episode = 3, + Person = 4 } public enum TheMovieDbLanguage diff --git a/src/WebApi/Controllers/JobTriggerController.cs b/src/WebApi/Controllers/JobTriggerController.cs index c6ae8e4..107654d 100644 --- a/src/WebApi/Controllers/JobTriggerController.cs +++ b/src/WebApi/Controllers/JobTriggerController.cs @@ -1,4 +1,5 @@ -using Interface.Jobs; +using System.Text.Json.Nodes; +using Interface.Jobs; using Microsoft.AspNetCore.Mvc; namespace WebApi.Controllers; @@ -22,8 +23,8 @@ public class JobTriggerController : BaseController IDiskActionMonitorRegistry diskActionMonitorRegistry, IHealthyTaskRegistry healthyTaskRegistry, IRSyncTaskRegistry rSyncTaskRegistry, - IStartupRegistry startupRegistry, - IShutdownRegistry shutdownRegistry, + IStartupRegistry startupRegistry, + IShutdownRegistry shutdownRegistry, IChineseNfoRegistry chineseNfoRegistry, IDiskMonitorRegistry diskMonitorRegistry) { @@ -77,36 +78,57 @@ public class JobTriggerController : BaseController return "OK"; } - + [HttpGet] public string Shutdown() { _shutdownRegistry.Job(); - + return "OK"; } - + [HttpGet] public string CancelShutdown() { _shutdownRegistry.CancelShutdown(); - + return "OK"; } - + [HttpGet] - public string ConvertChineseNfo(bool ignoreLocked = false, bool ignoreCompleted = false) + public string ConvertChineseNfo( + bool ignoreLocked = false, + bool ignoreCompleted = false) { - _chineseNfoRegistry.Job(ignoreLocked, ignoreCompleted); - + _chineseNfoRegistry.Job(ignoreLocked: ignoreLocked, ignoreCompleted: ignoreCompleted); + return "OK"; } - + + [HttpPost] + public async Task SonarrChangedConvertChineseNfo() + { + var body = Request.Body; + + using var reader = new StreamReader(body); + var text = await reader.ReadToEndAsync(); + + var json = JsonNode.Parse(text); + + var tmdbId = json?["series"]?["tmdbId"]?.ToString(); + var seasonNumber = json?["episodes"]?[0]?["seasonNumber"]?.ToString(); + var episodeNumber = json?["episodes"]?[0]?["episodeNumber"]?.ToString(); + + _chineseNfoRegistry.Job(tmdbId: tmdbId, seasonNumber: seasonNumber, episodeNumber: episodeNumber); + + return "OK"; + } + [HttpGet] public string DiskMonitor() { _diskMonitorRegistry.Job(); - + return "OK"; } } \ No newline at end of file diff --git a/src/WebApi/appsettings.Development.json b/src/WebApi/appsettings.Development.json index e0e9ff5..1817e9a 100644 --- a/src/WebApi/appsettings.Development.json +++ b/src/WebApi/appsettings.Development.json @@ -31,6 +31,7 @@ ], "ChineseNfo": { "TvFolder": "D:\\codes\\others\\ConvertChineseNfo", - "HttpProxy": "http://suncheng.online:47890" + "HttpProxy": "", + "ConnectionString": "Data Source=D:\\codes\\others\\ConvertChineseNfo\\chinesenfo.db;" } }