示例#1
0
        public void TestNfoMovieReaderReadMetadata()
        {
            //Arrange
            var resourceProviders = new Dictionary <Guid, IResourceProvider>();

            resourceProviders.Add(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, new LocalFsResourceProvider());
            var mockMediaAccessor = new Mock <IMediaAccessor>();

            ServiceRegistration.Set <IMediaAccessor>(mockMediaAccessor.Object);
            mockMediaAccessor.Setup(x => x.LocalResourceProviders).Returns(resourceProviders);

            Mock <IFileSystemResourceAccessor> mockRA = new Mock <IFileSystemResourceAccessor>();

            mockRA.Setup(r => r.OpenReadAsync()).Returns(Task.FromResult(
                                                             Assembly.GetExecutingAssembly().GetManifestResourceStream("Tests.Server.NfoMetadataExtractor.TestData.MovieNfo.movie.nfo")));
            mockRA.SetupGet(t => t.CanonicalLocalResourcePath).Returns(ResourcePath.BuildBaseProviderPath(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, @"TestData\MovieNfo\movie.nfo"));
            NfoMovieReader reader = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, false, false, false, null, new NfoMovieMetadataExtractorSettings());

            //Act
            reader.TryReadMetadataAsync(mockRA.Object).Wait();
            var stubs = reader.GetMovieStubs();

            //Assert
            Assert.NotNull(stubs);
            Assert.AreEqual(1, stubs.Count);
            var stub = stubs[0];

            Assert.NotNull(stub);
            Assert.AreEqual("The Lego Batman Movie", stub.Title);
            Assert.AreEqual("The Lego Batman Movie", stub.OriginalTitle);
            Assert.AreEqual(7.2m, stub.Rating);
            Assert.AreEqual(new DateTime(2017, 1, 1), stub.Year);
            Assert.AreEqual(1853, stub.Votes);
            Assert.AreEqual("In the irreverent spirit of fun that made “The Lego Movie” a worldwide phenomenon, the self-described leading man of that ensemble—Lego Batman—stars in his own big-screen adventure. But there are big changes...", stub.Outline);
            Assert.AreEqual("In the irreverent spirit of fun that made “The Lego Movie” a worldwide phenomenon, the self-described leading man of that ensemble—Lego Batman—stars in his own big-screen adventure. But there are big changes brewing in Gotham, and if he wants to save the city from The Joker’s hostile takeover, Batman may have to drop the lone vigilante thing, try to work with others and maybe, just maybe, learn to lighten up.", stub.Plot);
            Assert.AreEqual("Always be yourself. Unless you can be Batman.", stub.Tagline);
            Assert.AreEqual(TimeSpan.FromMinutes(104), stub.Runtime);
            CollectionAssert.AreEqual(new[] { "UK:U" }, stub.Mpaa);
            CollectionAssert.AreEqual(new[] { "UK:U" }, stub.Certification);
            Assert.AreEqual("tt4116284", stub.Id);
            Assert.AreEqual(324849, stub.TmdbId);
            CollectionAssert.AreEqual(new[] { "Denmark", "United States" }, stub.Countries);
            Assert.AreEqual(false, stub.Watched);
            Assert.AreEqual(0, stub.PlayCount);
            CollectionAssert.AreEqual(new[] { "Action", "Animation", "Comedy", "Family", "Fantasy" }, stub.Genres);
            CollectionAssert.AreEqual(new[] { "Lin Pictures", "Warner Bros. Animation", "Warner Bros.", "Animal Logic", "DC Entertainment", "Lord Miller", "LEGO System A", "S" }, stub.Studios);
            CollectionAssert.AreEqual(new[] { "Chris McKenna", "Erik Sommers", "Seth Grahame-Smith", "Jared Stern", "John Whittington" }, stub.Credits);
            Assert.AreEqual("Chris McKay", stub.Director);
            CollectionAssert.AreEqual(new[] { "English" }, stub.Languages);
        }
示例#2
0
        /// <summary>
        /// Asynchronously creates an <see cref="NfoMovieReader"/> for the given <param name="mediaItemAccessor"></param>
        /// </summary>
        /// <param name="mediaItemAccessor">Points to the resource for which we try to create an NfoMovieReader</param>
        /// <returns>An NfoMovieReader if an nfo file was found, else <c>null</c></returns>
        protected async Task <NfoMovieReader> TryGetNfoMovieReaderAsync(IResourceAccessor mediaItemAccessor)
        {
            // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier.
            // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries
            // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry.
            var miNumber = Interlocked.Increment(ref _lastMediaItemNumber);

            try
            {
                _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}'", miNumber, mediaItemAccessor);

                // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor.
                // Otherwise it is not possible to find a nfo-file in the MediaItem's directory.
                if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber);
                    return(null);
                }

                // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file.
                // If we don't find one, we cannot extract any metadata.
                IFileSystemResourceAccessor nfoFsra;
                if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra))
                {
                    return(null);
                }

                // Now we (asynchronously) extract the metadata into a stub object.
                // If there is an error parsing the nfo-file with XmlNfoReader, we at least try to parse for a valid IMDB-ID.
                // If no metadata was found, nothing can be stored in the MediaItemAspects.
                NfoMovieReader nfoReader = new NfoMovieReader(_debugLogger, miNumber, false, false, false, _httpClient, _settings);
                using (nfoFsra)
                {
                    if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false) &&
                        !await nfoReader.TryParseForImdbId(nfoFsra).ConfigureAwait(false))
                    {
                        _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber);
                        return(null);
                    }
                    return(nfoReader);
                }
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor);
                _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber);
            }
            return(null);
        }
示例#3
0
        /// <summary>
        /// Asynchronously tries to extract movie characters for the given <param name="mediaItemAccessor"></param>
        /// </summary>
        /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param>
        /// <param name="extractedAspects">List of MediaItemAspect dictionaries to update with metadata</param>
        /// <param name="reimport">During reimport only allow if nfo is for same media as this</param>
        /// <returns><c>true</c> if metadata was found and stored into the <paramref name="extractedAspects"/>, else <c>false</c></returns>
        protected async Task <bool> TryExtractMovieCharactersMetadataAsync(IResourceAccessor mediaItemAccessor, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedAspects, MovieInfo reimport)
        {
            NfoMovieReader movieNfoReader = await TryGetNfoMovieReaderAsync(mediaItemAccessor, false).ConfigureAwait(false);

            if (movieNfoReader != null)
            {
                if (reimport != null && !VerifyMovieReimport(movieNfoReader, reimport))
                {
                    return(false);
                }

                return(movieNfoReader.TryWriteCharacterMetadata(extractedAspects));
            }
            return(false);
        }
示例#4
0
        public void TestNfoMovieReaderWriteActorMetadata()
        {
            //Arrange
            IList <PersonStub> actors    = CreateTestActors();
            MovieStub          movieStub = CreateTestMovieStub(actors);
            NfoMovieReader     reader    = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, true, false, false, null, new NfoMovieMetadataExtractorSettings());

            reader.GetMovieStubs().Add(movieStub);

            //Act
            IList <IDictionary <Guid, IList <MediaItemAspect> > > aspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >();

            reader.TryWriteActorMetadata(aspects);

            //Assert
            Assert.AreEqual(2, aspects.Count);
            MediaItemAspect personAspect0 = MediaItemAspect.GetAspect(aspects[0], PersonAspect.Metadata);

            Assert.NotNull(personAspect0);
            Assert.AreEqual(actors[0].Name, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_PERSON_NAME));
            Assert.AreEqual(actors[0].Biography, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_BIOGRAPHY));
            Assert.AreEqual(actors[0].Birthdate, personAspect0.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFBIRTH));
            Assert.AreEqual(actors[0].Deathdate, personAspect0.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFDEATH));
            Assert.AreEqual(PersonAspect.OCCUPATION_ACTOR, personAspect0.GetAttributeValue <string>(PersonAspect.ATTR_OCCUPATION));
            IList <MediaItemAspect> externalIdentifiers0;

            Assert.IsTrue(aspects[0].TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers0));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers0, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_PERSON, actors[0].ImdbId));

            MediaItemAspect personAspect1 = MediaItemAspect.GetAspect(aspects[1], PersonAspect.Metadata);

            Assert.NotNull(personAspect1);
            Assert.AreEqual(actors[1].Name, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_PERSON_NAME));
            Assert.AreEqual(actors[1].Biography, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_BIOGRAPHY));
            Assert.AreEqual(actors[1].Birthdate, personAspect1.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFBIRTH));
            Assert.AreEqual(actors[1].Deathdate, personAspect1.GetAttributeValue <DateTime?>(PersonAspect.ATTR_DATEOFDEATH));
            Assert.AreEqual(PersonAspect.OCCUPATION_ACTOR, personAspect1.GetAttributeValue <string>(PersonAspect.ATTR_OCCUPATION));
            IList <MediaItemAspect> externalIdentifiers1;

            Assert.IsTrue(aspects[1].TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers1));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers1, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_PERSON, actors[1].ImdbId));
        }
示例#5
0
        /// <summary>
        /// Verifies if the movie being reimported matches the movie in the nfo file
        /// </summary>
        /// <param name="reader">Reader used read the movie information from the nfo file</param>
        /// <param name="reimport">The movie being reimported</param>
        /// <returns>Result of the verification</returns>
        protected bool VerifyMovieReimport(NfoMovieReader reader, MovieInfo reimport)
        {
            if (reimport == null)
            {
                return(true);
            }

            IDictionary <Guid, IList <MediaItemAspect> > aspectData = new Dictionary <Guid, IList <MediaItemAspect> >();

            if (reader.TryWriteMetadata(aspectData))
            {
                MovieInfo info = new MovieInfo();
                info.FromMetadata(aspectData);
                if (reimport.Equals(info))
                {
                    return(true);
                }
            }
            return(false);
        }
示例#6
0
        public void TestNfoMovieReaderWriteMetadata()
        {
            //Arrange
            MovieStub      movieStub       = CreateTestMovieStub(CreateTestActors());
            NfoMovieReader readerVideoOnly = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, true, false, false, null, new NfoMovieMetadataExtractorSettings());

            readerVideoOnly.GetMovieStubs().Add(movieStub);
            NfoMovieReader readerMovieOnly = new NfoMovieReader(new ConsoleLogger(LogLevel.All, true), 1, false, false, false, null, new NfoMovieMetadataExtractorSettings());

            readerMovieOnly.GetMovieStubs().Add(movieStub);

            //Act
            IDictionary <Guid, IList <MediaItemAspect> > aspectsVideoOnly = new Dictionary <Guid, IList <MediaItemAspect> >();

            readerVideoOnly.TryWriteMetadata(aspectsVideoOnly);
            IDictionary <Guid, IList <MediaItemAspect> > aspectsMovieOnly = new Dictionary <Guid, IList <MediaItemAspect> >();

            readerMovieOnly.TryWriteMetadata(aspectsMovieOnly);

            //Assert

            //Video aspects only
            MediaItemAspect mediaAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, MediaAspect.Metadata);

            Assert.NotNull(mediaAspect);
            Assert.AreEqual(movieStub.Title, mediaAspect.GetAttributeValue <string>(MediaAspect.ATTR_TITLE));
            Assert.AreEqual(movieStub.SortTitle, mediaAspect.GetAttributeValue <string>(MediaAspect.ATTR_SORT_TITLE));
            Assert.AreEqual(movieStub.Premiered, mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_RECORDINGTIME));
            Assert.AreEqual(movieStub.PlayCount, mediaAspect.GetAttributeValue <int?>(MediaAspect.ATTR_PLAYCOUNT));
            Assert.AreEqual(movieStub.LastPlayed, mediaAspect.GetAttributeValue <DateTime?>(MediaAspect.ATTR_LASTPLAYED));

            MediaItemAspect videoAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, VideoAspect.Metadata);

            Assert.NotNull(videoAspect);
            Assert.AreEqual(movieStub.Plot, videoAspect.GetAttributeValue <string>(VideoAspect.ATTR_STORYPLOT));
            CollectionAssert.AreEqual(movieStub.Actors.OrderBy(p => p.Order).Select(p => p.Name), videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS));
            Assert.AreEqual(movieStub.Director, videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_DIRECTORS).First());
            CollectionAssert.AreEqual(movieStub.Credits, videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_WRITERS));

            //ToDo: Rework Genre Mapper to make it testable, currently depends on IPathManager/language files!
            //IList<MediaItemAspect> genreAspects;
            //Assert.IsTrue(aspects.TryGetValue(GenreAspect.ASPECT_ID, out genreAspects));
            //CollectionAssert.AreEqual(movieStub.Genres, genreAspects.Select(g => g.GetAttributeValue<string>(GenreAspect.ATTR_GENRE)));

            MediaItemAspect thumbnailAspect = MediaItemAspect.GetAspect(aspectsVideoOnly, ThumbnailLargeAspect.Metadata);

            Assert.NotNull(thumbnailAspect);
            CollectionAssert.AreEqual(movieStub.Thumb, thumbnailAspect.GetAttributeValue <byte[]>(ThumbnailLargeAspect.ATTR_THUMBNAIL));

            //Movie aspects only
            MediaItemAspect movieAspect = MediaItemAspect.GetAspect(aspectsMovieOnly, MovieAspect.Metadata);

            Assert.NotNull(movieAspect);
            CollectionAssert.AreEqual(movieStub.Companies, movieAspect.GetCollectionAttribute <string>(MovieAspect.ATTR_COMPANIES));
            Assert.AreEqual(movieStub.Title, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_MOVIE_NAME));
            Assert.AreEqual(movieStub.OriginalTitle, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_ORIG_MOVIE_NAME));
            Assert.AreEqual(movieStub.Sets.OrderBy(set => set.Order).First().Name, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_COLLECTION_NAME));
            Assert.AreEqual((int)movieStub.Runtime.Value.TotalMinutes, movieAspect.GetAttributeValue <int?>(MovieAspect.ATTR_RUNTIME_M));
            Assert.AreEqual("US_PG", movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_CERTIFICATION));
            Assert.AreEqual(movieStub.Tagline, movieAspect.GetAttributeValue <string>(MovieAspect.ATTR_TAGLINE));
            Assert.AreEqual((double)movieStub.Rating, movieAspect.GetAttributeValue <double?>(MovieAspect.ATTR_TOTAL_RATING));
            Assert.AreEqual(movieStub.Votes, movieAspect.GetAttributeValue <int?>(MovieAspect.ATTR_RATING_COUNT));

            IList <MediaItemAspect> externalIdentifiers;

            Assert.IsTrue(aspectsMovieOnly.TryGetValue(ExternalIdentifierAspect.ASPECT_ID, out externalIdentifiers));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.TmdbId.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_TMDB, ExternalIdentifierAspect.TYPE_COLLECTION, movieStub.TmdbCollectionId.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_IMDB, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Id));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_ALLOCINE, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Allocine.ToString()));
            Assert.IsTrue(TestUtils.HasExternalId(externalIdentifiers, ExternalIdentifierAspect.SOURCE_CINEPASSION, ExternalIdentifierAspect.TYPE_MOVIE, movieStub.Cinepassion.ToString()));
        }
示例#7
0
        public override async Task CollectFanArtAsync(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects)
        {
            IResourceLocator mediaItemLocator = null;

            if (!BaseInfo.IsVirtualResource(aspects))
            {
                mediaItemLocator = GetResourceLocator(aspects);
            }

            if (!aspects.ContainsKey(MovieAspect.ASPECT_ID) || mediaItemLocator == null)
            {
                return;
            }

            IFanArtCache fanArtCache = ServiceRegistration.Get <IFanArtCache>();

            using (IResourceAccessor mediaItemAccessor = mediaItemLocator.CreateAccessor())
            {
                IList <Tuple <Guid, string> > actors = GetActors(aspects);

                //Check if loading nfo is needed
                if ((actors?.All(a => IsInCache(a.Item1)) ?? true) && IsInCache(mediaItemId))
                {
                    return; //Everything was already saved
                }
                NfoMovieReader movieNfoReader = await MOVIE_EXTRACTOR.TryGetNfoMovieReaderAsync(mediaItemAccessor, true).ConfigureAwait(false);

                if (movieNfoReader != null)
                {
                    //Movie fanart
                    var stubs    = movieNfoReader.GetMovieStubs();
                    var mainStub = stubs?.FirstOrDefault();
                    if (AddToCache(mediaItemId))
                    {
                        if (mainStub?.Thumb != null)
                        {
                            await fanArtCache.TrySaveFanArt(mediaItemId, mainStub.Title, FanArtTypes.Poster, p => TrySaveFileImage(mainStub.Thumb, p, "Thumb", "Nfo.")).ConfigureAwait(false);
                        }

                        await TrySaveFanArt(fanArtCache, FanArtTypes.FanArt, "FanArt", mainStub?.FanArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.DiscArt, "DiscArt", mainStub?.DiscArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Logo, "Logo", mainStub?.Logos, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.ClearArt, "ClearArt", mainStub?.ClearArt, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Banner, "Banner", mainStub?.Banners, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                        await TrySaveFanArt(fanArtCache, FanArtTypes.Thumbnail, "Landscape", mainStub?.Landscape, mediaItemId, mainStub?.Title).ConfigureAwait(false);
                    }

                    //Actor fanart
                    if (actors != null)
                    {
                        foreach (var actor in actors)
                        {
                            if (!IsInCache(actor.Item1))
                            {
                                var existingThumbs = fanArtCache.GetFanArtFiles(actor.Item1, FanArtTypes.Thumbnail);
                                var actorStub      = mainStub?.Actors?.FirstOrDefault(a => string.Equals(a?.Name, actor.Item2, StringComparison.InvariantCultureIgnoreCase));
                                if (actorStub != null || existingThumbs.Any()) //We have a thumb already or no thumb is available, so no need to check again
                                {
                                    AddToCache(actor.Item1);
                                }

                                if (actorStub?.Thumb != null)
                                {
                                    await fanArtCache.TrySaveFanArt(actor.Item1, actor.Item2, FanArtTypes.Thumbnail, p => TrySaveFileImage(actorStub.Thumb, p, "Thumb", "Nfo.")).ConfigureAwait(false);
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param>
        /// </summary>
        /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param>
        /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param>
        /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param>
        /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns>
        private async Task <bool> TryExtractMovieMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool forceQuickMode)
        {
            // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier.
            // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries
            // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry.
            var  miNumber = Interlocked.Increment(ref _lastMediaItemNumber);
            bool isStub   = extractedAspectData.ContainsKey(StubAspect.ASPECT_ID);

            try
            {
                _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode);

                // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor.
                // Otherwise it is not possible to find a nfo-file in the MediaItem's directory.
                if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber);
                    return(false);
                }

                // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before
                // has identified this MediaItem as a video and therefore added a VideoAspect.
                if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber);
                    return(false);
                }

                // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file.
                // If we don't find one, we cannot extract any metadata.
                IFileSystemResourceAccessor nfoFsra;
                if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra))
                {
                    return(false);
                }

                // Now we (asynchronously) extract the metadata into a stub object.
                // If there is an error parsing the nfo-file with XmlNfoReader, we at least try to parse for a valid IMDB-ID.
                // If no metadata was found, nothing can be stored in the MediaItemAspects.
                NfoMovieReader nfoReader = new NfoMovieReader(_debugLogger, miNumber, false, forceQuickMode, isStub, _httpClient, _settings);
                using (nfoFsra)
                {
                    if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false) &&
                        !await nfoReader.TryParseForImdbId(nfoFsra).ConfigureAwait(false))
                    {
                        _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber);
                        return(false);
                    }
                    else if (isStub)
                    {
                        Stubs.MovieStub movie = nfoReader.GetMovieStubs().FirstOrDefault();
                        if (movie != null)
                        {
                            IList <MultipleMediaItemAspect> providerResourceAspects;
                            if (MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects))
                            {
                                MultipleMediaItemAspect providerResourceAspect = providerResourceAspects.First(pa => pa.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB);
                                string mime = null;
                                if (movie.FileInfo != null && movie.FileInfo.Count > 0)
                                {
                                    mime = MimeTypeDetector.GetMimeTypeFromExtension("file" + movie.FileInfo.First().Container);
                                }
                                if (mime != null)
                                {
                                    providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, mime);
                                }
                            }

                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, movie.Title);
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, movie.SortTitle != null ? movie.SortTitle : BaseInfo.GetSortTitle(movie.Title));
                            MediaItemAspect.SetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, movie.Premiered.HasValue ? movie.Premiered.Value : movie.Year.HasValue ? movie.Year.Value : (DateTime?)null);

                            if (movie.FileInfo != null && movie.FileInfo.Count > 0)
                            {
                                extractedAspectData.Remove(VideoStreamAspect.ASPECT_ID);
                                extractedAspectData.Remove(VideoAudioStreamAspect.ASPECT_ID);
                                extractedAspectData.Remove(SubtitleAspect.ASPECT_ID);
                                StubParser.ParseFileInfo(extractedAspectData, movie.FileInfo, movie.Title, movie.Fps);
                            }
                        }
                    }
                }

                //Check reimport
                if (extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID))
                {
                    MovieInfo reimport = new MovieInfo();
                    reimport.FromMetadata(extractedAspectData);
                    if (!VerifyMovieReimport(nfoReader, reimport))
                    {
                        ServiceRegistration.Get <ILogger>().Info("NfoMovieMetadataExtractor: Nfo movie metadata from resource '{0}' ignored because it does not match reimport {1}", mediaItemAccessor, reimport);
                        return(false);
                    }
                }

                // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is
                // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false.
                if (!nfoReader.TryWriteMetadata(extractedAspectData))
                {
                    _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber);
                    return(false);
                }

                _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber);
                ServiceRegistration.Get <ILogger>().Debug("NfoMovieMetadataExtractor: Assigned nfo movie metadata for resource '{0}'", mediaItemAccessor);
                return(true);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor);
                _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber);
                return(false);
            }
        }
    /// <summary>
    /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param>
    /// </summary>
    /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param>
    /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param>
    /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param>
    /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns>
    private async Task<bool> TryExtractMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary<Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
    {
      // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier.
      // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries
      // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry.
      var miNumber = Interlocked.Increment(ref _lastMediaItemNumber);
      try
      {
        _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode);

        // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before
        // has identified this MediaItem as a video and therefore added a VideoAspect.
        if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID))
        {
          _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber);
          return false;
        }

        // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor.
        // Otherwise it is not possible to find a nfo-file in the MediaItem's directory.
        if (!(mediaItemAccessor is IFileSystemResourceAccessor))
        {
          _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber);
          return false;
        }

        // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file.
        // If we don't find one, we cannot extract any metadata.
        IFileSystemResourceAccessor nfoFsra;
        if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra))
          return false;

        // Now we (asynchronously) extract the metadata into a stub object.
        // If no metadata was found, nothing can be stored in the MediaItemAspects.
        var nfoReader = new NfoMovieReader(_debugLogger, miNumber, forceQuickMode, _httpClient, _settings);
        using (nfoFsra)
        {
          if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false))
          {
            _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber);
            return false;
          }
        }

        // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is
        // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false.
        if (!nfoReader.TryWriteMetadata(extractedAspectData))
        {
          _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber);
          return false;
        }

        _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber);
        return true;
      }
      catch (Exception e)
      {
        ServiceRegistration.Get<ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor);
        _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber);
        return false;
      }
    }
示例#10
0
        /// <summary>
        /// Asynchronously tries to extract metadata for the given <param name="mediaItemAccessor"></param>
        /// </summary>
        /// <param name="mediaItemAccessor">Points to the resource for which we try to extract metadata</param>
        /// <param name="extractedAspectData">Dictionary of <see cref="MediaItemAspect"/>s with the extracted metadata</param>
        /// <param name="forceQuickMode">If <c>true</c>, nothing is downloaded from the internet</param>
        /// <returns><c>true</c> if metadata was found and stored into <param name="extractedAspectData"></param>, else <c>false</c></returns>
        private async Task <bool> TryExtractMetadataAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, MediaItemAspect> extractedAspectData, bool forceQuickMode)
        {
            // Get a unique number for this call to TryExtractMetadataAsync. We use this to make reading the debug log easier.
            // This MetadataExtractor is called in parallel for multiple MediaItems so that the respective debug log entries
            // for one call are not contained one after another in debug log. We therefore prepend this number before every log entry.
            var miNumber = Interlocked.Increment(ref _lastMediaItemNumber);

            try
            {
                _debugLogger.Info("[#{0}]: Start extracting metadata for resource '{1}' (forceQuickMode: {2})", miNumber, mediaItemAccessor, forceQuickMode);

                // We only extract metadata with this MetadataExtractor, if another MetadataExtractor that was applied before
                // has identified this MediaItem as a video and therefore added a VideoAspect.
                if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; this resource is not a video", miNumber);
                    return(false);
                }

                // This MetadataExtractor only works for MediaItems accessible by an IFileSystemResourceAccessor.
                // Otherwise it is not possible to find a nfo-file in the MediaItem's directory.
                if (!(mediaItemAccessor is IFileSystemResourceAccessor))
                {
                    _debugLogger.Info("[#{0}]: Cannot extract metadata; mediaItemAccessor is not an IFileSystemResourceAccessor", miNumber);
                    return(false);
                }

                // Here we try to find an IFileSystemResourceAccessor pointing to the nfo-file.
                // If we don't find one, we cannot extract any metadata.
                IFileSystemResourceAccessor nfoFsra;
                if (!TryGetNfoSResourceAccessor(miNumber, mediaItemAccessor as IFileSystemResourceAccessor, out nfoFsra))
                {
                    return(false);
                }

                // Now we (asynchronously) extract the metadata into a stub object.
                // If no metadata was found, nothing can be stored in the MediaItemAspects.
                var nfoReader = new NfoMovieReader(_debugLogger, miNumber, forceQuickMode, _httpClient, _settings);
                using (nfoFsra)
                {
                    if (!await nfoReader.TryReadMetadataAsync(nfoFsra).ConfigureAwait(false))
                    {
                        _debugLogger.Warn("[#{0}]: No valid metadata found", miNumber);
                        return(false);
                    }
                }

                // Then we store the found metadata in the MediaItemAspects. If we only found metadata that is
                // not (yet) supported by our MediaItemAspects, this MetadataExtractor returns false.
                if (!nfoReader.TryWriteMetadata(extractedAspectData))
                {
                    _debugLogger.Warn("[#{0}]: No metadata was written into MediaItemsAspects", miNumber);
                    return(false);
                }

                _debugLogger.Info("[#{0}]: Successfully finished extracting metadata", miNumber);
                return(true);
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Warn("NfoMovieMetadataExtractor: Exception while extracting metadata for resource '{0}'; enable debug logging for more details.", mediaItemAccessor);
                _debugLogger.Error("[#{0}]: Exception while extracting metadata", e, miNumber);
                return(false);
            }
        }