public async Task<bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary<Guid, IList<MediaItemAspect>> aspects, IList<IDictionary<Guid, IList<MediaItemAspect>>> extractedLinkedAspects) { if (BaseInfo.IsVirtualResource(aspects)) return false; MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) return false; if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List<PersonInfo> writers)) movieInfo.Writers = writers; if (MovieMetadataExtractor.IncludeWriterDetails && !MovieMetadataExtractor.SkipOnlineSearches) await OnlineMatcherService.Instance.UpdatePersonsAsync(movieInfo, PersonAspect.OCCUPATION_WRITER).ConfigureAwait(false); foreach (PersonInfo person in movieInfo.Writers) { if (person.LinkedAspects != null) person.SetLinkedMetadata(); else { IDictionary<Guid, IList<MediaItemAspect>> personAspects = new Dictionary<Guid, IList<MediaItemAspect>>(); if (person.SetMetadata(personAspects) && personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) extractedLinkedAspects.Add(personAspects); } } return extractedLinkedAspects.Count > 0; }
/// <summary> /// Constructor. /// </summary> public MovingPicturesInfo(MediaItem mediaItem) { try { MovieInfo movie = new MovieInfo(); movie.FromMetadata(mediaItem.Aspects); ItemId = mediaItem.MediaItemId; Title = movie.MovieName.Text; AlternateTitles = movie.OriginalName; Directors = String.Join(", ", movie.Directors); Writers = String.Join(", ", movie.Writers); Actors = String.Join(", ", movie.Actors); Genres = String.Join(", ", movie.Genres.Select(g => g.Name)); Rating = Convert.ToString(movie.Rating.RatingValue ?? 0); RatingCount = Convert.ToString(movie.Rating.VoteCount ?? 0); Year = movie.ReleaseDate.Value.Year; Certification = movie.Certification; Tagline = movie.Tagline; Summary = movie.Summary.Text; ImageName = Helper.GetImageBaseURL(mediaItem, FanArtMediaTypes.Movie, FanArtTypes.Cover); } catch (Exception e) { ServiceRegistration.Get <ILogger>().Error("WifiRemote: Error getting movie info", e); } }
/// <summary> /// Constructor /// </summary> public VideoInfo(MediaItem mediaItem) { MovieInfo movie = new MovieInfo(); movie.FromMetadata(mediaItem.Aspects); ItemId = mediaItem.MediaItemId; Title = movie.MovieName.Text; Directors = String.Join(", ", movie.Directors); Writers = String.Join(", ", movie.Writers); Actors = String.Join(", ", movie.Actors); Summary = movie.Summary.Text; ImageName = Helper.GetImageBaseURL(mediaItem, FanArtMediaTypes.Undefined, FanArtTypes.Thumbnail); }
private void ExtractFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects) { if (aspects.ContainsKey(VideoAspect.ASPECT_ID)) { if (BaseInfo.IsVirtualResource(aspects)) { return; } MovieInfo movieInfo = new MovieInfo(); movieInfo.FromMetadata(aspects); bool forceFanart = !movieInfo.IsRefreshed; ExtractLocalImages(aspects, mediaItemId, movieInfo.ToString()); } }
public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects) { extractedLinkedAspects = null; if (!NfoMovieMetadataExtractor.IncludeActorDetails) { return(false); } //Only run during import if (!importOnly) { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (!UpdatePersons(aspects, movieInfo.Actors, false)) { return(false); } if (movieInfo.Actors.Count == 0) { return(false); } extractedLinkedAspects = new List <RelationshipItem>(); foreach (PersonInfo person in movieInfo.Actors) { person.AssignNameId(); person.HasChanged = movieInfo.HasChanged; IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); person.SetMetadata(personAspects); if (personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(new RelationshipItem(personAspects, Guid.Empty)); } } return(extractedLinkedAspects.Count > 0); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { if (!NfoMovieMetadataExtractor.IncludeDirectorDetails) { return(false); } MovieInfo reimport = null; if (aspects.ContainsKey(ReimportAspect.ASPECT_ID)) { reimport = new MovieInfo(); reimport.FromMetadata(aspects); } IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >(); if (!await TryExtractMovieDirectorMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false)) { return(false); } List <PersonInfo> directors; if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out directors)) { return(false); } directors = directors.Where(p => p != null && !string.IsNullOrEmpty(p.Name)).ToList(); if (directors.Count == 0) { return(false); } extractedLinkedAspects.Clear(); foreach (PersonInfo person in directors) { if (person.SetLinkedMetadata() && person.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(person.LinkedAspects); } } return(extractedLinkedAspects.Count > 0); }
public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects) { extractedLinkedAspects = null; if (!importOnly) //Only during import { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); if (collectionInfo.CollectionName.IsEmpty || collectionInfo.HasExternalId) { return(false); } extractedLinkedAspects = new List <RelationshipItem>(); IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); //Create custom collection collectionInfo.AssignNameId(); collectionInfo.SetMetadata(collectionAspects); bool movieVirtual = true; if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual)) { MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual); } if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, Guid.Empty)); } return(extractedLinkedAspects.Count > 0); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { if (!NfoMovieMetadataExtractor.IncludeCharacterDetails) { return(false); } MovieInfo reimport = null; if (aspects.ContainsKey(ReimportAspect.ASPECT_ID)) { reimport = new MovieInfo(); reimport.FromMetadata(aspects); } IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >(); if (!await TryExtractMovieCharactersMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false)) { return(false); } List <CharacterInfo> characters; if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out characters)) { return(false); } characters = characters.Where(c => c != null && !string.IsNullOrEmpty(c.Name)).ToList(); if (characters.Count == 0) { return(false); } extractedLinkedAspects.Clear(); foreach (CharacterInfo character in characters.Take(NfoMovieMetadataExtractor.MaximumCharacterCount)) { if (character.SetLinkedMetadata() && character.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(character.LinkedAspects); } } return(extractedLinkedAspects.Count > 0); }
public bool TryGetRelationshipIndex(IDictionary <Guid, IList <MediaItemAspect> > aspects, IDictionary <Guid, IList <MediaItemAspect> > linkedAspects, out int index) { index = -1; MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (movieInfo.ReleaseDate.HasValue) { index = movieInfo.ReleaseDate.Value.Year; } return(index >= 0); }
public override void Update(MediaItem mediaItem) { base.Update(mediaItem); MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(mediaItem.Aspects)) { return; } MovieName = movieInfo.MovieName.Text ?? ""; CollectionName = movieInfo.CollectionName.Text ?? ""; StoryPlot = movieInfo.Summary.Text ?? ""; Year = movieInfo.ReleaseDate.HasValue ? movieInfo.ReleaseDate.Value.Year.ToString() : ""; FireChange(); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { MovieInfo reimport = null; if (aspects.ContainsKey(ReimportAspect.ASPECT_ID)) { reimport = new MovieInfo(); reimport.FromMetadata(aspects); } IList <IDictionary <Guid, IList <MediaItemAspect> > > nfoLinkedAspects = new List <IDictionary <Guid, IList <MediaItemAspect> > >(); if (!await TryExtractMovieCollectionMetadataAsync(mediaItemAccessor, nfoLinkedAspects, reimport).ConfigureAwait(false)) { return(false); } List <MovieCollectionInfo> collections; if (!RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(nfoLinkedAspects, out collections)) { return(false); } collections = collections.Where(c => c != null && !c.CollectionName.IsEmpty).ToList(); bool movieVirtual; if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual)) { movieVirtual = false; } extractedLinkedAspects.Clear(); foreach (MovieCollectionInfo collection in collections) { if (collection.SetLinkedMetadata() && collection.LinkedAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { MediaItemAspect.SetAttribute(collection.LinkedAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual); extractedLinkedAspects.Add(collection.LinkedAspects); } } return(extractedLinkedAspects.Count > 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); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { if (BaseInfo.IsVirtualResource(aspects)) { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <CharacterInfo> characters)) { movieInfo.Characters = characters; } if (MovieMetadataExtractor.IncludeCharacterDetails && !MovieMetadataExtractor.SkipOnlineSearches) { await OnlineMatcherService.Instance.UpdateCharactersAsync(movieInfo).ConfigureAwait(false); } foreach (CharacterInfo character in movieInfo.Characters) { if (character.LinkedAspects != null) { character.SetLinkedMetadata(); } else { IDictionary <Guid, IList <MediaItemAspect> > characterAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); if (character.SetMetadata(characterAspects) && characterAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(characterAspects); } } } return(extractedLinkedAspects.Count > 0); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { if (BaseInfo.IsVirtualResource(aspects)) { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <PersonInfo> actors)) { movieInfo.Actors = actors; } if (MovieMetadataExtractor.IncludeActorDetails && !MovieMetadataExtractor.SkipOnlineSearches) { await OnlineMatcherService.Instance.UpdatePersonsAsync(movieInfo, PersonAspect.OCCUPATION_ACTOR, _category).ConfigureAwait(false); } foreach (PersonInfo person in movieInfo.Actors.Take(MovieMetadataExtractor.MaximumActorCount)) { if (person.LinkedAspects != null) { person.SetLinkedMetadata(); } else { IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); if (person.SetMetadata(personAspects) && personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(personAspects); } } } return(extractedLinkedAspects.Count > 0); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } MovieCollectionInfo collectionInfo = RelationshipExtractorUtils.TryCreateInfoFromLinkedAspects(extractedLinkedAspects, out List <MovieCollectionInfo> collection) ? collection[0] : movieInfo.CloneBasicInstance <MovieCollectionInfo>(); if (!MovieMetadataExtractor.SkipOnlineSearches && collectionInfo.HasExternalId) { await OnlineMatcherService.Instance.UpdateCollectionAsync(collectionInfo, false).ConfigureAwait(false); } IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = collectionInfo.LinkedAspects != null ? collectionInfo.LinkedAspects : new Dictionary <Guid, IList <MediaItemAspect> >(); collectionInfo.SetMetadata(collectionAspects); bool movieVirtual = true; if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual)) { MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual); } if (!collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { return(false); } if (collectionInfo.LinkedAspects == null) { extractedLinkedAspects.Add(collectionAspects); } return(extractedLinkedAspects.Count > 0); }
public override async Task CollectFanArtAsync(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects) { //Virtual resources won't have local fanart if (BaseInfo.IsVirtualResource(aspects)) { return; } //Don't process the same item again if (!AddToCache(mediaItemId)) { return; } IResourceLocator mediaItemLocator = GetResourceLocator(aspects); if (mediaItemLocator == null) { return; } //Only needed for the name used in the fanart cache MovieInfo movieInfo = new MovieInfo(); movieInfo.FromMetadata(aspects); string title = movieInfo.ToString(); //Fanart files in the local directory if (ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath, VideoMetadataExtractor.CacheLocalFanArt, VideoMetadataExtractor.CacheOfflineFanArt)) { await ExtractFolderFanArt(mediaItemLocator, mediaItemId, title).ConfigureAwait(false); } //Fanart in MKV tags if (MKV_EXTENSIONS.Contains(ResourcePathHelper.GetExtension(mediaItemLocator.NativeResourcePath.FileName))) { await ExtractMkvFanArt(mediaItemLocator, mediaItemId, title).ConfigureAwait(false); } }
public bool TryMatch(IDictionary <Guid, IList <MediaItemAspect> > extractedAspects, IDictionary <Guid, IList <MediaItemAspect> > existingAspects) { if (!existingAspects.ContainsKey(MovieAspect.ASPECT_ID)) { return(false); } MovieInfo linkedMovie = new MovieInfo(); if (!linkedMovie.FromMetadata(extractedAspects)) { return(false); } MovieInfo existingMovie = new MovieInfo(); if (!existingMovie.FromMetadata(existingAspects)) { return(false); } return(linkedMovie.Equals(existingMovie)); }
public async Task <bool> TryExtractRelationshipsAsync(IResourceAccessor mediaItemAccessor, IDictionary <Guid, IList <MediaItemAspect> > aspects, IList <IDictionary <Guid, IList <MediaItemAspect> > > extractedLinkedAspects) { if (BaseInfo.IsVirtualResource(aspects)) { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (MovieMetadataExtractor.IncludeProductionCompanyDetails && !MovieMetadataExtractor.SkipOnlineSearches) { await OnlineMatcherService.Instance.UpdateCompaniesAsync(movieInfo, CompanyAspect.COMPANY_PRODUCTION, _category).ConfigureAwait(false); } foreach (CompanyInfo company in movieInfo.ProductionCompanies) { if (company.LinkedAspects != null) { company.SetLinkedMetadata(); } else { IDictionary <Guid, IList <MediaItemAspect> > companyAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); if (company.SetMetadata(companyAspects) && companyAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(companyAspects); } } } return(extractedLinkedAspects.Count > 0); }
private void ExtractFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects, Guid?collectionMediaItemId, IDictionary <Guid, string> actorMediaItems) { if (aspects.ContainsKey(MovieAspect.ASPECT_ID)) { if (BaseInfo.IsVirtualResource(aspects)) { return; } MovieInfo movieInfo = new MovieInfo(); movieInfo.FromMetadata(aspects); bool forceFanart = !movieInfo.IsRefreshed; MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); ExtractLocalImages(aspects, mediaItemId, collectionMediaItemId, movieInfo.ToString(), collectionInfo.ToString(), actorMediaItems); if (!MovieMetadataExtractor.SkipFanArtDownload) { OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, movieInfo, forceFanart); } //Take advantage of the movie language being known and download collection too if (collectionMediaItemId.HasValue && !_checkCache.Contains(collectionMediaItemId.Value)) { if (!MovieMetadataExtractor.SkipFanArtDownload) { OnlineMatcherService.Instance.DownloadMovieFanArt(collectionMediaItemId.Value, collectionInfo, forceFanart); } _checkCache.Add(collectionMediaItemId.Value); } } else if (aspects.ContainsKey(PersonAspect.ASPECT_ID)) { PersonInfo personInfo = new PersonInfo(); personInfo.FromMetadata(aspects); if (personInfo.Occupation == PersonAspect.OCCUPATION_ACTOR || personInfo.Occupation == PersonAspect.OCCUPATION_DIRECTOR || personInfo.Occupation == PersonAspect.OCCUPATION_WRITER) { if (!MovieMetadataExtractor.SkipFanArtDownload) { OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, personInfo, !personInfo.IsRefreshed); } } } else if (aspects.ContainsKey(CharacterAspect.ASPECT_ID)) { CharacterInfo characterInfo = new CharacterInfo(); characterInfo.FromMetadata(aspects); if (!MovieMetadataExtractor.SkipFanArtDownload) { OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, characterInfo, !characterInfo.IsRefreshed); } } else if (aspects.ContainsKey(CompanyAspect.ASPECT_ID)) { CompanyInfo companyInfo = new CompanyInfo(); companyInfo.FromMetadata(aspects); if (companyInfo.Type == CompanyAspect.COMPANY_PRODUCTION) { if (!MovieMetadataExtractor.SkipFanArtDownload) { OnlineMatcherService.Instance.DownloadMovieFanArt(mediaItemId, companyInfo, !companyInfo.IsRefreshed); } } } }
protected async Task ExtractMovieFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects) { bool shouldCacheLocal = false; IResourceLocator mediaItemLocator = null; if (!BaseInfo.IsVirtualResource(aspects)) { mediaItemLocator = GetResourceLocator(aspects); //Whether local fanart should be stored in the fanart cache shouldCacheLocal = ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath, MovieMetadataExtractor.CacheLocalFanArt, MovieMetadataExtractor.CacheOfflineFanArt); } if (mediaItemLocator == null) { return; } if (!shouldCacheLocal && MovieMetadataExtractor.SkipFanArtDownload) { return; //Nothing to do } MovieInfo movieInfo = new MovieInfo(); movieInfo.FromMetadata(aspects); //Movie fanart if (AddToCache(mediaItemId)) { //Actor fanart may be stored in the movie directory, so get the actors now IList <Tuple <Guid, string> > actors = null; if (MediaItemAspect.TryGetAspect(aspects, VideoAspect.Metadata, out SingleMediaItemAspect videoAspect)) { var actorNames = videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS); if (actorNames != null) { RelationshipExtractorUtils.TryGetMappedLinkedIds(PersonAspect.ROLE_ACTOR, aspects, actorNames.ToList(), out actors); } } if (shouldCacheLocal) { await ExtractMovieFolderFanArt(mediaItemLocator, mediaItemId, movieInfo.ToString(), actors).ConfigureAwait(false); } if (!MovieMetadataExtractor.SkipFanArtDownload) { await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(mediaItemId, movieInfo).ConfigureAwait(false); } //Find central actor information folder var seriesDirectory = ResourcePathHelper.Combine(mediaItemLocator.NativeResourcePath, "../../"); ResourcePath centralActorFolderPath = LocalFanartHelper.GetCentralPersonFolder(seriesDirectory, CentralPersonFolderType.MovieActors); if (shouldCacheLocal && centralActorFolderPath != null && actors != null) { foreach (var actor in actors) { // Check if we already processed this actor if (!AddToCache(actor.Item1)) { continue; } // First get the ResourcePath of the central directory var artistFolderPath = ResourcePathHelper.Combine(centralActorFolderPath, $"{LocalFanartHelper.GetSafePersonFolderName(actor.Item2)}/"); using (IResourceAccessor accessor = new ResourceLocator(mediaItemLocator.NativeSystemId, artistFolderPath).CreateAccessor()) { if (accessor is IFileSystemResourceAccessor directoryAccessor) { FanArtPathCollection paths = new FanArtPathCollection(); List <ResourcePath> potentialFanArtFiles = LocalFanartHelper.GetPotentialFanArtFiles(directoryAccessor); ExtractAllFanArtImages(potentialFanArtFiles, paths); await SaveFolderImagesToCache(mediaItemLocator.NativeSystemId, paths, actor.Item1, actor.Item2).ConfigureAwait(false); } } } } } //Collection fanart if (RelationshipExtractorUtils.TryGetLinkedId(MovieCollectionAspect.ROLE_MOVIE_COLLECTION, aspects, out Guid collectionMediaItemId) && AddToCache(collectionMediaItemId)) { MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); if (shouldCacheLocal) { await ExtractCollectionFolderFanArt(mediaItemLocator, collectionMediaItemId, collectionInfo.ToString()).ConfigureAwait(false); } if (!MovieMetadataExtractor.SkipFanArtDownload) { await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(collectionMediaItemId, collectionInfo).ConfigureAwait(false); } } }
public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects) { extractedLinkedAspects = null; if (!MovieMetadataExtractor.IncludeWriterDetails) { return(false); } if (importOnly) { return(false); } if (BaseInfo.IsVirtualResource(aspects)) { return(false); } MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } if (CheckCacheContains(movieInfo)) { return(false); } int count = 0; if (!MovieMetadataExtractor.SkipOnlineSearches) { OnlineMatcherService.Instance.UpdatePersons(movieInfo, PersonAspect.OCCUPATION_WRITER, importOnly); count = movieInfo.Writers.Where(p => p.HasExternalId).Count(); if (!movieInfo.IsRefreshed) { movieInfo.HasChanged = true; //Force save to update external Ids for metadata found by other MDEs } } else { count = movieInfo.Writers.Where(p => !string.IsNullOrEmpty(p.Name)).Count(); } if (movieInfo.Writers.Count == 0) { return(false); } if (BaseInfo.CountRelationships(aspects, LinkedRole) < count || (BaseInfo.CountRelationships(aspects, LinkedRole) == 0 && movieInfo.Writers.Count > 0)) { movieInfo.HasChanged = true; //Force save if no relationship exists } if (!movieInfo.HasChanged) { return(false); } AddToCheckCache(movieInfo); extractedLinkedAspects = new List <RelationshipItem>(); foreach (PersonInfo person in movieInfo.Writers) { person.AssignNameId(); person.HasChanged = movieInfo.HasChanged; IDictionary <Guid, IList <MediaItemAspect> > personAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); person.SetMetadata(personAspects); if (personAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { Guid existingId; if (TryGetIdFromCache(person, out existingId)) { extractedLinkedAspects.Add(new RelationshipItem(personAspects, existingId)); } else { extractedLinkedAspects.Add(new RelationshipItem(personAspects, Guid.Empty)); } } } return(extractedLinkedAspects.Count > 0); }
private bool ExtractMovieData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData, bool importOnly) { // Calling EnsureLocalFileSystemAccess not necessary; only string operation string[] pathsToTest = new[] { lfsra.LocalFileSystemPath, lfsra.CanonicalLocalResourcePath.ToString() }; string title = null; string sortTitle = null; // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoStreamAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID)) { return(false); } if (extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID) && !importOnly) { return(false); //Subtitles can only be imported not refreshed } bool refresh = false; if (extractedAspectData.ContainsKey(MovieAspect.ASPECT_ID)) { refresh = true; } MovieInfo movieInfo = new MovieInfo(); if (refresh) { movieInfo.FromMetadata(extractedAspectData); } if (movieInfo.MovieName.IsEmpty) { //Try to get title if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) && !string.IsNullOrEmpty(title) && !lfsra.ResourceName.StartsWith(title, StringComparison.InvariantCultureIgnoreCase)) { movieInfo.MovieName = title; /* Clear the names from unwanted strings */ MovieNameMatcher.CleanupTitle(movieInfo); } } if (movieInfo.MovieNameSort.IsEmpty) { //Try to get sort title if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, out sortTitle) && !string.IsNullOrEmpty(sortTitle)) { movieInfo.MovieNameSort = sortTitle; } } if (movieInfo.MovieDbId == 0) { try { // Try to use an existing TMDB id for exact mapping string tmdbId; if (MatroskaMatcher.TryMatchTmdbId(lfsra, out tmdbId)) { movieInfo.MovieDbId = Convert.ToInt32(tmdbId); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading TMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } if (string.IsNullOrEmpty(movieInfo.ImdbId)) { try { // Try to use an existing IMDB id for exact mapping string imdbId = null; if (pathsToTest.Any(path => MatroskaMatcher.TryMatchImdbId(lfsra, out imdbId))) { movieInfo.ImdbId = imdbId; } else if (pathsToTest.Any(path => ImdbIdMatcher.TryMatchImdbId(path, out imdbId))) { movieInfo.ImdbId = imdbId; } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading IMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } if (!movieInfo.IsBaseInfoPresent) { // Also test the full path year. This is useful if the path contains the real name and year. foreach (string path in pathsToTest) { if (MovieNameMatcher.MatchTitleYear(path, movieInfo)) { break; } } //Fall back to MediaAspect.ATTR_TITLE if (movieInfo.MovieName.IsEmpty && !string.IsNullOrEmpty(title)) { movieInfo.MovieName = title; } /* Clear the names from unwanted strings */ MovieNameMatcher.CleanupTitle(movieInfo); } if (!movieInfo.ReleaseDate.HasValue && !movieInfo.HasExternalId) { // When searching movie title, the year can be relevant for multiple titles with same name but different years DateTime recordingDate; if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, out recordingDate)) { movieInfo.ReleaseDate = recordingDate; } } // Allow the online lookup to choose best matching language for metadata if (movieInfo.Languages.Count == 0) { IList <MultipleMediaItemAspect> audioAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects)) { foreach (MultipleMediaItemAspect aspect in audioAspects) { string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE); if (!string.IsNullOrEmpty(language) && !movieInfo.Languages.Contains(language)) { movieInfo.Languages.Add(language); } } } } if (importOnly) { try { MatroskaMatcher.ExtractFromTags(lfsra, movieInfo); MP4Matcher.ExtractFromTags(lfsra, movieInfo); } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } if (SkipOnlineSearches && !SkipFanArtDownload) { MovieInfo tempInfo = movieInfo.Clone(); OnlineMatcherService.Instance.FindAndUpdateMovie(tempInfo, importOnly); movieInfo.CopyIdsFrom(tempInfo); movieInfo.HasChanged = tempInfo.HasChanged; } else if (!SkipOnlineSearches) { OnlineMatcherService.Instance.FindAndUpdateMovie(movieInfo, importOnly); } //Send it to the videos section if (!SkipOnlineSearches && !movieInfo.HasExternalId) { return(false); } if (importOnly) { //Create custom collection (overrides online collection) MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); string collectionName; if (string.IsNullOrEmpty(collectionInfo.NameId) && CollectionFolderHasFanArt(lfsra, out collectionName)) { collectionInfo = new MovieCollectionInfo(); collectionInfo.CollectionName = collectionName; if (!collectionInfo.CollectionName.IsEmpty) { movieInfo.CollectionName = collectionInfo.CollectionName; movieInfo.CopyIdsFrom(collectionInfo); //Reset ID's movieInfo.HasChanged = true; } } } movieInfo.AssignNameId(); if (refresh) { if ((IncludeActorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_ACTOR) && movieInfo.Actors.Count > 0) || (IncludeCharacterDetails && !BaseInfo.HasRelationship(extractedAspectData, CharacterAspect.ROLE_CHARACTER) && movieInfo.Characters.Count > 0) || (IncludeDirectorDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_DIRECTOR) && movieInfo.Directors.Count > 0) || (IncludeWriterDetails && !BaseInfo.HasRelationship(extractedAspectData, PersonAspect.ROLE_WRITER) && movieInfo.Writers.Count > 0) || (IncludeProductionCompanyDetails && !BaseInfo.HasRelationship(extractedAspectData, CompanyAspect.ROLE_COMPANY) && movieInfo.ProductionCompanies.Count > 0)) { movieInfo.HasChanged = true; } } if (!movieInfo.HasChanged && !importOnly) { return(false); } movieInfo.SetMetadata(extractedAspectData); return(movieInfo.IsBaseInfoPresent); }
/// <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); } }
protected async Task ExtractMovieFanArt(Guid mediaItemId, IDictionary <Guid, IList <MediaItemAspect> > aspects) { bool shouldCacheLocal = false; IResourceLocator mediaItemLocator = null; if (!BaseInfo.IsVirtualResource(aspects)) { mediaItemLocator = GetResourceLocator(aspects); if (mediaItemLocator == null) { return; } //Whether local fanart should be stored in the fanart cache shouldCacheLocal = ShouldCacheLocalFanArt(mediaItemLocator.NativeResourcePath, MovieMetadataExtractor.CacheLocalFanArt, MovieMetadataExtractor.CacheOfflineFanArt); } if (!shouldCacheLocal && MovieMetadataExtractor.SkipFanArtDownload) { return; //Nothing to do } MovieInfo movieInfo = new MovieInfo(); movieInfo.FromMetadata(aspects); //Movie fanart if (AddToCache(mediaItemId)) { //Actor fanart may be stored in the movie directory, so get the actors now IList <Tuple <Guid, string> > actors = null; if (MediaItemAspect.TryGetAspect(aspects, VideoAspect.Metadata, out SingleMediaItemAspect videoAspect)) { var actorNames = videoAspect.GetCollectionAttribute <string>(VideoAspect.ATTR_ACTORS); if (actorNames != null) { RelationshipExtractorUtils.TryGetMappedLinkedIds(PersonAspect.ROLE_ACTOR, aspects, actorNames.ToList(), out actors); } } if (shouldCacheLocal) { await ExtractMovieFolderFanArt(mediaItemLocator, mediaItemId, movieInfo.ToString(), actors).ConfigureAwait(false); } if (!MovieMetadataExtractor.SkipFanArtDownload) { await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(mediaItemId, movieInfo).ConfigureAwait(false); } } //Collection fanart if (RelationshipExtractorUtils.TryGetLinkedId(MovieCollectionAspect.ROLE_MOVIE_COLLECTION, aspects, out Guid collectionMediaItemId) && AddToCache(collectionMediaItemId)) { MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); if (shouldCacheLocal) { await ExtractCollectionFolderFanArt(mediaItemLocator, collectionMediaItemId, collectionInfo.ToString()).ConfigureAwait(false); } if (!MovieMetadataExtractor.SkipFanArtDownload) { await OnlineMatcherService.Instance.DownloadMovieFanArtAsync(collectionMediaItemId, collectionInfo).ConfigureAwait(false); } } }
public bool TryMerge(IDictionary <Guid, IList <MediaItemAspect> > extractedAspects, IDictionary <Guid, IList <MediaItemAspect> > existingAspects) { try { MovieInfo existing = new MovieInfo(); MovieInfo extracted = new MovieInfo(); //Extracted aspects IList <MultipleMediaItemAspect> providerResourceAspects; if (!MediaItemAspect.TryGetAspects(extractedAspects, ProviderResourceAspect.Metadata, out providerResourceAspects)) { return(false); } //Existing aspects IList <MultipleMediaItemAspect> existingProviderResourceAspects; MediaItemAspect.TryGetAspects(existingAspects, ProviderResourceAspect.Metadata, out existingProviderResourceAspects); //Don't merge virtual resources if (!providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_VIRTUAL).Any()) { //Replace if existing is a virtual resource if (existingProviderResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_VIRTUAL).Any()) { //Don't allow merge of subtitles into virtual item if (extractedAspects.ContainsKey(SubtitleAspect.ASPECT_ID) && !extractedAspects.ContainsKey(VideoStreamAspect.ASPECT_ID)) { return(false); } MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISSTUB, providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any()); var now = DateTime.Now; MediaItemAspect.SetAttribute(existingAspects, ImporterAspect.ATTR_DATEADDED, now); MediaItemAspect.SetAttribute(existingAspects, ImporterAspect.ATTR_LAST_IMPORT_DATE, now); existingAspects.Remove(ProviderResourceAspect.ASPECT_ID); foreach (Guid aspect in extractedAspects.Keys) { if (!existingAspects.ContainsKey(aspect)) { existingAspects.Add(aspect, extractedAspects[aspect]); } } existing.FromMetadata(existingAspects); extracted.FromMetadata(extractedAspects); existing.MergeWith(extracted, true); existing.SetMetadata(existingAspects); return(true); } //Merge if (providerResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any() || existingProviderResourceAspects.Where(p => p.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) == ProviderResourceAspect.TYPE_STUB).Any()) { MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISVIRTUAL, false); MediaItemAspect.SetAttribute(existingAspects, MediaAspect.ATTR_ISSTUB, true); if (!ResourceAspectMerger.MergeVideoResourceAspects(extractedAspects, existingAspects)) { return(false); } } } existing.FromMetadata(existingAspects); extracted.FromMetadata(extractedAspects); existing.MergeWith(extracted, true); existing.SetMetadata(existingAspects); if (!ResourceAspectMerger.MergeVideoResourceAspects(extractedAspects, existingAspects)) { return(false); } return(true); } catch (Exception e) { // Only log at the info level here - And simply return false. This lets the caller know that we // couldn't perform our task here. ServiceRegistration.Get <ILogger>().Info("MovieMergeHandler: Exception merging resources (Text: '{0}')", e.Message); return(false); } }
public async Task <IList <MediaItemSearchResult> > SearchForMatchesAsync(IDictionary <Guid, IList <MediaItemAspect> > searchAspectData, ICollection <string> searchCategories) { try { if (!(searchCategories?.Contains(MEDIA_CATEGORY_NAME_MOVIE) ?? true)) { return(null); } string searchData = null; var reimportAspect = MediaItemAspect.GetAspect(searchAspectData, ReimportAspect.Metadata); if (reimportAspect != null) { searchData = reimportAspect.GetAttributeValue <string>(ReimportAspect.ATTR_SEARCH); } ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Search aspects to use: '{0}'", string.Join(",", searchAspectData.Keys)); //Prepare search info MovieInfo movieSearchinfo = null; List <MediaItemSearchResult> searchResults = new List <MediaItemSearchResult>(); if (!string.IsNullOrEmpty(searchData)) { if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { movieSearchinfo = new MovieInfo(); if (searchData.StartsWith("tt", StringComparison.InvariantCultureIgnoreCase) && !searchData.Contains(" ") && int.TryParse(searchData.Substring(2), out int id)) { movieSearchinfo.ImdbId = searchData; } else if (!searchData.Contains(" ") && int.TryParse(searchData, out int movieDbId)) { movieSearchinfo.MovieDbId = movieDbId; } else //Fallabck to name search { searchData = searchData.Trim(); if (!MovieNameMatcher.MatchTitleYear(searchData, movieSearchinfo)) { movieSearchinfo.MovieName = searchData; } } ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Searching for movie matches on search: '{0}'", searchData); } } else { if (searchAspectData.ContainsKey(VideoAspect.ASPECT_ID)) { movieSearchinfo = new MovieInfo(); movieSearchinfo.FromMetadata(searchAspectData); ServiceRegistration.Get <ILogger>().Debug("MovieMetadataExtractor: Searching for movie matches on aspects"); } } //Perform online search if (movieSearchinfo != null) { var matches = await OnlineMatcherService.Instance.FindMatchingMoviesAsync(movieSearchinfo).ConfigureAwait(false); ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Movie search returned {0} matches", matches.Count()); foreach (var match in matches) { var result = new MediaItemSearchResult { Name = $"{match.MovieName.Text}{(match.ReleaseDate == null ? "" : $" ({match.ReleaseDate.Value.Year})")}" + $"{(string.IsNullOrWhiteSpace(match.OriginalName) || string.Compare(match.MovieName.Text, match.OriginalName, true) == 0 ? "" : $" [{match.OriginalName}]")}", Description = match.Summary.IsEmpty ? "" : match.Summary.Text, }; //Add external Ids if (!string.IsNullOrEmpty(match.ImdbId)) { result.ExternalIds.Add("imdb.com", match.ImdbId); } if (match.MovieDbId > 0) { result.ExternalIds.Add("themoviedb.org", match.MovieDbId.ToString()); } //Assign aspects and remove unwanted aspects match.SetMetadata(result.AspectData, true); CleanReimportAspects(result.AspectData); searchResults.Add(result); } return(searchResults); }
private async Task <bool> ExtractMovieData(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData) { // VideoAspect must be present to be sure it is actually a video resource. if (!extractedAspectData.ContainsKey(VideoAspect.ASPECT_ID) && !extractedAspectData.ContainsKey(SubtitleAspect.ASPECT_ID)) { return(false); } // Calling EnsureLocalFileSystemAccess not necessary; only string operation string[] pathsToTest = new[] { lfsra.LocalFileSystemPath, lfsra.CanonicalLocalResourcePath.ToString() }; string title = null; string sortTitle = null; bool isReimport = extractedAspectData.ContainsKey(ReimportAspect.ASPECT_ID); MovieInfo movieInfo = new MovieInfo(); if (extractedAspectData.ContainsKey(MovieAspect.ASPECT_ID)) { movieInfo.FromMetadata(extractedAspectData); } if (movieInfo.MovieName.IsEmpty) { //Try to get title if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_TITLE, out title) && !string.IsNullOrEmpty(title) && !lfsra.ResourceName.StartsWith(title, StringComparison.InvariantCultureIgnoreCase)) { //The title may still contain tags and other noise, try and parse it for a title and year. MovieNameMatcher.MatchTitleYear(title, movieInfo); } } if (movieInfo.MovieNameSort.IsEmpty) { //Try to get sort title if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_SORT_TITLE, out sortTitle) && !string.IsNullOrEmpty(sortTitle)) { movieInfo.MovieNameSort = sortTitle; } } if (!isReimport) //Ignore tags or file based information for reimport because they might be the cause of the wrong import { if (movieInfo.MovieDbId == 0) { try { // Try to use an existing TMDB id for exact mapping string tmdbId = await MatroskaMatcher.TryMatchTmdbIdAsync(lfsra).ConfigureAwait(false); if (!string.IsNullOrEmpty(tmdbId)) { movieInfo.MovieDbId = Convert.ToInt32(tmdbId); } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading TMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } if (string.IsNullOrEmpty(movieInfo.ImdbId)) { try { // Try to use an existing IMDB id for exact mapping string imdbId = await MatroskaMatcher.TryMatchImdbIdAsync(lfsra).ConfigureAwait(false); if (!string.IsNullOrEmpty(imdbId)) { movieInfo.ImdbId = imdbId; } else if (pathsToTest.Any(path => ImdbIdMatcher.TryMatchImdbId(path, out imdbId))) { movieInfo.ImdbId = imdbId; } } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading IMDB ID for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } if (!movieInfo.IsBaseInfoPresent || !movieInfo.ReleaseDate.HasValue) { // Also test the full path year. This is useful if the path contains the real name and year. foreach (string path in pathsToTest) { if (MovieNameMatcher.MatchTitleYear(path, movieInfo)) { break; } } //Fall back to MediaAspect.ATTR_TITLE if (movieInfo.MovieName.IsEmpty && !string.IsNullOrEmpty(title)) { movieInfo.MovieName = title; } /* Clear the names from unwanted strings */ MovieNameMatcher.CleanupTitle(movieInfo); } if (!movieInfo.ReleaseDate.HasValue && !movieInfo.HasExternalId) { // When searching movie title, the year can be relevant for multiple titles with same name but different years DateTime recordingDate; if (MediaItemAspect.TryGetAttribute(extractedAspectData, MediaAspect.ATTR_RECORDINGTIME, out recordingDate)) { movieInfo.ReleaseDate = recordingDate; } } try { await MatroskaMatcher.ExtractFromTagsAsync(lfsra, movieInfo).ConfigureAwait(false); MP4Matcher.ExtractFromTags(lfsra, movieInfo); } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Debug("MoviesMetadataExtractor: Exception reading tags for '{0}'", ex, lfsra.CanonicalLocalResourcePath); } } // Allow the online lookup to choose best matching language for metadata if (movieInfo.Languages.Count == 0) { IList <MultipleMediaItemAspect> audioAspects; if (MediaItemAspect.TryGetAspects(extractedAspectData, VideoAudioStreamAspect.Metadata, out audioAspects)) { foreach (MultipleMediaItemAspect aspect in audioAspects) { string language = (string)aspect.GetAttributeValue(VideoAudioStreamAspect.ATTR_AUDIOLANGUAGE); if (!string.IsNullOrEmpty(language) && !movieInfo.Languages.Contains(language)) { movieInfo.Languages.Add(language); } } } } if (SkipOnlineSearches && !SkipFanArtDownload) { MovieInfo tempInfo = movieInfo.Clone(); if (await OnlineMatcherService.Instance.FindAndUpdateMovieAsync(tempInfo).ConfigureAwait(false)) { movieInfo.CopyIdsFrom(tempInfo); movieInfo.HasChanged = tempInfo.HasChanged; } } else if (!SkipOnlineSearches) { await OnlineMatcherService.Instance.FindAndUpdateMovieAsync(movieInfo).ConfigureAwait(false); } //Asign genre ids if (movieInfo.Genres.Count > 0) { IGenreConverter converter = ServiceRegistration.Get <IGenreConverter>(); foreach (var genre in movieInfo.Genres) { if (!genre.Id.HasValue && converter.GetGenreId(genre.Name, GenreCategory.Movie, null, out int genreId)) { genre.Id = genreId; movieInfo.HasChanged = true; } } } //Send it to the videos section if (!SkipOnlineSearches && !movieInfo.HasExternalId) { return(false); } //Create custom collection (overrides online collection) MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); string collectionName; if (string.IsNullOrEmpty(collectionInfo.NameId) && CollectionFolderHasFanArt(lfsra, out collectionName)) { collectionInfo = new MovieCollectionInfo(); collectionInfo.CollectionName = collectionName; if (!collectionInfo.CollectionName.IsEmpty) { movieInfo.CollectionName = collectionInfo.CollectionName; movieInfo.CopyIdsFrom(collectionInfo); //Reset ID's movieInfo.HasChanged = true; } } if (movieInfo.MovieNameSort.IsEmpty) { if (!movieInfo.CollectionName.IsEmpty && movieInfo.ReleaseDate.HasValue) { movieInfo.MovieNameSort = $"{movieInfo.CollectionName.Text} {movieInfo.ReleaseDate.Value.Year}-{movieInfo.ReleaseDate.Value.Month.ToString("00")}"; } else if (!movieInfo.MovieName.IsEmpty) { movieInfo.MovieNameSort = BaseInfo.GetSortTitle(movieInfo.MovieName.Text); } else { movieInfo.MovieNameSort = BaseInfo.GetSortTitle(title); } } movieInfo.SetMetadata(extractedAspectData); return(movieInfo.IsBaseInfoPresent); }
public bool TryExtractRelationships(IDictionary <Guid, IList <MediaItemAspect> > aspects, bool importOnly, out IList <RelationshipItem> extractedLinkedAspects) { extractedLinkedAspects = null; MovieInfo movieInfo = new MovieInfo(); if (!movieInfo.FromMetadata(aspects)) { return(false); } MovieCollectionInfo cachedCollection; Guid collectionId; MovieCollectionInfo collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); if (TryGetInfoFromCache(collectionInfo, out cachedCollection, out collectionId)) { collectionInfo = cachedCollection; } else if (!MovieMetadataExtractor.SkipOnlineSearches && collectionInfo.HasExternalId) { OnlineMatcherService.Instance.UpdateCollection(collectionInfo, false, false); } bool hasId = false; if (!MovieMetadataExtractor.SkipOnlineSearches) { hasId = collectionInfo.HasExternalId || !string.IsNullOrEmpty(movieInfo.CollectionNameId); } else { hasId = !string.IsNullOrEmpty(movieInfo.CollectionNameId); } if (!BaseInfo.HasRelationship(aspects, LinkedRole) && hasId) { collectionInfo.HasChanged = true; //Force save if no relationship exists } if (!collectionInfo.HasChanged && !importOnly) { return(false); } extractedLinkedAspects = new List <RelationshipItem>(); IDictionary <Guid, IList <MediaItemAspect> > collectionAspects = new Dictionary <Guid, IList <MediaItemAspect> >(); if (collectionId != Guid.Empty) { collectionInfo.SetMetadata(collectionAspects); bool movieVirtual = true; if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual)) { MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual); } if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, collectionId)); } } else { //Create custom collection if (!string.IsNullOrEmpty(movieInfo.CollectionNameId) && !collectionInfo.HasExternalId) { collectionInfo = movieInfo.CloneBasicInstance <MovieCollectionInfo>(); collectionInfo.HasChanged = true; } collectionInfo.SetMetadata(collectionAspects); bool movieVirtual = true; if (MediaItemAspect.TryGetAttribute(aspects, MediaAspect.ATTR_ISVIRTUAL, false, out movieVirtual)) { MediaItemAspect.SetAttribute(collectionAspects, MediaAspect.ATTR_ISVIRTUAL, movieVirtual); } if (collectionAspects.ContainsKey(ExternalIdentifierAspect.ASPECT_ID)) { extractedLinkedAspects.Add(new RelationshipItem(collectionAspects, Guid.Empty)); } } return(extractedLinkedAspects.Count > 0); }