Beispiel #1
0
        public void TestGetEpisodeMetadata()
        {
            EpisodeInfo episodeInfo = new EpisodeInfo()
            {
                Name = "老友记 第一季",
                ParentIndexNumber = 1,
                IndexNumber       = 1,
            };

            episodeInfo.SeriesProviderIds[FrodoUtils.ProviderId] = "1393859";
            var metadataResult = _doubanProvider.GetMetadata(episodeInfo, CancellationToken.None).Result;

            Assert.True(metadataResult.HasMetadata);

            EpisodeInfo episodeInfo2 = new EpisodeInfo()
            {
                Name = "老友记 第一季",
                ParentIndexNumber = 1,
                IndexNumber       = 2,
            };

            episodeInfo2.SeriesProviderIds[FrodoUtils.ProviderId] = "1393859";
            var metadataResult2 = _doubanProvider.GetMetadata(episodeInfo2, CancellationToken.None).Result;

            Assert.True(metadataResult2.HasMetadata);
        }
        private void LoadCommentsList()
        {
            GUIUtils.SetProperty("#Trakt.Items", string.Empty);

            GUIBackgroundTask.Instance.ExecuteInBackgroundAndCallback(() =>
            {
                switch (ShoutType)
                {
                case ShoutTypeEnum.movie:
                    if (MovieInfo == null)
                    {
                        return(null);
                    }
                    GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", MovieInfo.Title);
                    return(GetMovieComments());

                case ShoutTypeEnum.show:
                    if (ShowInfo == null)
                    {
                        return(null);
                    }
                    GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", ShowInfo.Title);
                    return(GetShowComments());

                case ShoutTypeEnum.season:
                    if (SeasonInfo == null)
                    {
                        return(null);
                    }
                    GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", SeasonInfo.Title);
                    return(GetSeasonComments());

                case ShoutTypeEnum.episode:
                    if (EpisodeInfo == null)
                    {
                        return(null);
                    }
                    GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", EpisodeInfo.ToString());
                    return(GetEpisodeComments());

                case ShoutTypeEnum.list:
                    if (ListInfo == null)
                    {
                        return(null);
                    }
                    GUIUtils.SetProperty("#Trakt.Shout.CurrentItem", ListInfo.Name);
                    return(GetListComments());

                default:
                    return(null);
                }
            },
                                                                      delegate(bool success, object result)
            {
                if (success)
                {
                    SendCommentsToFacade(result as IEnumerable <TraktComment>);
                }
            }, Translation.GettingShouts, true);
        }
        public EpisodeInfo GetSeriesFromTags(IDictionary metadata)
        {
            EpisodeInfo episodeInfo = new EpisodeInfo();
            string      tmpString;

            if (TryGet(metadata, TAG_TITLE, out tmpString))
            {
                episodeInfo.SeriesName.Text = tmpString;
            }

            if (TryGet(metadata, TAG_EPISODENAME, out tmpString))
            {
                episodeInfo.EpisodeName.Text = tmpString;
            }

            if (TryGet(metadata, TAG_GENRE, out tmpString))
            {
                episodeInfo.Genres = new List <GenreInfo>(tmpString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Select(s => new GenreInfo {
                    Name = s
                }));
                OnlineMatcherService.Instance.AssignMissingSeriesGenreIds(episodeInfo.Genres);
            }

            episodeInfo.HasChanged = true;
            return(episodeInfo);
        }
Beispiel #4
0
        public override void Update(MediaItem mediaItem)
        {
            base.Update(mediaItem);
            if (mediaItem == null)
            {
                return;
            }

            EpisodeInfo episodeInfo = new EpisodeInfo();

            if (!episodeInfo.FromMetadata(mediaItem.Aspects))
            {
                return;
            }

            Series        = episodeInfo.SeriesName.Text;
            EpisodeName   = episodeInfo.EpisodeName.Text;
            Season        = episodeInfo.SeasonNumber.ToString();
            EpisodeNumber = string.Join(", ", episodeInfo.EpisodeNumbers.Distinct().OrderBy(e => e));
            if (episodeInfo.DvdEpisodeNumbers.Count > 0)
            {
                DVDEpisodeNumber = string.Join(", ", episodeInfo.DvdEpisodeNumbers.Distinct().OrderBy(e => e));
            }
            else
            {
                DVDEpisodeNumber = EpisodeNumber;
            }

            // Use the short string without series name here
            SimpleTitle = episodeInfo.ToShortString();
            StoryPlot   = episodeInfo.Summary.Text;
            FireChange();
        }
Beispiel #5
0
        public EpisodeInfo GetSeriesFromTags(IDictionary metadata)
        {
            EpisodeInfo episodeInfo = new EpisodeInfo();
            string      tmpString;

            if (TryGet(metadata, TAG_TITLE, out tmpString))
            {
                episodeInfo.SeriesName.Text = tmpString;
            }

            if (TryGet(metadata, TAG_EPISODENAME, out tmpString))
            {
                episodeInfo.EpisodeName.Text = tmpString;
            }

            if (TryGet(metadata, TAG_GENRE, out tmpString))
            {
                episodeInfo.Genres = new List <GenreInfo>(tmpString.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Select(s => new GenreInfo {
                    Name = s.Trim()
                }));
                IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>();
                foreach (var genre in episodeInfo.Genres)
                {
                    if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Series, null, out int genreId))
                    {
                        genre.Id = genreId;
                    }
                }
            }

            episodeInfo.HasChanged = true;
            return(episodeInfo);
        }
Beispiel #6
0
        private async Task <EpisodeInfo> CreateEpisodeInfo(Episode episode, string episodeId = null)
        {
            if (episode == null)
            {
                return(null);
            }
            if (string.IsNullOrEmpty(episodeId))
            {
                episodeId = episode.IDs.ID.ToString();
            }
            var         cacheKey = $"episode:{episodeId}";
            EpisodeInfo info     = null;

            if (DataCache.TryGetValue <EpisodeInfo>(cacheKey, out info))
            {
                return(info);
            }
            var aniDB = (await ShokoAPI.GetEpisodeAniDb(episodeId));

            info = new EpisodeInfo
            {
                Id        = episodeId,
                ExtraType = GetExtraType(aniDB),
                Shoko     = (await ShokoAPI.GetEpisode(episodeId)),
                AniDB     = aniDB,
                TvDB      = ((await ShokoAPI.GetEpisodeTvDb(episodeId))?.FirstOrDefault()),
            };
            DataCache.Set <EpisodeInfo>(cacheKey, info, DefaultTimeSpan);
            return(info);
        }
        public ImageKey[] BuildImageKeysToDown()
        {
            List <ImageKey> list          = new List <ImageKey>();
            int             lastEpisodeNo = webtoonInfo.GetLastEpisodeNo();

            for (int episodeNo = 1; episodeNo <= lastEpisodeNo; episodeNo++)
            {
                if (!webtoonInfo.Episodes.ContainsKey(episodeNo))
                {
                    continue;
                }
                EpisodeInfo episodeInfo = webtoonInfo.Episodes[episodeNo];
                string[]    imageUrls   = episodeInfo.EpisodeImageUrls;
                for (int imageIndex = 0; imageIndex < imageUrls.Length; imageIndex++)
                {
                    ImageKey imageKey = new ImageKey(webtoonInfo.WebtoonTitleId, episodeNo, imageIndex);
                    if (File.Exists(fileNameBuilder.BuildImageFileFullPath(imageKey)))
                    {
                        continue;
                    }
                    list.Add(imageKey);
                }
            }
            return(list.ToArray());
        }
        public async Task <MetadataResult <Episode> > GetMetadata(EpisodeInfo info,
                                                                  CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Douban:GetMetadata for episode {info.Name}");
            var result = new MetadataResult <Episode>();

            if (info.IsMissingEpisode)
            {
                _logger.LogInformation("Do not support MissingEpisode");
                return(result);
            }

            info.SeriesProviderIds.TryGetValue(ProviderID, out string sid);
            if (string.IsNullOrEmpty(sid))
            {
                _logger.LogInformation("No douban sid found, just skip");
                return(result);
            }

            if (!info.IndexNumber.HasValue)
            {
                _logger.LogInformation("No episode num found, please check " +
                                       "the format of file name");
                return(result);
            }
            // Start to get information from douban
            result.Item = new Episode
            {
                Name              = info.Name,
                IndexNumber       = info.IndexNumber,
                ParentIndexNumber = info.ParentIndexNumber
            };

            var url = String.Format("https://movie.douban.com/subject/{0}" +
                                    "/episode/{1}/", sid, info.IndexNumber);
            String content = await _doubanAccessor.GetResponseWithDelay(url, cancellationToken);

            String pattern_name = "data-name=\\\"(.*?)\\\"";
            Match  match        = Regex.Match(content, pattern_name);

            if (match.Success)
            {
                var name = match.Groups[1].Value;
                _logger.LogDebug("The name is {0}", name);
                result.Item.Name = name;
            }

            String pattern_desc = "data-desc=\\\"(.*?)\\\"";

            match = Regex.Match(content, pattern_desc);
            if (match.Success)
            {
                var desc = match.Groups[1].Value;
                _logger.LogDebug("The desc is {0}", desc);
                result.Item.Overview = desc;
            }
            result.HasMetadata = true;

            return(result);
        }
Beispiel #9
0
        public Task <MetadataResult <Episode> > GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
        {
            var metadataResult = Try(() =>
            {
                var result = _mediaItemProcessor.GetResultAsync(info, MediaItemTypes.Episode, GetParentIds(info));

                return(result.Map(either =>
                                  either.Match(r =>
                {
                    _log.Info($"Found data for episode '{info.Name}': '{r.EmbyMetadataResult.Item.Name}'");

                    info.IndexNumber = null;
                    info.ParentIndexNumber = null;
                    info.Name = "";
                    info.ProviderIds = new Dictionary <string, string>();

                    return r.EmbyMetadataResult;
                },
                                               failure =>
                {
                    _log.Error($"Failed to get data for episode '{info.Name}': {failure.Reason}");

                    return EmptyMetadataResult;
                })
                                  ));
            })
                                 .IfFail(e =>
            {
                _log.ErrorException($"Failed to get data for episode '{info.Name}'", e);

                return(EmptyMetadataResult.AsTask());
            });

            return(metadataResult);
        }
        public IDictionary <Guid, IList <MediaItemAspect> > GetBaseChildAspectsFromExistingAspects(IDictionary <Guid, IList <MediaItemAspect> > existingChildAspects, IDictionary <Guid, IList <MediaItemAspect> > existingParentAspects)
        {
            if (existingParentAspects.ContainsKey(SeriesAspect.ASPECT_ID))
            {
                SeriesInfo series = new SeriesInfo();
                series.FromMetadata(existingParentAspects);

                if (existingChildAspects.ContainsKey(SeasonAspect.ASPECT_ID))
                {
                    SeasonInfo season = new SeasonInfo();
                    season.FromMetadata(existingChildAspects);

                    SeasonInfo basicSeason = series.CloneBasicInstance <SeasonInfo>();
                    basicSeason.SeasonNumber = season.SeasonNumber;
                    IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                    basicSeason.SetMetadata(aspects, true);
                    return(aspects);
                }
                else if (existingChildAspects.ContainsKey(EpisodeAspect.ASPECT_ID))
                {
                    EpisodeInfo episode = new EpisodeInfo();
                    episode.FromMetadata(existingChildAspects);

                    EpisodeInfo basicEpisode = series.CloneBasicInstance <EpisodeInfo>();
                    basicEpisode.SeasonNumber   = episode.SeasonNumber;
                    basicEpisode.EpisodeNumbers = episode.EpisodeNumbers.ToList();
                    IDictionary <Guid, IList <MediaItemAspect> > aspects = new Dictionary <Guid, IList <MediaItemAspect> >();
                    basicEpisode.SetMetadata(aspects, true);
                    return(aspects);
                }
            }
            return(null);
        }
            public void Setup()
            {
                _episodeInfo = new EpisodeInfo
                {
                    Name              = "EpisodeName",
                    IndexNumber       = 3,
                    ParentIndexNumber = 1,
                    ProviderIds       = new Dictionary <string, string>
                    {
                        { "Source", "66" }
                    }
                };
                _mediaItemProcessorResult = Left <ProcessFailedResult, IMetadataFoundResult <Episode> >(
                    new ProcessFailedResult("FailedSource",
                                            "MediaItemName", MediaItemTypes.Episode, "Failure reason"));

                _mediaItemProcessor = Substitute.For <IMediaItemProcessor>();
                _mediaItemProcessor.GetResultAsync(_episodeInfo, MediaItemTypes.Episode,
                                                   Arg.Any <IEnumerable <EmbyItemId> >())
                .Returns(x => _mediaItemProcessorResult);

                _logManager = Substitute.For <ILogManager>();

                _logger = Substitute.For <ILogger>();
                _logger.WhenForAnyArgs(l => l.Debug(null, null)).Do(c => Console.WriteLine($"Debug: {c.Arg<string>()}"));

                _logManager.GetLogger("EpisodeProvider").Returns(_logger);

                _episodeProvider = new EpisodeProvider(_logManager, _mediaItemProcessor);
            }
Beispiel #12
0
        /// <summary>
        /// Gets the new path.
        /// </summary>
        /// <param name="sourcePath">The source path.</param>
        /// <param name="series">The series.</param>
        /// <param name="seasonNumber">The season number.</param>
        /// <param name="episodeNumber">The episode number.</param>
        /// <param name="endingEpisodeNumber">The ending episode number.</param>
        /// <param name="options">The options.</param>
        /// <returns>System.String.</returns>
        private async Task <string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int?endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken)
        {
            var episodeInfo = new EpisodeInfo
            {
                IndexNumber         = episodeNumber,
                IndexNumberEnd      = endingEpisodeNumber,
                MetadataCountryCode = series.GetPreferredMetadataCountryCode(),
                MetadataLanguage    = series.GetPreferredMetadataLanguage(),
                ParentIndexNumber   = seasonNumber,
                SeriesProviderIds   = series.ProviderIds
            };

            var searchResults = await _providerManager.GetRemoteSearchResults <Episode, EpisodeInfo>(new RemoteSearchQuery <EpisodeInfo>
            {
                SearchInfo = episodeInfo
            }, cancellationToken).ConfigureAwait(false);

            var episode = searchResults.FirstOrDefault();

            if (episode == null)
            {
                _logger.Warn("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
                return(null);
            }

            var newPath = GetSeasonFolderPath(series, seasonNumber, options);

            var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);

            newPath = Path.Combine(newPath, episodeFileName);

            return(newPath);
        }
 private static void CompareMembers(EpisodeInfo a, EpisodeInfo b)
 {
     Assert.AreEqual(a.Name, b.Name);
     Assert.True(a.Season == b.Season);
     Assert.True(a.Episode == b.Episode);
     Assert.True((bool)a == (bool)b);
 }
Beispiel #14
0
        protected override async Task <bool> ExtractMetadataAsync(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode)
        {
            if (!CanExtract(lfsra, extractedAspectData))
            {
                return(false);
            }
            if (extractedAspectData.ContainsKey(EpisodeAspect.ASPECT_ID))
            {
                return(false);
            }

            // Handle series information
            EpisodeInfo episodeInfo = new EpisodeInfo();

            using (var rec = new MCRecMetadataEditor(lfsra.LocalFileSystemPath))
            {
                IDictionary tags = rec.GetAttributes();
                episodeInfo = GetSeriesFromTags(tags);
            }

            if (episodeInfo.IsBaseInfoPresent)
            {
                if (!forceQuickMode)
                {
                    await OnlineMatcherService.Instance.FindAndUpdateEpisodeAsync(episodeInfo).ConfigureAwait(false);
                }
                if (episodeInfo.IsBaseInfoPresent)
                {
                    episodeInfo.SetMetadata(extractedAspectData);
                }
            }
            return(episodeInfo.IsBaseInfoPresent);
        }
        public (int downloadedImageCount, long downloadedImagesSize) GetDownloadedImagesInformation()
        {
            WebtoonKey webtoonKey  = new WebtoonKey(webtoonInfo.WebtoonTitleId);
            int        count       = 0;
            long       size        = 0;
            int        lastEpisode = webtoonInfo.GetLastEpisodeNo();

            for (int episodeNo = 1; episodeNo <= lastEpisode; episodeNo++)
            {
                if (!webtoonInfo.Episodes.ContainsKey(episodeNo))
                {
                    continue;
                }
                EpisodeInfo episodeInfo = webtoonInfo.Episodes[episodeNo];
                string[]    imageUrls   = episodeInfo.EpisodeImageUrls;
                for (int imageIndex = 0; imageIndex < imageUrls.Length; imageIndex++)
                {
                    ImageKey imageKey = new ImageKey(webtoonInfo.WebtoonTitleId, episodeNo, imageIndex);
                    if (File.Exists(fileNameBuilder.BuildImageFileFullPath(imageKey)))
                    {
                        count++;
                        size += new FileInfo(fileNameBuilder.BuildImageFileFullPath(imageKey)).Length;
                    }
                }
            }
            return(count, size);
        }
Beispiel #16
0
        public async Task <IEnumerable <EpisodeInfo> > FindMatchingEpisodesAsync(EpisodeInfo episodeInfo, string category)
        {
            var tasks = SERIES_MATCHERS.Where(m => category == null || m.Key == category).SelectMany(m => m.Value).Where(m => m.Enabled)
                        .Select(m => m.FindMatchingEpisodesAsync(episodeInfo)).ToList();

            //Merge results
            return(await MergeResults(tasks).ConfigureAwait(false));
        }
 public Task <IEnumerable <RemoteSearchResult> > GetSearchResults(
     EpisodeInfo info, CancellationToken cancellationToken)
 {
     _logger.LogInformation("Douban:Search for episode {0}", info.Name);
     // It's needless for season to do search
     return(Task.FromResult <IEnumerable <RemoteSearchResult> >(
                new List <RemoteSearchResult>()));
 }
        public async Task <IEnumerable <EpisodeInfo> > FindMatchingEpisodesAsync(EpisodeInfo episodeInfo)
        {
            var tasks = SERIES_MATCHERS.Where(m => m.Enabled)
                        .Select(m => m.FindMatchingEpisodesAsync(episodeInfo)).ToList();

            //Merge results
            return(await MergeResults(tasks).ConfigureAwait(false));
        }
 public override bool UpdateFromOnlineSeriesEpisode(EpisodeInfo episode, string language, bool cacheOnly)
 {
     if (episode.SeriesTvdbId > 0)
     {
         return(true);
     }
     return(false);
 }
Beispiel #20
0
        /// <summary>
        /// Get index number for a movie in a box-set.
        /// </summary>
        /// <returns>Absoute index.</returns>
        public static int GetMovieIndexNumber(GroupInfo group, SeriesInfo series, EpisodeInfo episode)
        {
            switch (Plugin.Instance.Configuration.BoxSetGrouping)
            {
            default:
            case GroupType.Default:
                return(1);

            case GroupType.ShokoSeries:
                return(episode.AniDB.EpisodeNumber);

            case GroupType.ShokoGroup: {
                int offset = 0;
                foreach (SeriesInfo s in group.SeriesList)
                {
                    var sizes = s.Shoko.Sizes.Total;
                    if (s != series)
                    {
                        if (episode.AniDB.Type == EpisodeType.Special)
                        {
                            var index = series.FilteredSpecialEpisodesList.FindIndex(e => string.Equals(e.Id, episode.Id));
                            if (index == -1)
                            {
                                throw new System.IndexOutOfRangeException("Episode not in filtered list");
                            }
                            return(offset - (index + 1));
                        }
                        switch (episode.AniDB.Type)
                        {
                        case EpisodeType.Normal:
                            // offset += 0; // it's not needed, so it's just here as a comment instead.
                            break;

                        case EpisodeType.Parody:
                            offset += sizes?.Episodes ?? 0;
                            goto case EpisodeType.Normal;

                        case EpisodeType.Other:
                            offset += sizes?.Parodies ?? 0;
                            goto case EpisodeType.Parody;
                        }
                        return(offset + episode.AniDB.EpisodeNumber);
                    }
                    else
                    {
                        if (episode.AniDB.Type == EpisodeType.Special)
                        {
                            offset -= series.FilteredSpecialEpisodesList.Count;
                        }
                        offset += (sizes?.Episodes ?? 0) + (sizes?.Parodies ?? 0) + (sizes?.Others ?? 0);
                    }
                }
                break;
            }
            }
            return(0);
        }
 protected override bool SetSeriesEpisodeId(EpisodeInfo episode, string id)
 {
     if (!string.IsNullOrEmpty(id))
     {
         episode.ImdbId = id;
         return(true);
     }
     return(false);
 }
        /// <inheritdoc />
        public async Task <IEnumerable <RemoteImageInfo> > GetImages(BaseItem item, CancellationToken cancellationToken)
        {
            var episode     = (Episode)item;
            var series      = episode.Series;
            var imageResult = new List <RemoteImageInfo>();
            var language    = item.GetPreferredMetadataLanguage();

            if (series != null && TvdbSeriesProvider.IsValidSeries(series.ProviderIds))
            {
                // Process images
                try
                {
                    string?episodeTvdbId = null;

                    if (episode.IndexNumber.HasValue && episode.ParentIndexNumber.HasValue)
                    {
                        var episodeInfo = new EpisodeInfo
                        {
                            IndexNumber        = episode.IndexNumber.Value,
                            ParentIndexNumber  = episode.ParentIndexNumber.Value,
                            SeriesProviderIds  = series.ProviderIds,
                            SeriesDisplayOrder = series.DisplayOrder
                        };

                        episodeTvdbId = await _tvdbClientManager
                                        .GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false);
                    }

                    if (string.IsNullOrEmpty(episodeTvdbId))
                    {
                        _logger.LogError(
                            "Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}",
                            episode.ParentIndexNumber,
                            episode.IndexNumber,
                            series.GetProviderId(TvdbPlugin.ProviderId));
                        return(imageResult);
                    }

                    var episodeResult =
                        await _tvdbClientManager
                        .GetEpisodesAsync(Convert.ToInt32(episodeTvdbId, CultureInfo.InvariantCulture), language, cancellationToken)
                        .ConfigureAwait(false);

                    var image = GetImageInfo(episodeResult.Data);
                    if (image != null)
                    {
                        imageResult.Add(image);
                    }
                }
                catch (TvDbServerException e)
                {
                    _logger.LogError(e, "Failed to retrieve episode images for series {TvDbId}", series.GetProviderId(TvdbPlugin.ProviderId));
                }
            }

            return(imageResult);
        }
 protected override bool GetSeriesEpisodeId(EpisodeInfo episode, out string id)
 {
     id = null;
     if (!string.IsNullOrEmpty(episode.ImdbId))
     {
         id = episode.ImdbId;
     }
     return(id != null);
 }
Beispiel #24
0
        public override bool HasSearchableIds(EpisodeInfo episode)
        {
            if (episode.SeriesTvMazeId > 0 || episode.SeriesTvdbId > 0 || !string.IsNullOrWhiteSpace(episode.SeriesImdbId))
            {
                return(true);
            }

            return(base.HasSearchableIds(episode));
        }
Beispiel #25
0
        public MovieModel(MovieInfo info, EpisodeInfo lastWatched)
        {
            MarkWatchedCommand = new DelegateCommand <EpisodeModel>(OnMarkWatchedCommand);
            _info = info;

            FillEpisodesInfo();

            SetLastWatched(lastWatched == null ? null : _episodes.FirstOrDefault(e => e.Season == lastWatched.Season && e.Episode == lastWatched.Episode));
        }
 protected override bool SetSeriesEpisodeId(EpisodeInfo episode, string id)
 {
     if (!string.IsNullOrEmpty(id))
     {
         episode.TvMazeId = Convert.ToInt32(id);
         return(true);
     }
     return(false);
 }
 protected override bool GetSeriesEpisodeId(EpisodeInfo episode, out string id)
 {
     id = null;
     if (episode.TvMazeId > 0)
     {
         id = episode.TvMazeId.ToString();
     }
     return(id != null);
 }
        public EpisodeInfo GetSeriesFromTags(Argus.Recording recording)
        {
            EpisodeInfo episodeInfo = new EpisodeInfo {
                SeriesName = recording.Title
            };

            if (recording.SeriesNumber.HasValue)
            {
                episodeInfo.SeasonNumber = recording.SeriesNumber.Value;
            }

            if (recording.EpisodeNumber.HasValue)
            {
                episodeInfo.EpisodeNumbers.Add(recording.EpisodeNumber.Value);
            }

            if (!episodeInfo.IsBaseInfoPresent)
            {
                // Check for formatted display value, i.e.:
                // <EpisodeNumberDisplay>1.4</EpisodeNumberDisplay>
                if (!string.IsNullOrWhiteSpace(recording.EpisodeNumberDisplay))
                {
                    var parts = recording.EpisodeNumberDisplay.Split('.');
                    if (parts.Length == 2)
                    {
                        int val;
                        if (int.TryParse(parts[0], out val))
                        {
                            episodeInfo.SeasonNumber = val;
                        }
                        if (int.TryParse(parts[1], out val))
                        {
                            episodeInfo.EpisodeNumbers.Add(val);
                        }
                    }
                }
            }

            if (!string.IsNullOrEmpty(recording.Category?.Trim()))
            {
                episodeInfo.Genres.Add(new GenreInfo {
                    Name = recording.Category.Trim()
                });
                IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>();
                foreach (var genre in episodeInfo.Genres)
                {
                    if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Series, null, out int genreId))
                    {
                        genre.Id = genreId;
                    }
                }
            }

            episodeInfo.HasChanged = true;
            return(episodeInfo);
        }
        public void StandardShownameTestWithX()
        {
            var expectedShowDetails  = new EpisodeInfo("Arrow", 1, 2);
            var incorrectShowDetails = new EpisodeInfo("Arrow", 2, 1);
            var returnedShowDetails  = FileCategorizer.GetFileInfo(DefaultShownameWithX);

            CompareMembers(expectedShowDetails, returnedShowDetails);
            Assert.AreEqual(expectedShowDetails, returnedShowDetails);
            Assert.AreNotEqual(incorrectShowDetails, returnedShowDetails);
        }
        public async Task <bool> UpdateEpisodeCharactersAsync(EpisodeInfo episodeInfo)
        {
            bool success = false;

            foreach (ISeriesMatcher matcher in SERIES_MATCHERS.Where(m => m.Enabled))
            {
                success |= await matcher.UpdateEpisodeCharactersAsync(episodeInfo).ConfigureAwait(false);
            }
            return(success);
        }