public void TestMovieMerge() { MovieInfo clone = _movie.Clone(); clone.MergeWith(_movieSearch); Assert.AreEqual(clone.MovieName.Text, _movieSearch.MovieName.Text, "Error merging strings by length"); Assert.IsTrue(clone.Awards.Contains("Emmy"), "Error adding missing award"); Assert.IsFalse(clone.Genres.Any(g => g.Name == "Adventure"), "Error with only merging if genre is empty"); Assert.IsTrue(clone.ProductionCompanies.Any(p => p.Name == "Company Name" && p.AudioDbId == 333), "Error adding missing company"); Assert.AreEqual(clone.Rating.RatingValue, _movieSearch.Rating.RatingValue, "Error updating rating"); Assert.AreEqual(clone.MovieDbId, _movieSearch.MovieDbId, "Error merging integer id"); Assert.AreEqual(clone.ImdbId, _movieSearch.ImdbId, "Error merging string id"); Assert.IsTrue(!clone.Summary.IsEmpty, "Error updating empty string"); Assert.AreEqual(clone.Actors[1].Name, "Actor Name Long 2", "Error merging strings by length"); Assert.AreEqual(clone.Actors[1].TvdbId, _movieSearch.Actors[0].TvdbId, "Error merging actors"); Assert.IsTrue(clone.Actors[1].DateOfDeath.HasValue, "Error merging actors"); }
/// <summary> /// Tries to lookup the Movie online and downloads images. /// </summary> /// <param name="movieInfo">Movie to check</param> /// <returns><c>true</c> if successful</returns> public virtual async Task <bool> FindAndUpdateMovieAsync(MovieInfo movieInfo) { try { // Try online lookup if (!await InitAsync().ConfigureAwait(false)) { return(false); } MovieInfo movieMatch = null; string movieId = null; bool matchFound = false; TLang language = FindBestMatchingLanguage(movieInfo.Languages); if (GetMovieId(movieInfo, out movieId)) { // Prefer memory cache CheckCacheAndRefresh(); if (_memoryCache.TryGetValue(movieId, out movieMatch)) { matchFound = true; } } if (!matchFound) { MovieMatch match = GetStroredMatch(movieInfo); movieMatch = movieInfo.Clone(); if (string.IsNullOrEmpty(movieId)) { Logger.Debug(_id + ": Try to lookup movie \"{0}\" from cache: {1}", movieInfo, match != null && !string.IsNullOrEmpty(match.Id)); if (match != null) { if (SetMovieId(movieMatch, match.Id)) { //If Id was found in cache the online movie info is probably also in the cache if (await _wrapper.UpdateFromOnlineMovieAsync(movieMatch, language, true).ConfigureAwait(false)) { Logger.Debug(_id + ": Found movie {0} in cache", movieInfo.ToString()); matchFound = true; } } else if (string.IsNullOrEmpty(movieId)) { //Match was found but with invalid Id probably to avoid a retry //No Id is available so online search will probably fail again return(false); } } } else { if (match != null && movieId != match.Id) { //Id was changed so remove it so it can be updated _storage.TryRemoveMatch(match); } } if (!matchFound) { Logger.Debug(_id + ": Search for movie {0} online", movieInfo.ToString()); //Try to update movie information from online source if online Ids are present if (!await _wrapper.UpdateFromOnlineMovieAsync(movieMatch, language, false).ConfigureAwait(false)) { //Search for the movie online and update the Ids if a match is found if (await _wrapper.SearchMovieUniqueAndUpdateAsync(movieMatch, language).ConfigureAwait(false)) { //Ids were updated now try to update movie information from online source if (await _wrapper.UpdateFromOnlineMovieAsync(movieMatch, language, false).ConfigureAwait(false)) { matchFound = true; } } } else { matchFound = true; } } } //Always save match even if none to avoid retries StoreMovieMatch(movieInfo, movieMatch); if (matchFound) { movieInfo.MergeWith(movieMatch, true); //Store person matches foreach (PersonInfo person in movieInfo.Actors) { string id; if (GetPersonId(person, out id)) { _actorMatcher.StoreNameMatch(id, person.Name, person.Name); } } foreach (PersonInfo person in movieInfo.Directors) { string id; if (GetPersonId(person, out id)) { _directorMatcher.StoreNameMatch(id, person.Name, person.Name); } } foreach (PersonInfo person in movieInfo.Writers) { string id; if (GetPersonId(person, out id)) { _writerMatcher.StoreNameMatch(id, person.Name, person.Name); } } //Store character matches foreach (CharacterInfo character in movieInfo.Characters) { string id; if (GetCharacterId(character, out id)) { _characterMatcher.StoreNameMatch(id, character.Name, character.Name); } } //Store company matches foreach (CompanyInfo company in movieInfo.ProductionCompanies) { string id; if (GetCompanyId(company, out id)) { _companyMatcher.StoreNameMatch(id, company.Name, company.Name); } } if (GetMovieId(movieInfo, out movieId)) { _memoryCache.TryAdd(movieId, movieInfo); } return(true); } return(false); } catch (Exception ex) { Logger.Debug(_id + ": Exception while processing movie {0}", ex, movieInfo.ToString()); return(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); } }