Refactor ChineseNfoRegistry to remove redundant permission setting and improve episode processing logic
This commit is contained in:
@@ -64,15 +64,6 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry
|
|||||||
var failedCount = 0;
|
var failedCount = 0;
|
||||||
var skippedCount = 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 文件
|
// 扫描 tvshow.nfo 文件
|
||||||
var tvShowFiles = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories);
|
var tvShowFiles = Directory.GetFiles(tvFolder, "tvshow.nfo", SearchOption.AllDirectories);
|
||||||
|
|
||||||
@@ -96,6 +87,10 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await SetTvInfo(tvShowFile, tvXml, tmdbId);
|
||||||
|
|
||||||
|
await Task.Delay(10000);
|
||||||
|
|
||||||
// 获取 tvShowFile 的文件夹
|
// 获取 tvShowFile 的文件夹
|
||||||
var folderPath = Path.GetDirectoryName(tvShowFile);
|
var folderPath = Path.GetDirectoryName(tvShowFile);
|
||||||
|
|
||||||
@@ -112,155 +107,347 @@ public class ChineseNfoRegistry : Registry, IChineseNfoRegistry
|
|||||||
|
|
||||||
foreach (var episodeFile in seasonFiles)
|
foreach (var episodeFile in seasonFiles)
|
||||||
{
|
{
|
||||||
var episodeContent = await File.ReadAllTextAsync(episodeFile);
|
await SetEpisodeInfo(episodeFile, tmdbId);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取 <season>1</season>
|
|
||||||
var seasonNode = episodeXml.SelectSingleNode("//season");
|
|
||||||
if (seasonNode == null)
|
|
||||||
{
|
|
||||||
failedCount++;
|
|
||||||
Console.WriteLine($"{episodeFile} & 未找到 season");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取 <episode>1</episode>
|
|
||||||
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 = $"<![CDATA[{title}]]>";
|
|
||||||
|
|
||||||
if (titleNode.InnerXml != title)
|
|
||||||
{
|
|
||||||
isUpdate = true;
|
|
||||||
// 写入且不转义
|
|
||||||
titleNode.InnerXml = title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var plotNode = episodeXml.SelectSingleNode("//plot");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(overview) && plotNode != null)
|
|
||||||
{
|
|
||||||
overview = $"<![CDATA[{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 Task.Delay(10000);
|
await Task.Delay(10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await WxNotify.SendCommonAsync($"ChineseNfoRegistry.Job() success: {successCount}, failed: {failedCount}, skipped: {skippedCount}");
|
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 = $"<![CDATA[{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 = $"<![CDATA[{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)
|
||||||
|
{
|
||||||
|
// 删除原有的 <genre> 节点
|
||||||
|
var genreNodes = tvXml.SelectNodes("//genre");
|
||||||
|
if (genreNodes != null)
|
||||||
|
{
|
||||||
|
foreach (XmlNode genreNode in genreNodes)
|
||||||
|
{
|
||||||
|
tvXml.DocumentElement?.RemoveChild(genreNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加新的 <genre> 节点
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 <season>1</season>
|
||||||
|
var seasonNode = episodeXml.SelectSingleNode("//season");
|
||||||
|
if (seasonNode == null)
|
||||||
|
{
|
||||||
|
failedCount++;
|
||||||
|
Console.WriteLine($"{episodeFile} & 未找到 season");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 <episode>1</episode>
|
||||||
|
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 = $"<![CDATA[{title}]]>";
|
||||||
|
|
||||||
|
if (titleNode.InnerXml != title)
|
||||||
|
{
|
||||||
|
isUpdate = true;
|
||||||
|
// 写入且不转义
|
||||||
|
titleNode.InnerXml = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var plotNode = episodeXml.SelectSingleNode("//plot");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(overview) && plotNode != null)
|
||||||
|
{
|
||||||
|
overview = $"<![CDATA[{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<JsonObject?> 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<JsonObject?> GetTmdbEpisode(
|
private async Task<JsonObject?> GetTmdbEpisode(
|
||||||
string path,
|
string path,
|
||||||
int tmdbId,
|
int tmdbId,
|
||||||
|
|||||||
Reference in New Issue
Block a user