コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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);
        }
コード例 #4
0
ファイル: ShowsHTML.cs プロジェクト: hummigbird1/tvrename
        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>");
        }
コード例 #5
0
ファイル: FinderHelper.cs プロジェクト: SirSparkles/tvrename
        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);
        }
コード例 #6
0
        public Episode(int seriesId, [NotNull] JObject r, CachedSeriesInfo si) : this(seriesId, si)
        {
            // <Episode>
            //  <id>...</id>
            //  blah blah
            // </Episode>

            LoadJson(r);
        }
コード例 #7
0
        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;
            }
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
ファイル: ShowLibrary.cs プロジェクト: cxiong18-matc/tvrename
        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);
        }
コード例 #10
0
ファイル: FinderHelper.cs プロジェクト: SirSparkles/tvrename
        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);
        }
コード例 #11
0
        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));
        }
コード例 #12
0
        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;
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        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));
        }
コード例 #15
0
        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);
        }
コード例 #16
0
        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));
        }
コード例 #17
0
        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();
                }
            }
        }
コード例 #18
0
ファイル: SeriesBanners.cs プロジェクト: hummigbird1/tvrename
 // ReSharper disable once NotNullMemberIsNotInitialized
 public SeriesBanners(CachedSeriesInfo s)
 {
     cachedSeries = s;
     ResetBanners();
 }
コード例 #19
0
        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()))
            }
        }
コード例 #20
0
        // 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;
        }
コード例 #21
0
        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?{&quot;apikey&quot;:&quot;((API-KEY))&quot;,&quot;id&quot;:((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());
        }
コード例 #22
0
        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());
        }