mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-30 17:29:30 -06:00
FF-1256 - added nfo file creator
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
internal class Globals
|
||||
{
|
||||
public static string MOVIE_INFO = "MovieInfo";
|
||||
public static string MOVIE = "Movie";
|
||||
public static string MOVIE_CREDITS = "MovieCredits";
|
||||
public static string TV_SHOW_INFO = "TVShowInfo";
|
||||
public static string TV_EPISODE_INFO = "TVEpisodeInfo";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,19 @@
|
||||
"MusicMeta": {
|
||||
"Description": "Loads the metadata of a music file into the flow variables."
|
||||
},
|
||||
"NfoFileCreator": {
|
||||
"Description": "Creates a Kodi NFO file from previously loaded metadata.",
|
||||
"Fields": {
|
||||
"DestinationPath": "Destination Folder",
|
||||
"DestinationPath-Help": "The folder where the NFO file will be created in.\nIf empty will be created in the same directory as the original file.",
|
||||
"DestinationFile": "Destination File",
|
||||
"DestinationFile-Help": "The filename of the new NFO file. If empty, the original filename will be used with the extension changed to `.nfo`"
|
||||
},
|
||||
"Outputs": {
|
||||
"1": "NFO File created",
|
||||
"2": "NFO failed to be created"
|
||||
}
|
||||
},
|
||||
"TVShowLookup": {
|
||||
"Description": "Performs a search on TheMovieDB.org for a TV Show.\nStores the Metadata inside the variable 'TVShowInfo'.",
|
||||
"Outputs": {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using DM.MovieApi;
|
||||
using DM.MovieApi.MovieDb.Movies;
|
||||
using FileFlows.Plugin;
|
||||
using MetaNodes.TheMovieDb;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
@@ -181,7 +182,9 @@ public class MovieLookupTests
|
||||
{
|
||||
MovieDbFactory.RegisterSettings(MovieLookup.MovieDbBearerToken);
|
||||
var movieApi = MovieDbFactory.Create<IApiMovieRequest>().Value;
|
||||
var md = MovieLookup.GetVideoMetadata(movieApi, 414906, @"D:\videos\temp");
|
||||
var args = new FileFlows.Plugin.NodeParameters(@"/test/Ghostbusters 1984.mkv", new TestLogger(), false, string.Empty, null);;
|
||||
|
||||
var md = MovieLookup.GetVideoMetadata(args, movieApi, 414906, @"D:\videos\temp");
|
||||
Assert.IsNotNull(md);
|
||||
string json = System.Text.Json.JsonSerializer.Serialize(md, new System.Text.Json.JsonSerializerOptions
|
||||
{
|
||||
@@ -189,6 +192,31 @@ public class MovieLookupTests
|
||||
});
|
||||
File.WriteAllText(@"D:\videos\metadata.json", json);
|
||||
}
|
||||
[TestMethod]
|
||||
public void MovieLookupTests_WonderWoman_Nfo()
|
||||
{
|
||||
var logger = new TestLogger();
|
||||
var args = new NodeParameters(@"/test/Wonder.Woman.1984.2020.German.DL.AC3.1080p.BluRay.x265-Fun{{fdg$ERGESDG32fesdfgds}}/Wonder.Woman.1984.2020.German.DL.AC3.1080p.BluRay.x265-Fun{{fdg$ERGESDG32fesdfgds}}.mkv",
|
||||
logger, false, string.Empty, null);;
|
||||
|
||||
MovieLookup ml = new MovieLookup();
|
||||
ml.UseFolderName = false;
|
||||
|
||||
var result = ml.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
Assert.IsTrue(args.Parameters.ContainsKey(Globals.MOVIE_INFO));
|
||||
|
||||
var mi = args.Parameters[Globals.MOVIE_INFO] as MovieInfo;
|
||||
Assert.IsNotNull(mi);
|
||||
Assert.AreEqual("Wonder Woman 1984", mi.Title);
|
||||
Assert.AreEqual(2020, mi.ReleaseDate.Year);
|
||||
|
||||
var eleNfo = new NfoFileCreator();
|
||||
result = eleNfo.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
string nfo = (string)args.Variables["NFO"];
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(nfo));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#if(DEBUG)
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using DM.MovieApi.MovieDb.Movies;
|
||||
using DM.MovieApi.MovieDb.TV;
|
||||
using MetaNodes.TheMovieDb;
|
||||
@@ -102,6 +103,47 @@ public class TVEpisodeLookupTests
|
||||
Assert.AreEqual("The Batman/Superman Story (1)", args.Variables["tvepisode.Subtitle"]);
|
||||
Assert.IsFalse(string.IsNullOrWhiteSpace(args.Variables["tvepisode.Overview"] as string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void TheBatman_2x03_nfo()
|
||||
{
|
||||
var logger = new TestLogger();
|
||||
var args = new FileFlows.Plugin.NodeParameters("/test/tv/The Batman/Season 2/The Batman - 2x03.mkv", logger, false, string.Empty, null);
|
||||
|
||||
var element = new TVEpisodeLookup();
|
||||
|
||||
var result = element.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
|
||||
var eleNfo = new NfoFileCreator();
|
||||
result = eleNfo.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
|
||||
TVShowInfo tvShowInfo = (TVShowInfo)args.Variables[Globals.TV_SHOW_INFO];
|
||||
Episode epInfo = (Episode)args.Variables[Globals.TV_EPISODE_INFO];
|
||||
string nfo = eleNfo.CreateTvShowNfo(args, tvShowInfo, epInfo);
|
||||
Assert.IsNotNull(nfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TheBatman_s5e1_2_3_Nfo()
|
||||
{
|
||||
var logger = new TestLogger();
|
||||
var args = new FileFlows.Plugin.NodeParameters("/test/tv/The Batman/Season 5/The Batman - s5e1-3.mkv", logger, false, string.Empty, null);
|
||||
|
||||
var element = new TVEpisodeLookup();
|
||||
|
||||
var result = element.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
|
||||
var eleNfo = new NfoFileCreator();
|
||||
result = eleNfo.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
string nfo = (string)args.Variables["NFO"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ public class MovieLookup : Node
|
||||
}
|
||||
|
||||
// remove double spaces in case they were added when removing the year
|
||||
while (lookupName.IndexOf(" ") > 0)
|
||||
while (lookupName.IndexOf(" ", StringComparison.Ordinal) > 0)
|
||||
lookupName = lookupName.Replace(" ", " ");
|
||||
|
||||
args.Logger?.ILog("Lookup name: " + lookupName);
|
||||
@@ -145,14 +145,18 @@ public class MovieLookup : Node
|
||||
|
||||
args.SetParameter(Globals.MOVIE_INFO, result);
|
||||
|
||||
|
||||
Variables["movie.Title"] = result.Title;
|
||||
Variables["movie.Year"] = result.ReleaseDate.Year;
|
||||
var meta = GetVideoMetadata(movieApi, result.Id, args.TempPath);
|
||||
var meta = GetVideoMetadata(args, movieApi, result.Id, args.TempPath);
|
||||
Variables["VideoMetadata"] = meta;
|
||||
if (string.IsNullOrWhiteSpace(meta.OriginalLanguage) == false)
|
||||
Variables["OriginalLanguage"] = meta.OriginalLanguage;
|
||||
|
||||
Variables[Globals.MOVIE_INFO] = result;
|
||||
var movie = movieApi.FindByIdAsync(result.Id).Result.Item;
|
||||
if(movie != null)
|
||||
Variables[Globals.MOVIE] = movie;
|
||||
|
||||
args.UpdateVariables(Variables);
|
||||
return 1;
|
||||
@@ -167,7 +171,7 @@ public class MovieLookup : Node
|
||||
/// <param name="id">the ID of the movie</param>
|
||||
/// <param name="tempPath">the temp path to save any images to</param>
|
||||
/// <returns>the VideoMetadata</returns>
|
||||
internal static VideoMetadata GetVideoMetadata(IApiMovieRequest movieApi, int id, string tempPath)
|
||||
internal static VideoMetadata GetVideoMetadata(NodeParameters args, IApiMovieRequest movieApi, int id, string tempPath)
|
||||
{
|
||||
var movie = movieApi.FindByIdAsync(id).Result?.Item;
|
||||
if (movie == null)
|
||||
@@ -202,8 +206,9 @@ public class MovieLookup : Node
|
||||
|
||||
if(credits != null)
|
||||
{
|
||||
args.Variables[Globals.MOVIE_CREDITS] = credits;
|
||||
md.Actors = credits.CastMembers?.Select(x => x.Name)?.ToList();
|
||||
md.Writers = credits.CrewMembers?.Where(x => x.Job == "Writer" || x.Job == "Screenplay") ?.Select(x => x.Name)?.ToList();
|
||||
md.Writers = credits.CrewMembers?.Where(x => x.Department == "Writing" || x.Job == "Writer" || x.Job == "Screenplay") ?.Select(x => x.Name)?.ToList();
|
||||
md.Directors = credits.CrewMembers?.Where(x => x.Job == "Director")?.Select(x => x.Name)?.ToList();
|
||||
md.Producers = credits.CrewMembers?.Where(x => x.Job == "Producer")?.Select(x => x.Name)?.ToList();
|
||||
}
|
||||
|
||||
335
MetaNodes/TheMovieDb/NfoFileCreator.cs
Normal file
335
MetaNodes/TheMovieDb/NfoFileCreator.cs
Normal file
@@ -0,0 +1,335 @@
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using DM.MovieApi.MovieDb.Movies;
|
||||
using DM.MovieApi.MovieDb.TV;
|
||||
using FileFlows.Plugin;
|
||||
using FileFlows.Plugin.Attributes;
|
||||
using FileFlows.Plugin.Helpers;
|
||||
|
||||
namespace MetaNodes.TheMovieDb;
|
||||
|
||||
/// <summary>
|
||||
/// A flow element that will create a NFO file for a video once the Movie or TV Show info has been read
|
||||
/// </summary>
|
||||
public class NfoFileCreator : Node
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the number of inputs
|
||||
/// </summary>
|
||||
public override int Inputs => 1;
|
||||
/// <summary>
|
||||
/// Gets the number of outputs
|
||||
/// </summary>
|
||||
public override int Outputs => 2;
|
||||
/// <summary>
|
||||
/// Gets the flow element type
|
||||
/// </summary>
|
||||
public override FlowElementType Type => FlowElementType.Process;
|
||||
/// <summary>
|
||||
/// Gets the help URL
|
||||
/// </summary>
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/meta-nodes/nfo-file-creator";
|
||||
/// <summary>
|
||||
/// Gets the icon
|
||||
/// </summary>
|
||||
public override string Icon => "fas fa-file-code";
|
||||
|
||||
private const string TAB = " ";
|
||||
|
||||
|
||||
private string _DestinationPath = string.Empty;
|
||||
private string _DestinationFile = string.Empty;
|
||||
/// <summary>
|
||||
/// Gets or sets the destination path for zipping.
|
||||
/// </summary>
|
||||
[Folder(1)]
|
||||
public string DestinationPath
|
||||
{
|
||||
get => _DestinationPath;
|
||||
set { _DestinationPath = value ?? ""; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the destination file name for zipping.
|
||||
/// </summary>
|
||||
[TextVariable(2)]
|
||||
public string DestinationFile
|
||||
{
|
||||
get => _DestinationFile;
|
||||
set { _DestinationFile = value ?? ""; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the flow element
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string nfoXml = null;
|
||||
if (args.Variables.TryGetValue(Globals.TV_SHOW_INFO, out object oTvShowInfo) &&
|
||||
oTvShowInfo is TVShowInfo tvShowInfo)
|
||||
{
|
||||
if (args.Variables.TryGetValue(Globals.TV_EPISODE_INFO, out object oTvEpisodeInfo) &&
|
||||
oTvEpisodeInfo is Episode epInfo)
|
||||
{
|
||||
args.Logger?.ILog("TVEpisodeInfo found");
|
||||
nfoXml = CreateTvShowNfo(args, tvShowInfo, epInfo);
|
||||
|
||||
|
||||
// look for more episodes
|
||||
for (int i = 1; 1 <= 100; i++)
|
||||
{
|
||||
if (args.Variables.TryGetValue(Globals.TV_EPISODE_INFO + "_" + i, out object oOther) == false)
|
||||
break;
|
||||
if (oOther is Episode epOther == false)
|
||||
break;
|
||||
|
||||
nfoXml += CreateTvShowNfo(args, tvShowInfo, epOther);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (args.Variables.TryGetValue(Globals.MOVIE, out object oMovieInfo) &&
|
||||
oMovieInfo is Movie movie)
|
||||
{
|
||||
args.Logger?.ILog("MovieInformation found");
|
||||
nfoXml = CreateMovieNfo(args, movie);
|
||||
}
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(nfoXml))
|
||||
{
|
||||
args.Logger?.ILog("No TV or Movie information found in flow");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// remove any white space
|
||||
nfoXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" + Environment.NewLine + nfoXml.Trim();
|
||||
args.Variables["NFO"] = nfoXml;
|
||||
|
||||
string path = args.ReplaceVariables(DestinationPath, stripMissing: true)?.EmptyAsNull() ?? FileHelper.GetDirectory(args.LibraryFileName ?? string.Empty);
|
||||
string filename = args.ReplaceVariables(DestinationFile, stripMissing: true)?.EmptyAsNull() ??
|
||||
FileHelper.ChangeExtension(FileHelper.GetShortFileName(args.LibraryFileName ?? string.Empty), "nfo");
|
||||
|
||||
if ((path + filename) == ".nfo")
|
||||
{
|
||||
// this is extremely likely to be a unit test, the library file would be set otherwise
|
||||
args.Logger?.ILog("No file set to output to.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
string output = FileHelper.Combine(path, filename);
|
||||
|
||||
string tempFile = FileHelper.Combine(args.TempPath, Guid.NewGuid() + ".nfo");
|
||||
File.WriteAllText(tempFile, nfoXml);
|
||||
if (args.FileService.FileMove(tempFile, output).Failed(out string error))
|
||||
{
|
||||
args.FailureReason = error;
|
||||
return -1;
|
||||
}
|
||||
args.Logger.ILog("NFO File Created at: " + output);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private string? CreateMovieNfo(NodeParameters args, Movie movie)
|
||||
{
|
||||
StringBuilder output = new();
|
||||
|
||||
output.AppendLine("<movie>");
|
||||
|
||||
WriteXmlEscapedElement(output, "title", movie.Title);
|
||||
WriteXmlEscapedElement(output, "originaltitle", movie.OriginalTitle);
|
||||
WriteXmlEscapedElement(output, "plot", movie.Overview);
|
||||
WriteXmlEscapedElement(output, "tagline", movie.Tagline);
|
||||
if(movie.Runtime > 0)
|
||||
WriteXmlEscapedElement(output, "runtime", movie.Runtime.ToString());
|
||||
WriteXmlEscapedElement(output, "premiered", movie.ReleaseDate.ToString("yyyy-MM-dd"));
|
||||
output.AppendLine($"{TAB}<uniqueid type=\"tmdb\" default=\"true\">{movie.Id}</uniqueid>");
|
||||
if(string.IsNullOrWhiteSpace(movie.ImdbId) == false)
|
||||
output.AppendLine($"{TAB}<uniqueid type=\"imdb\">{movie.ImdbId}</uniqueid>");
|
||||
|
||||
// Genres
|
||||
if (movie.Genres?.Any() == true)
|
||||
{
|
||||
string genres = string.Join(",", movie.Genres.Select(g => g.Name));
|
||||
WriteXmlEscapedElement(output, "genres", genres);
|
||||
}
|
||||
|
||||
if(movie.ProductionCompanies?.Any() == true)
|
||||
WriteXmlEscapedElement(output, "studio", movie.ProductionCompanies.First().Name);
|
||||
|
||||
WriteThumb(output, "poster", movie.PosterPath);
|
||||
WriteThumb(output, "landscape", movie.BackdropPath);
|
||||
|
||||
object oCredits = null;
|
||||
if (args.Variables.TryGetValue(Globals.MOVIE_CREDITS, out oCredits) && oCredits is MovieCredit credit)
|
||||
{
|
||||
var writers = credit.CrewMembers
|
||||
.Where(x => x.Department == "Writing" || x.Job == "Writer" || x.Job == "Screenplay")
|
||||
.Select(crewMember => crewMember.Name).Distinct();
|
||||
|
||||
var directors = credit.CrewMembers.Where(crewMember => crewMember.Job == "Director")
|
||||
.Select(crewMember => crewMember.Name).Distinct();
|
||||
|
||||
foreach (var epWriter in writers)
|
||||
{
|
||||
WriteXmlEscapedElement(output, "credits", epWriter);
|
||||
}
|
||||
|
||||
foreach (var director in directors)
|
||||
{
|
||||
WriteXmlEscapedElement(output, "director", director);
|
||||
}
|
||||
}
|
||||
|
||||
if (movie.VoteCount > 0)
|
||||
{
|
||||
output.AppendLine(TAB + "<ratings>");
|
||||
output.AppendLine(TAB + TAB + "<rating name=\"themoviedb\" max=\"10\">");
|
||||
WriteXmlEscapedElement(output, "value", movie.VoteAverage.ToString(), tabs: 3);
|
||||
WriteXmlEscapedElement(output, "votes", movie.VoteCount.ToString(), tabs: 3);
|
||||
output.AppendLine(TAB + TAB + "</rating>");
|
||||
output.AppendLine(TAB + "</ratings>");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(movie.MovieCollectionInfo?.Name) == false)
|
||||
{
|
||||
output.AppendLine(TAB + "<set>");
|
||||
WriteXmlEscapedElement(output, "name", movie.MovieCollectionInfo.Name, tabs: 2);
|
||||
output.AppendLine(TAB + "</set>");
|
||||
}
|
||||
|
||||
|
||||
if (oCredits is MovieCredit credit2)
|
||||
{
|
||||
var cast = credit2.CastMembers?.ToList();
|
||||
if(cast?.Any() == true)
|
||||
{
|
||||
for (int i = 0; i < cast.Count; i++)
|
||||
{
|
||||
var castMember = cast[i];
|
||||
WriteActorElement(output, castMember.Name, castMember.Character, i, castMember.ProfilePath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
output.AppendLine("</movie>");
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
internal string CreateTvShowNfo(NodeParameters args, TVShowInfo tvShowInfo, Episode episode)
|
||||
{
|
||||
StringBuilder output = new();
|
||||
|
||||
output.AppendLine("<episodedetails>");
|
||||
|
||||
WriteXmlEscapedElement(output, "title", episode.Name);
|
||||
WriteXmlEscapedElement(output, "originaltitle", tvShowInfo.OriginalName);
|
||||
WriteXmlEscapedElement(output, "showtitle", tvShowInfo.Name);
|
||||
WriteXmlEscapedElement(output, "season", episode.SeasonNumber.ToString());
|
||||
WriteXmlEscapedElement(output, "episode", episode.EpisodeNumber.ToString());
|
||||
WriteXmlEscapedElement(output, "plot", episode.Overview);
|
||||
WriteXmlEscapedElement(output, "premiered", episode.AirDate.ToString("yyyy-MM-dd"));
|
||||
|
||||
output.AppendLine($"{TAB}<uniqueid type=\"tmdb\" default=\"true\">{episode.Id}</uniqueid>");
|
||||
|
||||
// Additional episode information from TVShowInfo
|
||||
//WriteXmlEscapedElement(writer, "tvshow_id", tvShowInfo.Id.ToString());
|
||||
//WriteXmlEscapedElement(writer, "tvshow_name", tvShowInfo.Name);
|
||||
//WriteXmlEscapedElement(writer, "original_name", tvShowInfo.OriginalName);
|
||||
// WriteXmlEscapedElement(writer, "poster_path", tvShowInfo.PosterPath);
|
||||
// WriteXmlEscapedElement(writer, "backdrop_path", tvShowInfo.BackdropPath);
|
||||
|
||||
WriteXmlEscapedElement(output, "overview", tvShowInfo.Overview);
|
||||
WriteXmlEscapedElement(output, "first_air_date", tvShowInfo.FirstAirDate.ToString("yyyy-MM-dd"));
|
||||
WriteXmlEscapedElement(output, "origin_country", string.Join(",", tvShowInfo.OriginCountry));
|
||||
WriteXmlEscapedElement(output, "original_language", tvShowInfo.OriginalLanguage);
|
||||
|
||||
// Genres
|
||||
if (tvShowInfo.Genres != null && tvShowInfo.Genres.Any())
|
||||
{
|
||||
string genres = string.Join(",", tvShowInfo.Genres.Select(g => g.Name));
|
||||
WriteXmlEscapedElement(output, "genres", genres);
|
||||
}
|
||||
|
||||
// Additional episode information
|
||||
WriteXmlEscapedElement(output, "episode_id", episode.Id.ToString());
|
||||
WriteXmlEscapedElement(output, "still_path", episode.StillPath);
|
||||
|
||||
if (episode.VoteCount > 0)
|
||||
{
|
||||
output.AppendLine(TAB + "<ratings>");
|
||||
output.AppendLine(TAB + TAB + "<rating namee=\"themoviedb\" max=\"10\">");
|
||||
WriteXmlEscapedElement(output, "value", episode.VoteAverage.ToString(), tabs: 3);
|
||||
WriteXmlEscapedElement(output, "votes", episode.VoteCount.ToString(), tabs: 3);
|
||||
output.AppendLine(TAB + TAB + "</rating>");
|
||||
output.AppendLine(TAB + "</ratings>");
|
||||
}
|
||||
|
||||
if (episode.Crew?.Any() == true)
|
||||
{
|
||||
var writers = episode.Crew.Where(crewMember => crewMember.Department == "Writing").Select(crewMember => crewMember.Name).Distinct();
|
||||
var directors = episode.Crew.Where(crewMember => crewMember.Job == "Director").Select(crewMember => crewMember.Name).Distinct();
|
||||
|
||||
foreach (var epWriter in writers)
|
||||
{
|
||||
WriteXmlEscapedElement(output, "credits", epWriter);
|
||||
}
|
||||
|
||||
foreach (var director in directors)
|
||||
{
|
||||
WriteXmlEscapedElement(output, "director", director);
|
||||
}
|
||||
}
|
||||
|
||||
if (episode.GuestStars?.Any() == true)
|
||||
{
|
||||
for (int i = 0; i < episode.GuestStars.Count; i++)
|
||||
{
|
||||
var guestStar = episode.GuestStars[i];
|
||||
WriteActorElement(output, guestStar.Name, guestStar.Character, i, guestStar.ProfilePath);
|
||||
}
|
||||
}
|
||||
|
||||
output.AppendLine("</episodedetails>");
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
|
||||
private void WriteXmlEscapedElement(StringBuilder output, string elementName, string elementValue, int tabs = 1)
|
||||
{
|
||||
if (string.IsNullOrEmpty(elementValue))
|
||||
return; // Skip writing if the value is null or empty
|
||||
output.Append($"{string.Join("", Enumerable.Range(1, tabs).Select(x => TAB))}<{elementName}>");
|
||||
output.Append(XmlEscape(elementValue));
|
||||
output.AppendLine($"</{elementName}>");
|
||||
}
|
||||
|
||||
private string XmlEscape(string unescaped)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
var node = doc.CreateElement("root");
|
||||
node.InnerText = unescaped;
|
||||
return node.InnerXml;
|
||||
}
|
||||
private void WriteActorElement(StringBuilder output, string name, string role, int order, string thumb)
|
||||
{
|
||||
output.AppendLine(TAB +"<actor>");
|
||||
WriteXmlEscapedElement(output, "name", name, tabs: 2);
|
||||
WriteXmlEscapedElement(output, "role", role, tabs: 2);
|
||||
WriteXmlEscapedElement(output, "order", order.ToString(), tabs: 2);
|
||||
if(string.IsNullOrWhiteSpace(thumb) == false)
|
||||
WriteXmlEscapedElement(output, "thumb", "https://image.tmdb.org/t/p/original" + thumb, tabs: 2);
|
||||
output.AppendLine(TAB + "</actor>");
|
||||
}
|
||||
|
||||
private void WriteThumb(StringBuilder output, string aspect, string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
return;
|
||||
string preview = "https://image.tmdb.org/t/p/original" + url;
|
||||
output.AppendLine(TAB +$"<thumb aspect=\"{aspect}\" preview=\"{preview}\" />");
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,19 @@ public class TVEpisodeLookup : Node
|
||||
|
||||
args.SetParameter(Globals.TV_SHOW_INFO, result);
|
||||
|
||||
if (lastEpisode > episode)
|
||||
{
|
||||
for (int i = episode.Value + 1; i <= lastEpisode; i++)
|
||||
{
|
||||
|
||||
var epInfoExtra = show.Item.Episodes.FirstOrDefault(x => x.EpisodeNumber == i);
|
||||
if (epInfoExtra == null)
|
||||
continue;
|
||||
int diff = i - episode.Value;
|
||||
args.Variables[Globals.TV_EPISODE_INFO + "_" + diff] = epInfoExtra;
|
||||
}
|
||||
}
|
||||
|
||||
Variables["tvepisode.Title"] = result.Name;
|
||||
Variables["tvepisode.Subtitle"] = epInfo.Name;
|
||||
Variables["tvepisode.Year"] = epInfo.AirDate.Year;
|
||||
@@ -156,6 +169,7 @@ public class TVEpisodeLookup : Node
|
||||
Variables["tvepisode.Overview"] = epInfo.Overview;
|
||||
//Variables["VideoMetadata"] = GetVideoMetadata(movieApi, result.Id, args.TempPath);
|
||||
Variables[Globals.TV_SHOW_INFO] = result;
|
||||
Variables[Globals.TV_EPISODE_INFO] = epInfo;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(result.OriginalLanguage) == false)
|
||||
Variables["OriginalLanguage"] = result.OriginalLanguage;
|
||||
|
||||
Reference in New Issue
Block a user