private static string CreateHtml(ShowItem si) { string posterUrl = TheTVDB.GetImageURL(si.TheSeries().GetImage(TVSettings.FolderJpgIsType.Poster)); int minYear = si.TheSeries().MinYear(); int maxYear = si.TheSeries().MaxYear(); string yearRange = (minYear == maxYear) ? minYear.ToString() : minYear + "-" + maxYear; string episodeSummary = si.TheSeries().AiredSeasons.Sum(pair => pair.Value.Episodes.Count).ToString(); string stars = ShowHtmlHelper.StarRating(si.TheSeries().GetSiteRating()); string genreIcons = string.Join(" ", si.TheSeries().GetGenres().Select(ShowHtmlHelper.GenreIconHtml)); bool ratingIsNumber = float.TryParse(si.TheSeries().GetSiteRating(), NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, CultureInfo.CreateSpecificCulture("en-US"), out float rating); string siteRating = ratingIsNumber && rating > 0 ? rating + "/10" : ""; return($@"<div class=""card card-body""> <div class=""row""> <div class=""col-md-4""> <img class=""show-poster rounded w-100"" src=""{posterUrl}"" alt=""{si.ShowName} Show Poster""></div> <div class=""col-md-8 d-flex flex-column""> <div class=""row""> <div class=""col-md-8""><h1>{si.ShowName}</h1></div> <div class=""col-md-4 text-right""><h6>{yearRange} ({si.TheSeries().GetStatus()})</h6><small class=""text-muted"">{episodeSummary} Episodes</small></div> </div> <div><blockquote>{si.TheSeries().GetOverview()}</blockquote></div> <div><blockquote>{string.Join(", ", si.TheSeries().GetActorNames())}</blockquote></div> <div class=""row align-items-bottom flex-grow-1""> <div class=""col-md-4 align-self-end"">{stars}<br>{siteRating}</div> <div class=""col-md-4 align-self-end text-center"">{si.TheSeries().GetContentRating()}<br>{si.TheSeries().GetNetwork()}</div> <div class=""col-md-4 align-self-end text-right"">{genreIcons}<br>{string.Join(", ", si.TheSeries().GetGenres())}</div> </div> </div></div></div>"); }
private static string CreateHtml([NotNull] ShowItem si) { SeriesInfo series = si.TheSeries(); if (series is null) { return(string.Empty); } string posterUrl = TheTVDB.GetImageURL(series.GetImage(TVSettings.FolderJpgIsType.Poster)); string yearRange = ShowHtmlHelper.YearRange(series); string episodeSummary = series.AiredSeasons.Sum(pair => pair.Value.Episodes.Count).ToString(); string stars = ShowHtmlHelper.StarRating(series.SiteRating / 2); string genreIcons = string.Join(" ", series.Genres().Select(ShowHtmlHelper.GenreIconHtml)); string siteRating = series.SiteRating > 0 ? series.SiteRating + "/10" : ""; return($@"<div class=""card card-body""> <div class=""row""> <div class=""col-md-4""> <img class=""show-poster rounded w-100"" src=""{posterUrl}"" alt=""{si.ShowName} Show Poster""></div> <div class=""col-md-8 d-flex flex-column""> <div class=""row""> <div class=""col-md-8""><h1>{si.ShowName}</h1></div> <div class=""col-md-4 text-right""><h6>{yearRange} ({series.Status})</h6><small class=""text-muted"">{episodeSummary} Episodes</small></div> </div> <div><blockquote>{series.Overview}</blockquote></div> <div><blockquote>{string.Join(", ", series.GetActorNames())}</blockquote></div> <div class=""row align-items-bottom flex-grow-1""> <div class=""col-md-4 align-self-end"">{stars}<br>{siteRating}</div> <div class=""col-md-4 align-self-end text-center"">{series.ContentRating}<br>{series.Network}</div> <div class=""col-md-4 align-self-end text-right"">{genreIcons}<br>{string.Join(", ", series.Genres())}</div> </div> </div></div></div>"); }
private static string CreatePosterHtml(SeriesInfo ser) { if ((!string.IsNullOrEmpty(ser.GetSeriesPosterPath())) && (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesPosterPath())))) { return($"<img class=\"show-poster rounded w-100\" src=\"{TheTVDB.GetImageURL(ser.GetSeriesPosterPath())}\" alt=\"{ser.Name} Show Poster\">"); } return(string.Empty); }
private static string CreateHorizontalBannerHtml([NotNull] this Season s) { if ((!string.IsNullOrEmpty(s.GetWideBannerPath())) && (!string.IsNullOrEmpty(TheTVDB.GetImageURL(s.GetWideBannerPath())))) { return($"<img class=\"rounded w-100\" src=\"{TheTVDB.GetImageURL(s.GetWideBannerPath())}\"><br/>"); } return(string.Empty); }
private static string CreateHorizontalBannerHtml([NotNull] SeriesInfo ser) { if ((!string.IsNullOrEmpty(ser.GetSeriesWideBannerPath())) && (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath())))) { return($"<img class=\"rounded\" src=\"{TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath())}\"><br/> "); } return(string.Empty); }
private static string ImageSection(string title, int width, int height, [CanBeNull] string bannerPath) { if (string.IsNullOrEmpty(bannerPath)) { return(""); } string url = TheTVDB.GetImageURL(bannerPath); return(string.IsNullOrEmpty(url) ? "" : $"<h2>{title}</h2><img width={width} height={height} src=\"{url}\"><br/>"); }
private static string ScreenShotHtml(this ProcessedEpisode ei) { if (!TVSettings.Instance.ShowEpisodePictures) { return(string.Empty); } if (TVSettings.Instance.HideMyShowsSpoilers && ei.HowLong() != "Aired") { return(string.Empty); } if (string.IsNullOrEmpty(ei.Filename)) { return(string.Empty); } if (string.IsNullOrWhiteSpace(TheTVDB.GetImageURL(ei.Filename))) { return(string.Empty); } return($"<img class=\"rounded w-100\" src=\"{TheTVDB.GetImageURL(ei.Filename)}\" alt=\"{ei.Name} Screenshot\">"); }
public static string GetSeasonHtmlOverviewOffline([NotNull] this ShowItem si, [NotNull] Season s) { SeriesInfo ser = s.TheSeries; int snum = s.SeasonNumber; string body = ""; if (!string.IsNullOrEmpty(ser.GetSeriesWideBannerPath()) && !string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()))) { body += "<img width=758 height=140 src=\"" + TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()) + "\"><br/>"; } List <ProcessedEpisode> eis = si.SeasonEpisodes.ContainsKey(snum) ? si.SeasonEpisodes[snum] : ShowItem.ProcessedListFromEpisodes(s.Episodes.Values, si); string seasText = SeasonName(si, snum); if ((eis.Count > 0) && (eis[0].SeasonId > 0)) { seasText = " - <A HREF=\"" + TheTVDB.Instance.WebsiteUrl(ser.TvdbCode, eis[0].SeasonId, false) + "\">" + seasText + "</a>"; } else { seasText = " - " + seasText; } body += "<h1><A HREF=\"" + TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true) + "\">" + si.ShowName + "</A>" + seasText + "</h1>"; DirFilesCache dfc = new DirFilesCache(); foreach (ProcessedEpisode ei in eis) { string epl = ei.NumsAsString(); string episodeUrl = TheTVDB.Instance.WebsiteUrl(ei.SeriesId, ei.SeasonId, ei.EpisodeId); body += "<A href=\"" + episodeUrl + "\" name=\"ep" + epl + "\">"; // anchor if (si.DvdOrder && snum == 0) { body += "<b>" + ei.Name + "</b>"; } else { body += "<b>" + HttpUtility.HtmlEncode(CustomEpisodeName.NameForNoExt(ei, CustomEpisodeName.OldNStyle(6))) + "</b>"; } body += "</A>"; // anchor if (si.UseSequentialMatch && (ei.OverallNumber != -1)) { body += " (#" + ei.OverallNumber + ")"; } List <FileInfo> fl = dfc.FindEpOnDisk(ei); if (fl.Count > 0) { foreach (FileInfo fi in fl) { string urlFilename = HttpUtility.UrlEncode(fi.FullName); body += $" <A HREF=\"watch://{urlFilename}\" class=\"search\">Watch</A>"; body += $" <A HREF=\"explore://{urlFilename}\" class=\"search\">Show in Explorer</A>"; } } else { body += " <A HREF=\"" + TVSettings.Instance.BTSearchURL(ei) + "\" class=\"search\">Search</A>"; } DateTime?dt = ei.GetAirDateDt(true); if ((dt != null) && (dt.Value.CompareTo(DateTime.MaxValue) != 0)) { body += "<p>" + dt.Value.ToShortDateString() + " (" + ei.HowLong() + ")"; } body += "<p><p>"; if ((TVSettings.Instance.ShowEpisodePictures) || (TVSettings.Instance.HideMyShowsSpoilers && ei.HowLong() != "Aired")) { body += "<table><tr>"; body += "<td width=100% valign=top>" + GetOverview(ei) + "</td><td width=300 height=225>"; // 300x168 / 300x225 if (!string.IsNullOrEmpty(ei.Filename)) { body += "<img src=" + TheTVDB.GetImageURL(ei.Filename) + ">"; } body += "</td></tr></table>"; } else { body += GetOverview(ei); } body += "<p><hr><p>"; } // for each episode in this season return(body); }
public static string GetShowHtmlOverviewOffline([NotNull] this ShowItem si) { string body = ""; SeriesInfo ser = si.TheSeries(); if ((!string.IsNullOrEmpty(ser?.GetSeriesWideBannerPath())) && (!string.IsNullOrEmpty(TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath())))) { body += "<img width=758 height=140 src=\"" + TheTVDB.GetImageURL(ser.GetSeriesWideBannerPath()) + "\"><br/>"; } body += $"<h1><A HREF=\"{TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true)}\">{si.ShowName}</A> </h1>"; body += "<h2>Overview</h2>" + ser?.Overview; //get overview in either format bool first = true; foreach (Actor aa in si.Actors.Where(aa => !string.IsNullOrEmpty(aa.ActorName))) { body += first ? "<h2>Actors</h2>" : ", "; body += "<A HREF=\"http://www.imdb.com/find?s=nm&q=" + aa.ActorName + "\">" + aa.ActorName + $"</a> as {aa.ActorRole}"; first = false; } string airsTime = ser?.AirsTime.PrettyPrint(); string airsDay = ser?.AirsDay; if ((!string.IsNullOrEmpty(airsTime)) && (!string.IsNullOrEmpty(airsDay))) { body += "<h2>Airs</h2> " + airsTime + " " + airsDay; string net = ser.Network; if (!string.IsNullOrEmpty(net)) { body += ", " + net; } } string yearRange = YearRange(ser); string siteRating = ser?.SiteRating > 0 ? ser.SiteRating + "/10" : string.Empty; string tvdbLink = TheTVDB.Instance.WebsiteUrl(si.TvdbCode, -1, true); string tableHtml = string.Empty; tableHtml += GetOverviewPart("thetvdb.com", $"<A HREF=\"{tvdbLink}\">Visit</a>"); tableHtml += GetOverviewPart("imdb.com", "<A HREF=\"http://www.imdb.com/title/" + ser?.Imdb + "\">Visit</a>"); tableHtml += GetOverviewPart("tv.com", "<A HREF=\"http://www.tv.com/show/" + ser?.SeriesId + "/summary.html\">Visit</a>"); tableHtml += GetOverviewPart("Runtime", ser?.Runtime); tableHtml += GetOverviewPart("Aliases", string.Join(", ", si.AliasNames)); tableHtml += GetOverviewPart("Genres", string.Join(", ", si.Genres)); tableHtml += GetOverviewPart("Rating", ser?.ContentRating); tableHtml += GetOverviewPart("User Rating", $"{siteRating}{AddRatingCount(ser?.SiteRatingVotes??0)}"); tableHtml += GetOverviewPart("Active From", yearRange); tableHtml += GetOverviewPart("Status", ser?.Status); if (!string.IsNullOrWhiteSpace(tableHtml)) { body += "<h2>Information<table border=0>" + tableHtml + "</table>"; } return(body); }
private bool WriteEpisodeMetaDataFile() { // "try" and silently fail. eg. when file is use by other... try { XmlWriterSettings settings = new XmlWriterSettings { Indent = true, NewLineOnAttributes = true, }; using (XmlWriter writer = XmlWriter.Create(Where.FullName, settings)) { writer.WriteStartElement("details"); writer.WriteElement("title", TVSettings.Instance.NamingStyle.NameFor(Episode)); writer.WriteElement("mpaa", Episode.TheSeries.ContentRating); if (Episode.FirstAired.HasValue) { writer.WriteElement("year", Episode.FirstAired.Value.ToString("yyyy-MM-dd")); writer.WriteElement("firstaired", Episode.FirstAired.Value.ToString("yyyy-MM-dd")); } writer.WriteElement("runtime", Episode.TheSeries.Runtime, true); writer.WriteElement("rating", Episode.EpisodeRating); writer.WriteElement("studio", Episode.TheSeries.Network); writer.WriteElement("plot", Episode.TheSeries.Overview); writer.WriteElement("overview", Episode.Overview); foreach (string director in Episode.Directors) { writer.WriteElement("directors", director); } foreach (string epwriter in Episode.Writers) { writer.WriteElement("writers", epwriter); } foreach (string genre in Episode.TheSeries.Genres()) { writer.WriteElement("genre", genre); } // actors... foreach (Actor aa in Episode.TheSeries.GetActors()) { if (string.IsNullOrEmpty(aa.ActorName)) { continue; } writer.WriteStartElement("actor"); writer.WriteElement("name", aa.ActorName); writer.WriteElement("role", aa.ActorRole); writer.WriteEndElement(); // actor } // guest stars... foreach (string guest in Episode.GuestStars) { writer.WriteElement("guest", guest); } writer.WriteElement("thumbnail", TheTVDB.GetImageURL(Episode.Filename)); writer.WriteElement("banner", TheTVDB.GetImageURL(Episode.AppropriateSeason.GetWideBannerPath())); writer.WriteElement("backdrop", TheTVDB.GetImageURL(Episode.TheSeries.GetSeriesFanartPath())); writer.WriteEndElement(); // details } Done = true; return(true); } catch (Exception e) { ErrorText = e.Message; Error = true; Done = true; return(false); } }
private static void WriteEpisodeDetailsFor([NotNull] Episode episode, [CanBeNull] ShowItem show, [NotNull] XmlWriter writer, bool multi, bool dvdOrder) { // See: http://xbmc.org/wiki/?title=Import_-_Export_Library#TV_Episodes writer.WriteStartElement("episodedetails"); writer.WriteElement("title", episode.Name); writer.WriteElement("originaltitle", show?.ShowName); writer.WriteElement("showtitle", show?.ShowName); writer.WriteElement("id", episode.EpisodeId); writer.WriteStartElement("uniqueid"); writer.WriteAttributeString("type", "tvdb"); writer.WriteAttributeString("default", "true"); writer.WriteValue(episode.EpisodeId); writer.WriteEndElement(); if (!string.IsNullOrEmpty(episode.ImdbCode)) { writer.WriteStartElement("uniqueid"); writer.WriteAttributeString("type", "imdb"); writer.WriteAttributeString("default", "false"); writer.WriteValue(episode.ImdbCode); writer.WriteEndElement(); } string showRating = episode.EpisodeRating; if (showRating != null) { writer.WriteStartElement("ratings"); writer.WriteStartElement("rating"); writer.WriteAttributeString("name", "tvdb"); writer.WriteAttributeString("max", "10"); writer.WriteAttributeString("default", "true"); writer.WriteElement("value", showRating); writer.WriteElement("votes", episode.SiteRatingCount ?? 0, true); writer.WriteEndElement(); //rating writer.WriteEndElement(); //ratings } if (dvdOrder) { writer.WriteElement("season", episode.DvdSeasonNumber); writer.WriteElement("episode", episode.DvdEpNum); } else { writer.WriteElement("season", episode.AiredSeasonNumber); writer.WriteElement("episode", episode.AiredEpNum); } writer.WriteElement("plot", episode.Overview); writer.WriteElement("studio", episode.TheSeries?.Network); writer.WriteStartElement("aired"); if (episode.FirstAired != null) { writer.WriteValue(episode.FirstAired.Value.ToString("yyyy-MM-dd")); } writer.WriteEndElement(); writer.WriteElement("mpaa", show?.TheSeries()?.ContentRating, true); //Director(s) string epDirector = episode.EpisodeDirector; if (!string.IsNullOrEmpty(epDirector)) { foreach (string daa in epDirector.Split('|')) { writer.WriteElement("director", daa, true); } } //Writers(s) string epWriter = episode.Writer; if (!string.IsNullOrEmpty(epWriter)) { foreach (string txtWriter in epWriter.Split('|')) { writer.WriteElement("credits", txtWriter, true); } } // Guest Stars... if (!string.IsNullOrEmpty(episode.EpisodeGuestStars)) { string recurringActors = ""; if (show != null) { recurringActors = string.Join("|", show.TheSeries()?.GetActorNames() ?? new List <string>()); } string guestActors = episode.EpisodeGuestStars; if (!string.IsNullOrEmpty(guestActors)) { foreach (string gaa in guestActors.Split('|') .Where(gaa => !string.IsNullOrEmpty(gaa)) .Where(gaa => string.IsNullOrEmpty(recurringActors) || !recurringActors.Contains(gaa))) { writer.WriteStartElement("actor"); writer.WriteElement("name", gaa); writer.WriteEndElement(); // actor } } } // actors... if (show != null) { foreach (Actor aa in (show.TheSeries()?.GetActors() ?? new List <Actor>()) .Where(aa => !string.IsNullOrEmpty(aa.ActorName))) { writer.WriteStartElement("actor"); writer.WriteElement("name", aa.ActorName); writer.WriteElement("role", aa.ActorRole); writer.WriteElement("order", aa.ActorSortOrder); writer.WriteElement("thumb", TheTVDB.GetImageURL(aa.ActorImage), true); writer.WriteEndElement(); // actor } } if (multi) { writer.WriteStartElement("resume"); //we have to put 0 as we don't know where the multipart episode starts/ends writer.WriteElement("position", 0); writer.WriteElement("total", 0); writer.WriteEndElement(); // resume //For now we only put art in for multipart episodes. Kodi finds the art appropriately //without our help for the others if (show != null) { string filename = TVSettings.Instance.FilenameFriendly( TVSettings.Instance.NamingStyle.GetTargetEpisodeName(show, episode, show.GetTimeZone(), show.DvdOrder)); string thumbFilename = filename + ".jpg"; writer.WriteElement("thumb", thumbFilename); //Should be able to do this using the local filename, but only seems to work if you provide a URL //XMLHelper.WriteElementToXML(writer, "thumb", TheTVDB.Instance.GetTVDBDownloadURL(episode.GetFilename())) } } writer.WriteEndElement(); // episodedetails }
private void WriteSeriesXmlFile([NotNull] XmlWriter writer) { SeriesInfo series = SelectedShow.TheSeries(); // https://kodi.wiki/view/NFO_files/TV_shows writer.WriteStartElement("tvshow"); writer.WriteElement("title", SelectedShow.ShowName); writer.WriteElement("originaltitle", series?.Name); writer.WriteElement("studio", series?.Network); float?showRating = series?.SiteRating; if (showRating.HasValue) { writer.WriteStartElement("ratings"); writer.WriteStartElement("rating"); writer.WriteAttributeString("name", "tvdb"); writer.WriteAttributeString("max", "10"); writer.WriteAttributeString("default", "true"); writer.WriteElement("value", showRating.Value); writer.WriteElement("votes", series.SiteRatingVotes, true); writer.WriteEndElement(); //rating writer.WriteEndElement(); //ratings } string lang = TVSettings.Instance.PreferredLanguageCode; if (SelectedShow.UseCustomLanguage && SelectedShow.PreferredLanguage != null) { lang = SelectedShow.PreferredLanguage.Abbreviation; } //https://forum.kodi.tv/showthread.php?tid=323588 //says that we need a format like this: //<episodeguide><url post="yes" cache="auth.json">https://api.thetvdb.com/login?{"apikey":"((API-KEY))","id":((ID))}|Content-Type=application/json</url></episodeguide> writer.WriteStartElement("episodeguide"); writer.WriteStartElement("url"); writer.WriteAttributeString("post", "yes"); writer.WriteAttributeString("cache", "auth.json"); writer.WriteRaw(TheTVDB.BuildUrl(SelectedShow.TvdbCode, lang)); writer.WriteEndElement(); //url writer.WriteEndElement(); //episodeguide if (!(series is null)) { writer.WriteElement("id", series.TvdbCode); writer.WriteElement("runtime", series.Runtime, true); writer.WriteElement("mpaa", series.ContentRating, true); writer.WriteStartElement("uniqueid"); writer.WriteAttributeString("type", "tvdb"); writer.WriteAttributeString("default", "true"); writer.WriteValue(series.TvdbCode); writer.WriteEndElement(); writer.WriteStartElement("uniqueid"); writer.WriteAttributeString("type", "imdb"); writer.WriteAttributeString("default", "false"); writer.WriteValue(series.Imdb); writer.WriteEndElement(); writer.WriteElement("plot", series.Overview); writer.WriteElement("premiered", series.FirstAired); writer.WriteElement("year", series.Year); writer.WriteElement("status", series.Status); } writer.WriteStringsToXml("genre", SelectedShow.Genres); // actors... foreach (Actor aa in SelectedShow.Actors.Where(aa => !string.IsNullOrEmpty(aa.ActorName))) { writer.WriteStartElement("actor"); writer.WriteElement("name", aa.ActorName); writer.WriteElement("role", aa.ActorRole); writer.WriteElement("order", aa.ActorSortOrder); writer.WriteElement("thumb", TheTVDB.GetImageURL(aa.ActorImage), true); writer.WriteEndElement(); // actor } writer.WriteEndElement(); // tvshow }