public static void GuessShowItem([NotNull] PossibleNewTvShow ai, [NotNull] ShowLibrary library, bool showErrorMsgBox) { string languageCode = TVSettings.Instance.DefaultProvider == TVDoc.ProviderType.TMDB ? TVSettings.Instance.TMDBLanguage : TVSettings.Instance.PreferredLanguageCode; string showName = GuessShowName(ai, library); //todo - (BulkAdd Manager needs to work for new providers) int tvdbId = FindTVDBShowCode(ai); if (string.IsNullOrEmpty(showName) && tvdbId == -1) { return; } if (tvdbId != -1) { try { CachedSeriesInfo cachedSeries = TheTVDB.LocalCache.Instance.GetSeriesAndDownload(tvdbId, showErrorMsgBox); if (cachedSeries != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); return; } } catch (MediaNotFoundException) { //continue to try the next method } } CachedSeriesInfo ser = TheTVDB.LocalCache.Instance.GetSeries(showName, showErrorMsgBox, languageCode); if (ser != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); return; } //Try removing any year string showNameNoYear = Regex.Replace(showName, @"\(\d{4}\)", "").Trim(); //Remove anything we can from hint to make it cleaner and hence more likely to match string refinedHint = FinderHelper.RemoveSeriesEpisodeIndicators(showNameNoYear, library.SeasonWords()); if (string.IsNullOrWhiteSpace(refinedHint)) { Logger.Info($"Ignoring {showName} as it refines to nothing."); } ser = TheTVDB.LocalCache.Instance.GetSeries(refinedHint, showErrorMsgBox, languageCode); ai.RefinedHint = refinedHint; if (ser != null) { ai.SetId(tvdbId, TVDoc.ProviderType.TheTVDB); } }
public override ItemList?ProcessShow(ShowConfiguration si, bool forceRefresh) { if (TVSettings.Instance.Mede8erXML) { ItemList theActionList = new ItemList(); FileInfo tvshowxml = FileHelper.FileInFolder(si.AutoAddFolderBase, "cachedSeries.xml"); CachedSeriesInfo cachedSeriesInfo = si.CachedShow; bool needUpdate = !tvshowxml.Exists || cachedSeriesInfo is null || cachedSeriesInfo.SrvLastUpdated > TimeZoneHelper.Epoch(tvshowxml.LastWriteTime); if ((forceRefresh || needUpdate) && !doneFiles.Contains(tvshowxml.FullName)) { doneFiles.Add(tvshowxml.FullName); theActionList.Add(new ActionMede8erXML(tvshowxml, si)); } //Updates requested by [email protected] on 18/4/2013 FileInfo viewxml = FileHelper.FileInFolder(si.AutoAddFolderBase, "View.xml"); if (!viewxml.Exists && !doneFiles.Contains(viewxml.FullName)) { doneFiles.Add(viewxml.FullName); theActionList.Add(new ActionMede8erViewXML(viewxml, si)); } return(theActionList); } return(base.ProcessShow(si, forceRefresh)); }
public override ItemList ProcessShow(ShowConfiguration si, bool forceRefresh) { ItemList theActionList = new ItemList(); if (!TVSettings.Instance.FolderJpg) { return(theActionList); } FileInfo fi = FileHelper.FileInFolder(si.AutoAddFolderBase, DEFAULT_FILE_NAME); bool fileDoesntExist = !doneFolderJpg.Contains(fi.FullName) && !fi.Exists; if (forceRefresh || fileDoesntExist) { CachedSeriesInfo cachedSeries = si.CachedShow; if (cachedSeries is null) { return(theActionList); } //default to poster when we want season posters for the season specific folders string downloadPath = TVSettings.Instance.SeasonSpecificFolderJPG() ? cachedSeries.GetSeriesPosterPath() : cachedSeries.GetImage(TVSettings.Instance.ItemForFolderJpg()); if (!string.IsNullOrEmpty(downloadPath)) { theActionList.Add(new ActionDownloadImage(si, null, fi, downloadPath, false)); } doneFolderJpg.Add(fi.FullName); } return(theActionList); }
private static string CreateHtml([NotNull] ShowConfiguration si) { CachedSeriesInfo cachedSeries = si.CachedShow; if (cachedSeries is null) { return(string.Empty); } string posterUrl = TheTVDB.API.GetImageURL(cachedSeries.GetImage(TVSettings.FolderJpgIsType.Poster)); string yearRange = ShowHtmlHelper.YearRange(cachedSeries); string episodeSummary = cachedSeries.Episodes.Count.ToString(); string stars = ShowHtmlHelper.StarRating(cachedSeries.SiteRating / 2); string genreIcons = string.Join(" ", cachedSeries.Genres.Select(ShowHtmlHelper.GenreIconHtml)); string siteRating = cachedSeries.SiteRating > 0 ? cachedSeries.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} ({cachedSeries.Status})</h6><small class=""text-muted"">{episodeSummary} Episodes</small></div> </div> <div><blockquote>{cachedSeries.Overview}</blockquote></div> <div><blockquote>{cachedSeries.GetActorNames().ToCsv()}</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"">{cachedSeries.ContentRating}<br>{cachedSeries.Network}</div> <div class=""col-md-4 align-self-end text-right"">{genreIcons}<br>{cachedSeries.Genres.ToCsv()}</div> </div> </div></div></div>"); }
public static bool FindSeasEpDateCheck(string?filename, out int seas, out int ep, ShowConfiguration?si) { ep = -1; seas = -1; if (filename is null || si is null) { return(false); } // look for a valid airdate in the filename // check for YMD, DMY, and MDY // only check against airdates we expect for the given show CachedSeriesInfo ser = si.CachedShow; if (ser is null) { return(false); } string[] dateFormats = { "yyyy-MM-dd", "dd-MM-yyyy", "MM-dd-yyyy", "yy-MM-dd", "dd-MM-yy", "MM-dd-yy" }; // force possible date separators to a dash filename = filename.Replace("/", "-"); filename = filename.Replace(".", "-"); filename = filename.Replace(",", "-"); filename = filename.Replace(" ", "-"); foreach (Episode epi in si.EpisodesToUse()) { LocalDateTime?dt = epi.GetAirDateDt(); // file will have local timezone date, not ours if (dt is null) { continue; } TimeSpan closestDate = TimeSpan.MaxValue; foreach (string dateFormat in dateFormats) { string datestr = dt.Value.ToString(dateFormat, CultureInfo.CurrentCulture); if (filename.Contains(datestr) && DateTime.TryParseExact(datestr, dateFormat, new CultureInfo("en-GB"), DateTimeStyles.None, out DateTime dtInFilename)) { TimeSpan timeAgo = DateTime.Now.Subtract(dtInFilename); if (timeAgo < closestDate) { seas = epi.GetSeasonNumber(si.Order); ep = epi.GetEpisodeNumber(si.Order); closestDate = timeAgo; } } } } return(ep != -1 && seas != -1); }
public Episode(int seriesId, [NotNull] JObject r, CachedSeriesInfo si) : this(seriesId, si) { // <Episode> // <id>...</id> // blah blah // </Episode> LoadJson(r); }
public static void GuessShowItem([NotNull] PossibleNewTvShow ai, [NotNull] ShowLibrary library, bool showErrorMsgBox) { string showName = GuessShowName(ai, library); int tvdbId = FindShowCode(ai); if (string.IsNullOrEmpty(showName) && tvdbId == -1) { return; } if (tvdbId != -1) { try { CachedSeriesInfo cachedSeries = TheTVDB.LocalCache.Instance.GetSeriesAndDownload(tvdbId, showErrorMsgBox); if (cachedSeries != null) { ai.TVDBCode = tvdbId; return; } } catch (ShowNotFoundException) { //continue to try the next method } } CachedSeriesInfo ser = TheTVDB.LocalCache.Instance.GetSeries(showName, showErrorMsgBox); if (ser != null) { ai.TVDBCode = ser.TvdbCode; return; } //Try removing any year string showNameNoYear = Regex.Replace(showName, @"\(\d{4}\)", "").Trim(); //Remove anything we can from hint to make it cleaner and hence more likely to match string refinedHint = FinderHelper.RemoveSeriesEpisodeIndicators(showNameNoYear, library.SeasonWords()); if (string.IsNullOrWhiteSpace(refinedHint)) { Logger.Info($"Ignoring {showName} as it refines to nothing."); } ser = TheTVDB.LocalCache.Instance.GetSeries(refinedHint, showErrorMsgBox); ai.RefinedHint = refinedHint; if (ser != null) { ai.TVDBCode = ser.TvdbCode; } }
public void LoadFromXml([NotNull] XElement xmlSettings) { foreach (ShowConfiguration si in xmlSettings.Descendants("ShowItem").Select(showSettings => new ShowConfiguration(showSettings))) { if (si.UseCustomShowName) // see if custom show name is actually the real show name { CachedSeriesInfo ser = si.CachedShow; if (ser != null && si.CustomShowName == ser.Name) { // then, turn it off si.CustomShowName = string.Empty; si.UseCustomShowName = false; } } Add(si); } }
public static bool GenerateEpisodeDict([NotNull] ShowConfiguration si) { // copy data from tvdb // process as per rules // done! bool r = true; lock (si.Provider == TVDoc.ProviderType.TVmaze? TVmaze.LocalCache.Instance.SERIES_LOCK: TheTVDB.LocalCache.Instance.SERIES_LOCK) { si.ClearEpisodes(); CachedSeriesInfo ser = si.Provider == TVDoc.ProviderType.TVmaze ? TVmaze.LocalCache.Instance.GetSeries(si.TVmazeCode): si.Provider == TVDoc.ProviderType.TMDB ? TMDB.LocalCache.Instance.GetSeries(si.TmdbCode) : TheTVDB.LocalCache.Instance.GetSeries(si.TvdbCode); if (ser is null) { string source = si.Provider == TVDoc.ProviderType.TVmaze ? "TVMaze" : "TVDB"; Logger.Warn($"Asked to generate episodes for {si.ShowName}, but this has not yet been downloaded from {source}"); return(false); } foreach (Episode ep in ser.Episodes) { si.AddEpisode(ep); } foreach (int snum in si.AppropriateSeasons().Keys.ToList()) { List <ProcessedEpisode> pel = GenerateEpisodes(si, snum, true); si.SeasonEpisodes[snum] = pel; if (pel is null) { r = false; } } AddOverallCount(si); } return(r); }
private static bool EpisodeNeeded([NotNull] ShowConfiguration si, DirFilesCache dfc, int seasF, int epF, [NotNull] FileSystemInfo fi) { if (si is null) { throw new ArgumentNullException(nameof(si)); } if (fi is null) { throw new ArgumentNullException(nameof(fi)); } try { CachedSeriesInfo s = si.CachedShow; if (s is null) { //We have not downloaded the cachedSeries, so have to assume that we need the episode/file return(true); } ProcessedEpisode pep = si.GetEpisode(seasF, epF); foreach (FileInfo testFileInfo in FindEpOnDisk(dfc, si, pep)) { //We will check that the file that is found is not the one we are testing if (fi.FullName == testFileInfo.FullName) { continue; } //We have found another file that matches return(false); } } catch (ShowConfiguration.EpisodeNotFoundException) { //Ignore exception, we may need the file return(true); } return(true); }
private static Action SetupDirectoryRemoval([NotNull] DirectoryInfo di, [NotNull] IReadOnlyList <ShowConfiguration> matchingShows) { ShowConfiguration si = matchingShows[0]; //Choose the first cachedSeries FinderHelper.FindSeasEp(di, out int seasF, out int epF, si, out TVSettings.FilenameProcessorRE _); CachedSeriesInfo s = si.CachedShow; if (s is null) { throw new ArgumentNullException(nameof(s)); } ProcessedEpisode pep = si.GetEpisode(seasF, epF); LOGGER.Info( $"Removing {di.FullName} as it matches {si.ShowName} and no episodes are needed"); return(new ActionDeleteDirectory(di, pep, TVSettings.Instance.Tidyup)); }
public Episode(int seriesId, CachedSeriesInfo si) { internalSeries = si; SeriesId = seriesId; Overview = string.Empty; EpisodeRating = string.Empty; EpisodeGuestStars = string.Empty; EpisodeDirector = string.Empty; Writer = string.Empty; mName = string.Empty; EpisodeId = -1; ReadAiredSeasonNum = -1; ReadDvdSeasonNum = -1; AiredEpNum = -1; DvdEpNum = -1; FirstAired = null; SrvLastUpdated = -1; Dirty = false; }
private static ListViewItem NewLvi([NotNull] CachedSeriesInfo si, int num, string show, bool numberMatch) { ListViewItem lvi = new ListViewItem { Text = num.ToString() }; lvi.SubItems.Add(show); lvi.SubItems.Add(si.Year); lvi.SubItems.Add(si.Network ?? string.Empty); lvi.SubItems.Add(si.Status); lvi.ToolTipText = si.Overview; lvi.Tag = si; if (numberMatch) { lvi.Selected = true; } return(lvi); }
public override ItemList?ProcessShow(ShowConfiguration si, bool forceRefresh) { if (TVSettings.Instance.wdLiveTvMeta) { ItemList theActionList = new ItemList(); FileInfo tvShowXml = FileHelper.FileInFolder(si.AutoAddFolderBase, "cachedSeries.xml"); CachedSeriesInfo cachedSeriesInfo = si.CachedShow; bool needUpdate = !tvShowXml.Exists || cachedSeriesInfo is null || cachedSeriesInfo.SrvLastUpdated > TimeZoneHelper.Epoch(tvShowXml.LastWriteTime); if ((forceRefresh || needUpdate) && !doneFiles.Contains(tvShowXml.FullName)) { doneFiles.Add(tvShowXml.FullName); theActionList.Add(new ActionWdtvMeta(tvShowXml, si)); } return(theActionList); } return(base.ProcessShow(si, forceRefresh)); }
public static bool GenerateEpisodeDict([NotNull] ShowConfiguration si) { // copy data from tvdb // process as per rules // done! bool r = true; lock (TVDoc.GetMediaCache(si.Provider).SERIES_LOCK) { si.ClearEpisodes(); CachedSeriesInfo ser = TVDoc.GetMediaCache(si.Provider).GetSeries(si.Code); if (ser is null) { Logger.Warn($"Asked to generate episodes for {si.ShowName}, but this has not yet been downloaded from {si.Provider.PrettyPrint()}"); return(false); } foreach (Episode ep in ser.Episodes) { si.AddEpisode(ep); } foreach (int snum in si.AppropriateSeasons().Keys.ToList()) { List <ProcessedEpisode> pel = GenerateEpisodes(si, snum, true); si.SeasonEpisodes[snum] = pel; if (pel is null) { r = false; } } AddOverallCount(si); } return(r); }
public override ItemList?ProcessShow(ShowConfiguration si, bool forceRefresh) { // for each tv show, optionally write a tvshow.nfo file if (TVSettings.Instance.NFOShows) { ItemList theActionList = new ItemList(); FileInfo tvshownfo = FileHelper.FileInFolder(si.AutoAddFolderBase, "tvshow.nfo"); CachedSeriesInfo cachedSeriesInfo = si.CachedShow; bool needUpdate = !tvshownfo.Exists || cachedSeriesInfo is null || System.Math.Abs(cachedSeriesInfo.SrvLastUpdated - TimeZoneHelper.Epoch(tvshownfo.LastWriteTime)) > 1; bool alreadyOnTheList = DoneNfo.Contains(tvshownfo.FullName); if ((forceRefresh || needUpdate) && !alreadyOnTheList) { theActionList.Add(new ActionNfoShow(tvshownfo, si)); DoneNfo.Add(tvshownfo.FullName); } return(theActionList); } return(base.ProcessShow(si, forceRefresh)); }
public Episode(int seriesId, JObject?bestLanguageR, JObject jsonInDefaultLang, CachedSeriesInfo si) : this(seriesId, si) { if (bestLanguageR is null) { LoadJson(jsonInDefaultLang); } else { //Here we have two pieces of JSON. One in local language and one in the default language (English). //We will populate with the best language first and then fill in any gaps with the backup Language LoadJson(bestLanguageR); //backupLanguageR should be a cachedSeries of name/value pairs (ie a JArray of JProperties) //TVDB asserts that name and overview are the fields that are localised string?epName = (string)jsonInDefaultLang["episodeName"]; if (string.IsNullOrWhiteSpace(mName) && epName != null) { mName = System.Web.HttpUtility.HtmlDecode(epName).Trim(); } string overviewFromJson = (string)jsonInDefaultLang["overview"]; if (string.IsNullOrWhiteSpace(Overview) && overviewFromJson != null) { Overview = System.Web.HttpUtility.HtmlDecode(overviewFromJson).Trim(); } } }
// ReSharper disable once NotNullMemberIsNotInitialized public SeriesBanners(CachedSeriesInfo s) { cachedSeries = s; ResetBanners(); }
private static void UpdateEpisodeFields([NotNull] Episode episode, ShowConfiguration?show, [NotNull] XElement root, bool isMultiPart) { root.UpdateElement("title", episode.Name, true); root.UpdateElement("id", episode.EpisodeId, true); root.UpdateElement("plot", episode.Overview, true); UpdateAmongstElements(root, "studio", episode.TheCachedSeries.Network); UpdateId(root, "tvdb", "true", episode.EpisodeId); UpdateId(root, "imdb", "false", episode.ImdbCode); string showRating = episode.EpisodeRating; if (showRating != null) { UpdateRatings(root, showRating, episode.SiteRatingCount ?? 0); } if (!(show is null)) { root.UpdateElement("originaltitle", show.ShowName, true); root.UpdateElement("showtitle", show.ShowName, true); root.UpdateElement("season", episode.GetSeasonNumber(show.Order), true); root.UpdateElement("episode", episode.GetEpisodeNumber(show.Order), true); root.UpdateElement("mpaa", show.CachedShow?.ContentRating, true); //actor(s) and guest actor(s) CachedSeriesInfo s = show.CachedShow; if (s != null) { ReplaceActors(root, episode.AllActors(s)); } } if (episode.FirstAired.HasValue) { root.UpdateElement("aired", episode.FirstAired.Value.ToString("yyyy-MM-dd"), true); } //Director(s) string?epDirector = episode.EpisodeDirector; if (!string.IsNullOrEmpty(epDirector)) { string[] dirs = epDirector.Split('|'); if (dirs.Any()) { root.ReplaceElements("director", dirs); } } //Writers(s) string?epWriter = episode.Writer; if (!string.IsNullOrEmpty(epWriter)) { string[] writers = epWriter.Split('|'); if (writers.Any()) { root.ReplaceElements("credits", writers); } } if (isMultiPart && show != null) { XElement resumeElement = root.GetOrCreateElement("resume"); //we have to put 0 as we don't know where the multipart episode starts/ends resumeElement.UpdateElement("position", 0); resumeElement.UpdateElement("total", 0); //For now we only put art in for multipart episodes. Kodi finds the art appropriately //without our help for the others string filename = TVSettings.Instance.FilenameFriendly(show, episode); string thumbFilename = filename + ".jpg"; UpdateAmongstElements(root, "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", LocalCache.Instance.GetTVDBDownloadURL(episode.GetFilename())) } }
// ReSharper disable once FunctionComplexityOverflow public void Merge([NotNull] CachedSeriesInfo o) { if (o.TvdbCode != TvdbCode && o.TvMazeCode != TvMazeCode) { return; // that's not us! } if (o.TvMazeCode != -1 && TvMazeCode != o.TvMazeCode) { TvMazeCode = o.TvMazeCode; } if (o.TmdbCode != -1 && TmdbCode != o.TmdbCode) { TmdbCode = o.TmdbCode; } if (o.TvdbCode != -1 && TvdbCode != o.TvdbCode) { TvdbCode = o.TvdbCode; } if (o.SrvLastUpdated != 0 && o.SrvLastUpdated < SrvLastUpdated) { return; // older!? } if (!o.IsSearchResultOnly) { IsSearchResultOnly = false; } bool currentLanguageNotSet = LanguageId == -1; string bestLanguageCode = TargetLanguageCode ?? TVSettings.Instance.PreferredLanguageCode; Language optimaLanguage = LocalCache.Instance.GetLanguageFromCode(bestLanguageCode); bool newLanguageOptimal = !(optimaLanguage is null) && o.LanguageId == optimaLanguage.Id; bool useNewDataOverOld = currentLanguageNotSet || newLanguageOptimal; SrvLastUpdated = o.SrvLastUpdated; // take the best bits of "o" // "o" is always newer/better than us, if there is a choice Name = ChooseBetter(Name, useNewDataOverOld, o.Name); AirsDay = ChooseBetter(AirsDay, useNewDataOverOld, o.AirsDay); Imdb = ChooseBetter(Imdb, useNewDataOverOld, o.Imdb); WebUrl = ChooseBetter(WebUrl, useNewDataOverOld, o.WebUrl); OfficialUrl = ChooseBetter(OfficialUrl, useNewDataOverOld, o.OfficialUrl); ShowLanguage = ChooseBetter(ShowLanguage, useNewDataOverOld, o.ShowLanguage); Type = ChooseBetter(Type, useNewDataOverOld, o.Type); Overview = ChooseBetter(Overview, useNewDataOverOld, o.Overview); BannerString = ChooseBetter(BannerString, useNewDataOverOld, o.BannerString); PosterUrl = ChooseBetter(PosterUrl, useNewDataOverOld, o.PosterUrl); Network = ChooseBetter(Network, useNewDataOverOld, o.Network); Runtime = ChooseBetter(Runtime, useNewDataOverOld, o.Runtime); SeriesId = ChooseBetter(SeriesId, useNewDataOverOld, o.SeriesId); Status = ChooseBetterStatus(Status, useNewDataOverOld, o.Status); ContentRating = ChooseBetter(ContentRating, useNewDataOverOld, o.ContentRating); Slug = ChooseBetter(Slug, useNewDataOverOld, o.Slug); if (o.FirstAired.HasValue && (useNewDataOverOld || !FirstAired.HasValue)) { FirstAired = o.FirstAired; } if (useNewDataOverOld && o.SiteRating > 0) { SiteRating = o.SiteRating; } if (useNewDataOverOld && o.SiteRatingVotes > 0) { SiteRatingVotes = o.SiteRatingVotes; } bool useNewAliases = o.Aliases.Any() && useNewDataOverOld; if (!Aliases.Any() || useNewAliases) { Aliases = o.Aliases; } bool useNewGenres = o.Genres.Any() && useNewDataOverOld; if (!Genres.Any() || useNewGenres) { Genres = o.Genres; } bool useNewSeasons = o.seasons.Any() && useNewDataOverOld; if (!seasons.Any() || useNewSeasons) { seasons = o.seasons; } if (o.AirsTime != null) { AirsTime = o.AirsTime; } if (o.sourceEpisodes != null && o.sourceEpisodes.Count != 0) { sourceEpisodes = o.sourceEpisodes; } banners.MergeBanners(o.banners); BannersLoaded = o.BannersLoaded; if (useNewDataOverOld) { LanguageId = o.LanguageId; } Dirty = o.Dirty; }
protected override ActionOutcome UpdateFile() { XDocument doc = XDocument.Load(Where.FullName); XElement? root = doc.Root; if (root is null) { return(new ActionOutcome($"Could not load {Where.FullName}")); } CachedSeriesInfo cachedSeries = SelectedShow !.CachedShow; root.UpdateElement("title", SelectedShow.ShowName); float?showRating = cachedSeries?.SiteRating; if (showRating.HasValue) { UpdateRatings(root, showRating.Value.ToString(CultureInfo.InvariantCulture), cachedSeries.SiteRatingVotes); } 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> XElement episodeGuideNode = root.GetOrCreateElement("episodeguide"); XElement urlNode = episodeGuideNode.GetOrCreateElement("url"); urlNode.UpdateAttribute("post", "yes"); urlNode.UpdateAttribute("cache", "auth.json"); urlNode.SetValue(TheTVDB.API.BuildUrl(SelectedShow.TvdbCode, lang)); if (!(cachedSeries is null)) { root.UpdateElement("originaltitle", SelectedShow.ShowName); UpdateAmongstElements(root, "studio", cachedSeries.Network); root.UpdateElement("id", cachedSeries.TvdbCode); root.UpdateElement("runtime", cachedSeries.Runtime, true); root.UpdateElement("mpaa", cachedSeries.ContentRating, true); root.UpdateElement("premiered", cachedSeries.FirstAired); root.UpdateElement("year", cachedSeries.Year); root.UpdateElement("status", cachedSeries.Status); root.UpdateElement("plot", cachedSeries.Overview); UpdateId(root, "tvdb", "true", cachedSeries.TvdbCode); UpdateId(root, "imdb", "false", cachedSeries.Imdb); } root.ReplaceElements("genre", SelectedShow.Genres); ReplaceActors(root, SelectedShow.Actors); doc.Save(Where.FullName); return(ActionOutcome.Success()); }
private string GetTargetEpisodeName([NotNull] ShowConfiguration show, [NotNull] Episode ep, bool urlEncode) { //note this is for an Episode and not a ProcessedEpisode string name = StyleString; string epname = ep.Name; name = name.ReplaceInsensitive("{ShowName}", show.ShowName); name = name.ReplaceInsensitive("{ShowNameLower}", show.ShowName.ToLower().Replace(' ', '-').RemoveCharactersFrom("()[]{}&$:")); name = name.ReplaceInsensitive("{ShowNameInitial}", show.ShowName.Initial().ToLower()); int seasonNumber; int episodeNumber; switch (show.Order) { case ProcessedSeason.SeasonType.dvd: seasonNumber = ep.DvdSeasonNumber; episodeNumber = ep.DvdEpNum; break; case ProcessedSeason.SeasonType.aired: seasonNumber = ep.AiredSeasonNumber; episodeNumber = ep.AiredEpNum; break; default: throw new ArgumentOutOfRangeException(); } string seasonName = show.CachedShow?.Season(seasonNumber)?.SeasonName; name = name.ReplaceInsensitive("{Season}", seasonNumber.ToString()); name = name.ReplaceInsensitive("{Season:2}", seasonNumber.ToString("00")); name = name.ReplaceInsensitiveLazy("{SeasonNumber}", new Lazy <string?>(() => show.GetSeasonIndex(seasonNumber).ToString()), StringComparison.CurrentCultureIgnoreCase); name = name.ReplaceInsensitiveLazy("{SeasonNumber:2}", new Lazy <string?>(() => show.GetSeasonIndex(seasonNumber).ToString("00")), StringComparison.CurrentCultureIgnoreCase); name = name.ReplaceInsensitive("{Episode}", episodeNumber.ToString("00")); name = name.ReplaceInsensitive("{Episode2}", episodeNumber.ToString("00")); name = Regex.Replace(name, "{AllEpisodes}", episodeNumber.ToString("00")); name = name.ReplaceInsensitive("{SeasonName}", seasonName ?? string.Empty); name = name.ReplaceInsensitive("{EpisodeName}", epname); name = name.ReplaceInsensitive("{Number}", ""); name = name.ReplaceInsensitive("{Number:2}", ""); name = name.ReplaceInsensitive("{Number:3}", ""); name = name.ReplaceInsensitive("{Imdb}", ep.ImdbCode ?? string.Empty); CachedSeriesInfo si = show.CachedShow; name = name.ReplaceInsensitive("{ShowImdb}", si?.Imdb ?? string.Empty); name = name.ReplaceInsensitiveLazy("{Year}", new Lazy <string?>(() => si?.MinYear.ToString() ?? string.Empty), StringComparison.CurrentCultureIgnoreCase); ProcessedSeason selectedProcessedSeason = show.GetSeason(ep.GetSeasonNumber(show.Order)); name = name.ReplaceInsensitive("{SeasonYear}", selectedProcessedSeason != null ? selectedProcessedSeason.MinYear().ToString() : string.Empty); name = ReplaceDates(urlEncode, name, ep.GetAirDateDt(show.GetTimeZone())); name = Regex.Replace(name, "([^\\\\])\\[.*?[^\\\\]\\]", "$1"); // remove optional parts name = name.Replace("\\[", "["); name = name.Replace("\\]", "]"); return(name.Trim()); }