private async Task <MetadataResult <T> > GetMovieResult <T>(ItemLookupInfo info, CancellationToken cancellationToken) where T : BaseItem, new() { var result = new MetadataResult <T> { Item = new T() }; var imdbId = info.GetProviderId(MetadataProviders.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false); } if (!string.IsNullOrEmpty(imdbId)) { result.Item.SetProviderId(MetadataProviders.Imdb, imdbId); result.HasMetadata = true; await new OmdbProvider(_jsonSerializer, _httpClient).Fetch(result.Item, imdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); } return(result); }
private async Task <MetadataResult <T> > GetMovieResult <T>(ItemLookupInfo info, CancellationToken cancellationToken) where T : Video, new() { var result = new MetadataResult <T> { Item = new T() }; var imdbId = info.GetProviderId(MetadataProviders.Imdb); var searchResult = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false); result.Item.Name = searchResult.Item3; if (string.IsNullOrEmpty(imdbId)) { imdbId = searchResult.Item1; if (!string.IsNullOrEmpty(searchResult.Item2)) { result.Item.SetProviderId(MetadataProviders.Tmdb, searchResult.Item2); } } if (!string.IsNullOrEmpty(imdbId)) { result.Item.SetProviderId(MetadataProviders.Imdb, imdbId); result.HasMetadata = true; await new OmdbProvider(_jsonSerializer, _httpClient).Fetch(result.Item, imdbId, cancellationToken) .ConfigureAwait(false); } return(result); }
public async Task <MetadataResult <T> > GetMetadata(ItemLookupInfo itemId, CancellationToken cancellationToken) { var tmdbId = itemId.GetProviderId(MetadataProviders.Tmdb); var imdbId = itemId.GetProviderId(MetadataProviders.Imdb); // Don't search for music video id's because it is very easy to misidentify. if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo)) { var searchResults = await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(itemId, cancellationToken).ConfigureAwait(false); var searchResult = searchResults.FirstOrDefault(); if (searchResult != null) { tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); } } if (!string.IsNullOrEmpty(tmdbId) || !string.IsNullOrEmpty(imdbId)) { cancellationToken.ThrowIfCancellationRequested(); return(await FetchMovieData(tmdbId, imdbId, itemId.MetadataLanguage, itemId.MetadataCountryCode, cancellationToken).ConfigureAwait(false)); } return(new MetadataResult <T>()); }
public Task <MetadataResult <T> > GetItemMetadata <T>(ItemLookupInfo id, CancellationToken cancellationToken) where T : BaseItem, new() { var movieDb = new GenericMovieDbInfo <T>(_logger, _jsonSerializer, _libraryManager, _fileSystem); return(movieDb.GetMetadata(id, cancellationToken)); }
private RemoteSearchResult ResultToMetadataResult(SearchResult result, ItemLookupInfo searchInfo, int?indexNumberEnd) { var item = new RemoteSearchResult { IndexNumber = searchInfo.IndexNumber, Name = result.Title, ParentIndexNumber = searchInfo.ParentIndexNumber, SearchProviderName = Name, IndexNumberEnd = indexNumberEnd }; item.SetProviderId(MetadataProvider.Imdb, result.imdbID); if (OmdbProvider.TryParseYear(result.Year, out var parsedYear)) { item.ProductionYear = parsedYear; } if (!string.IsNullOrEmpty(result.Released) && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released)) { item.PremiereDate = released; } if (!string.IsNullOrWhiteSpace(result.Poster)) { item.ImageUrl = result.Poster; } return(item); }
private async Task <MetadataResult <T> > GetResult <T>(ItemLookupInfo info, CancellationToken cancellationToken) where T : BaseItem, new() { var result = new MetadataResult <T> { Item = new T(), QueriedById = true }; var imdbId = info.GetProviderId(MetadataProvider.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { imdbId = await GetImdbId(info, cancellationToken).ConfigureAwait(false); result.QueriedById = false; } if (!string.IsNullOrEmpty(imdbId)) { result.Item.SetProviderId(MetadataProvider.Imdb, imdbId); result.HasMetadata = true; await _omdbProvider.Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); } return(result); }
private async Task <MetadataResult <T> > GetMovieResult <T>(ItemLookupInfo info, CancellationToken cancellationToken) where T : BaseItem, new() { var result = new MetadataResult <T> { Item = new T(), QueriedById = true }; var imdbId = info.GetProviderId(MetadataProvider.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false); result.QueriedById = false; } if (!string.IsNullOrEmpty(imdbId)) { result.Item.SetProviderId(MetadataProvider.Imdb, imdbId); result.HasMetadata = true; await new OmdbProvider(_jsonSerializer, _httpClientFactory, _fileSystem, _appHost, _configurationManager).Fetch(result, imdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); } return(result); }
public Task <MetadataResult <T> > GetItemMetadata <T>(ItemLookupInfo id, CancellationToken cancellationToken) where T : Video, new() { var movieDb = new GenericMovieDbInfo <T>(_logger, _jsonSerializer); return(movieDb.GetMetadata(id, cancellationToken)); }
private async Task <string> GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken) { var results = await GetSearchResultsInternal(info, "movie", false, cancellationToken).ConfigureAwait(false); var first = results.FirstOrDefault(); return(first == null ? null : first.GetProviderId(MetadataProvider.Imdb)); }
private EmbyItemData ToEmbyItemData <TEmbyItem>(ItemLookupInfo embyInfo, IMediaItemType <TEmbyItem> itemType, IEnumerable <EmbyItemId> parentIds) where TEmbyItem : BaseItem { var existingIds = embyInfo.ProviderIds.Where(v => int.TryParse(v.Value, out _)) .ToDictionary(k => k.Key, v => int.Parse(v.Value)); return(new EmbyItemData(itemType, new ItemIdentifier(embyInfo.IndexNumber.ToOption(), embyInfo.ParentIndexNumber.ToOption(), embyInfo.Name), existingIds, embyInfo.MetadataLanguage, parentIds)); }
private async Task <Tuple <string, string, string> > GetMovieImdbId(ItemLookupInfo info, CancellationToken cancellationToken) { var result = await new GenericMovieDbInfo <Movie>(_logger, _jsonSerializer).GetMetadata(info, cancellationToken) .ConfigureAwait(false); var imdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Imdb) : null; var tmdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tmdb) : null; var name = result.HasMetadata ? result.Item.Name : null; return(new Tuple <string, string, string>(imdb, tmdb, name)); }
public async Task <IEnumerable <RemoteSearchResult> > GetMovieSearchResults(ItemLookupInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { cancellationToken.ThrowIfCancellationRequested(); var obj = await EnsureMovieInfo(tmdbId, searchInfo.MetadataLanguage, searchInfo.MetadataCountryCode, cancellationToken).ConfigureAwait(false); if (obj == null) { return(new List <RemoteSearchResult>()); } var tmdbSettings = await GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original"); var remoteResult = new RemoteSearchResult { Name = obj.GetTitle(), SearchProviderName = Name, ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path }; if (!string.IsNullOrWhiteSpace(obj.release_date)) { DateTimeOffset r; // These dates are always in this exact format if (DateTimeOffset.TryParse(obj.release_date, _usCulture, DateTimeStyles.None, out r)) { remoteResult.PremiereDate = r.ToUniversalTime(); remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; } } remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture)); if (!string.IsNullOrWhiteSpace(obj.imdb_id)) { remoteResult.SetProviderId(MetadataProviders.Imdb, obj.imdb_id); } return(new[] { remoteResult }); } return(await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(searchInfo, cancellationToken).ConfigureAwait(false)); }
public async Task <List <MediaRoot> > GetSearchResultsFromInfoAsync(ItemLookupInfo info, string format, CancellationToken cancellationToken) { if (info == null) { throw new ArgumentNullException(nameof(info)); } var results = new List <MediaRoot>(); if (info.ProviderIds != null && info.ProviderIds.TryGetValue(Name, out var rawId) && int.TryParse(rawId, out var id)) { _logger.LogCallerInfo($"Id: {id}"); var media = await _api.GetFromIdAsync(id, cancellationToken).ConfigureAwait(false); if (media != null) { results.Add(media); return(results); } _logger.LogCallerWarning($"No Media with Id: {id} found"); } else { _logger.LogCallerWarning($"No Id found for {nameof(info.Name)}: \"{info.Name}\""); } if (!string.IsNullOrEmpty(info.Name)) { var searchResults = await _api.SearchAsync(info.Name, format, cancellationToken).ConfigureAwait(false); if (searchResults?.Count > 0) { results.AddRange(searchResults); return(results); } _logger.LogCallerWarning($"No Results found for {nameof(info.Name)}: \"{info.Name}\""); } else { _logger.LogCallerWarning($"No {nameof(info.Name)} found"); } return(results); }
public async Task<IEnumerable<RemoteSearchResult>> GetMovieSearchResults(ItemLookupInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { cancellationToken.ThrowIfCancellationRequested(); await EnsureMovieInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage); var obj = _jsonSerializer.DeserializeFromFile<MovieResult>(dataFilePath); var tmdbSettings = await GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original"); var remoteResult = new RemoteSearchResult { Name = obj.GetTitle(), SearchProviderName = Name, ImageUrl = string.IsNullOrWhiteSpace(obj.Poster_Path) ? null : tmdbImageUrl + obj.Poster_Path }; if (!string.IsNullOrWhiteSpace(obj.Release_Date)) { // These dates are always in this exact format if (DateTime.TryParse(obj.Release_Date, _usCulture, DateTimeStyles.None, out var r)) { remoteResult.PremiereDate = r.ToUniversalTime(); remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; } } remoteResult.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture)); if (!string.IsNullOrWhiteSpace(obj.Imdb_Id)) { remoteResult.SetProviderId(MetadataProvider.Imdb, obj.Imdb_Id); } return new[] { remoteResult }; } return await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetMovieSearchResults(searchInfo, cancellationToken).ConfigureAwait(false); }
private async Task <Show?> GetIdentifyShow(ItemLookupInfo lookupInfo, TvMazeClient tvMazeClient) { var searchResults = (await tvMazeClient.Search.ShowSearchAsync(lookupInfo.Name?.Trim()).ConfigureAwait(false)).ToList(); if (searchResults.Count == 0) { // No search results. return(null); } if (lookupInfo.Year.HasValue) { return(searchResults.OrderBy( s => DateTime.TryParse(s.Show.Premiered, out var premiereDate) ? Math.Abs(premiereDate.Year - lookupInfo.Year.Value) : 1) .ThenByDescending(s => s.Score) .FirstOrDefault()?.Show); } return(searchResults[0].Show); }
public Task <Either <ProcessFailedResult, IMetadataFoundResult <TEmbyItem> > > GetResultAsync <TEmbyItem>( ItemLookupInfo embyInfo, IMediaItemType <TEmbyItem> itemType, IEnumerable <EmbyItemId> parentIds) where TEmbyItem : BaseItem { var embyItemData = this.ToEmbyItemData(embyInfo, itemType, parentIds); this.log.Debug($"Finding metadata for {embyItemData}"); var mediaItem = this.mediaItemBuilder.Identify(embyItemData, itemType); var fullyRecognisedMediaItem = mediaItem.BindAsync(this.mediaItemBuilder.BuildMediaItem); return(fullyRecognisedMediaItem.BindAsync( mi => itemType.CreateMetadataFoundResult(this.pluginConfiguration, mi, this.logManager)) .MapAsync(r => { this.log.Debug( $"Created metadata with provider Ids: {string.Join(", ", r.EmbyMetadataResult.Item.ProviderIds.Select(kvp => $"{kvp.Key}: {kvp.Value}"))}"); return r; })); }
private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) { // Episode and Season do not support Identify, so the search results are the Series' switch (lookupInfo) { case EpisodeInfo episodeInfo: episodeInfo.SeriesProviderIds = result.ProviderIds; episodeInfo.ProviderIds.Clear(); break; case SeasonInfo seasonInfo: seasonInfo.SeriesProviderIds = result.ProviderIds; seasonInfo.ProviderIds.Clear(); break; default: lookupInfo.ProviderIds = result.ProviderIds; lookupInfo.Name = result.Name; lookupInfo.Year = result.ProductionYear; break; } }
/// <summary> /// Finds the id from music brainz. /// </summary> /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{System.String}.</returns> private async Task <string> FindId(ItemLookupInfo item, CancellationToken cancellationToken) { // They seem to throw bad request failures on any term with a slash var nameToSearch = item.Name.Replace('/', ' '); var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); var ns = new XmlNamespaceManager(doc.NameTable); ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); var node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns); if (node != null && node.Value != null) { return(node.Value); } if (HasDiacritics(item.Name)) { // Try again using the search with accent characters url url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false); ns = new XmlNamespaceManager(doc.NameTable); ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); node = doc.SelectSingleNode("//mb:artist-list/mb:artist/@id", ns); if (node != null && node.Value != null) { return(node.Value); } } return(null); }
public Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken) { return(GetSearchResultsInternal(searchInfo, type, true, cancellationToken)); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken) { bool isSearch = false; var episodeSearchInfo = searchInfo as EpisodeInfo; var list = new List <RemoteSearchResult>(); var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); var url = "http://www.omdbapi.com/?plot=full&r=json"; if (type == "episode" && episodeSearchInfo != null) { episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); } var name = searchInfo.Name; var year = searchInfo.Year; if (!string.IsNullOrWhiteSpace(name)) { var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year = year ?? yearInName; } if (string.IsNullOrWhiteSpace(imdbId)) { if (year.HasValue) { url += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture); } // &s means search and returns a list of results as opposed to t if (enableMultipleResults) { url += "&s=" + WebUtility.UrlEncode(name); } else { url += "&t=" + WebUtility.UrlEncode(name); } url += "&type=" + type; isSearch = true; } else { url += "&i=" + imdbId; } if (type == "episode") { if (searchInfo.IndexNumber.HasValue) { url += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber); } if (searchInfo.ParentIndexNumber.HasValue) { url += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber); } } using (var stream = await _httpClient.Get(new HttpRequestOptions { Url = url, ResourcePool = OmdbProvider.ResourcePool, CancellationToken = cancellationToken }).ConfigureAwait(false)) { var resultList = new List <SearchResult>(); if (isSearch) { var searchResultList = _jsonSerializer.DeserializeFromStream <SearchResultList>(stream); if (searchResultList != null && searchResultList.Search != null) { resultList.AddRange(searchResultList.Search); } } else { var result = _jsonSerializer.DeserializeFromStream <SearchResult>(stream); if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase)) { resultList.Add(result); } } foreach (var result in resultList) { var item = new RemoteSearchResult { IndexNumber = searchInfo.IndexNumber, Name = result.Title, ParentIndexNumber = searchInfo.ParentIndexNumber, ProviderIds = searchInfo.ProviderIds, SearchProviderName = Name }; if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue) { item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value; } item.SetProviderId(MetadataProviders.Imdb, result.imdbID); int parsedYear; if (result.Year.Length > 0 && int.TryParse(result.Year.Substring(0, Math.Min(result.Year.Length, 4)), NumberStyles.Any, CultureInfo.InvariantCulture, out parsedYear)) { item.ProductionYear = parsedYear; } DateTime released; if (!string.IsNullOrEmpty(result.Released) && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out released)) { item.PremiereDate = released; } if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase)) { item.ImageUrl = result.Poster; } list.Add(item); } } return(list); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResultsInternal(ItemLookupInfo searchInfo, bool isSearch, CancellationToken cancellationToken) { var type = searchInfo switch { EpisodeInfo => "episode", SeriesInfo => "series", _ => "movie" }; // This is a bit hacky? var episodeSearchInfo = searchInfo as EpisodeInfo; var indexNumberEnd = episodeSearchInfo?.IndexNumberEnd; var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); var urlQuery = new StringBuilder("plot=full&r=json"); if (episodeSearchInfo != null) { episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out imdbId); if (searchInfo.IndexNumber.HasValue) { urlQuery.Append("&Episode=").Append(searchInfo.IndexNumber.Value); } if (searchInfo.ParentIndexNumber.HasValue) { urlQuery.Append("&Season=").Append(searchInfo.ParentIndexNumber.Value); } } if (string.IsNullOrWhiteSpace(imdbId)) { var name = searchInfo.Name; var year = searchInfo.Year; if (!string.IsNullOrWhiteSpace(name)) { var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year ??= yearInName; } if (year.HasValue) { urlQuery.Append("&y=").Append(year); } // &s means search and returns a list of results as opposed to t urlQuery.Append(isSearch ? "&s=" : "&t="); urlQuery.Append(WebUtility.UrlEncode(name)); urlQuery.Append("&type=") .Append(type); } else { urlQuery.Append("&i=") .Append(imdbId); isSearch = false; } var url = OmdbProvider.GetOmdbUrl(urlQuery.ToString()); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); if (isSearch) { var searchResultList = await JsonSerializer.DeserializeAsync <SearchResultList>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (searchResultList?.Search != null) { var resultCount = searchResultList.Search.Count; var result = new RemoteSearchResult[resultCount]; for (var i = 0; i < resultCount; i++) { result[i] = ResultToMetadataResult(searchResultList.Search[i], searchInfo, indexNumberEnd); } return(result); } } else { var result = await JsonSerializer.DeserializeAsync <SearchResult>(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); if (string.Equals(result?.Response, "true", StringComparison.OrdinalIgnoreCase)) { return(new[] { ResultToMetadataResult(result, searchInfo, indexNumberEnd) }); } } return(Enumerable.Empty <RemoteSearchResult>()); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken) { var name = idInfo.Name; var year = idInfo.Year; if (string.IsNullOrWhiteSpace(name)) { return(new List <RemoteSearchResult>()); } var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original"); // TODO: Investigate: Does this mean we are reparsing already parsed ItemLookupInfo? var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year ??= yearInName; _logger.LogInformation("TmdbSearch: Finding id for item: {0} ({1})", name, year); var language = idInfo.MetadataLanguage.ToLowerInvariant(); // Replace sequences of non-word characters with space // TMDB expects a space separated list of words make sure that is the case name = _cleanNonWord.Replace(name, " ").Trim(); var results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0) { //try in english if wasn't before if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } // TODO: retrying alternatives should be done outside the search // provider so that the retry logic can be common for all search // providers if (results.Count == 0) { var name2 = parsedName.Name; // Remove things enclosed in []{}() etc name2 = _cleanEnclosed.Replace(name2, string.Empty); // Replace sequences of non-word characters with space name2 = _cleanNonWord.Replace(name2, " "); // Clean based on common stop words / tokens name2 = _cleanStopWords.Replace(name2, string.Empty); // Trim whitespace name2 = name2.Trim(); // Search again if the new name is different if (!string.Equals(name2, name) && !string.IsNullOrWhiteSpace(name2)) { _logger.LogInformation("TmdbSearch: Finding id for item: {0} ({1})", name2, year); results = await GetSearchResults(name2, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { //one more time, in english results = await GetSearchResults(name2, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } } return(results.Where(i => { if (year.HasValue && i.ProductionYear.HasValue) { // Allow one year tolerance return Math.Abs(year.Value - i.ProductionYear.Value) <= 1; } return true; })); }
public Task <IEnumerable <RemoteSearchResult> > GetMovieSearchResults(ItemLookupInfo idInfo, CancellationToken cancellationToken) { return(GetSearchResults(idInfo, "movie", cancellationToken)); }
private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) { lookupInfo.ProviderIds = result.ProviderIds; lookupInfo.Name = result.Name; lookupInfo.Year = result.ProductionYear; }
private void FillLookupData(ItemLookupInfo lookupInfo, IHasMetadata item, MetadataRawTable table) { var propInfos = GetItemProperties(lookupInfo.GetType()); var name = lookupInfo.Name; if (lookupInfo.Year.HasValue) { name = string.Format("{0} ({1})", name, lookupInfo.Year.Value); } table.LookupData.Add(new KeyValuePair <string, object>("Name", name)); foreach (var propInfo in propInfos) { switch (propInfo.Name) { case "ProviderIds": table.LookupData.Add(new KeyValuePair <string, object>(propInfo.Name, FlattenProviderIds(lookupInfo.ProviderIds, item, ", "))); break; case "SeriesProviderIds": var seasonInfo = lookupInfo as SeasonInfo; if (seasonInfo != null) { table.LookupData.Add(new KeyValuePair <string, object>(propInfo.Name, FlattenProviderIds(seasonInfo.SeriesProviderIds, new Series(), ", "))); } var episodeInfo = lookupInfo as EpisodeInfo; if (episodeInfo != null) { table.LookupData.Add(new KeyValuePair <string, object>(propInfo.Name, FlattenProviderIds(episodeInfo.SeriesProviderIds, new Series(), ", "))); } break; case "Name": case "Year": case "IsAutomated": case "MetadataCountryCode": break; default: var value = propInfo.GetValue(lookupInfo); if (value != null) { if (propInfo.PropertyType == typeof(DateTime?)) { DateTime?dateValue = (DateTime?)value; table.LookupData.Add(new KeyValuePair <string, object>(propInfo.Name, dateValue.Value.ToString(CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern))); } else { table.LookupData.Add(new KeyValuePair <string, object>(propInfo.Name, value)); } } break; } } }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken) { var list = new List <RemoteSearchResult>(); var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); var url = "http://www.omdbapi.com/?plot=short&r=json"; var name = searchInfo.Name; var year = searchInfo.Year; if (!string.IsNullOrWhiteSpace(name)) { var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year = year ?? yearInName; } if (string.IsNullOrWhiteSpace(imdbId)) { if (year.HasValue) { url += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture); } url += "&t=" + WebUtility.UrlEncode(name); url += "&type=" + type; } else { url += "&i=" + imdbId; } using (var stream = await _httpClient.Get(new HttpRequestOptions { Url = url, ResourcePool = OmdbProvider.ResourcePool, CancellationToken = cancellationToken, CacheMode = CacheMode.Unconditional, CacheLength = TimeSpan.FromDays(2) }).ConfigureAwait(false)) { var result = _jsonSerializer.DeserializeFromStream <SearchResult>(stream); if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase)) { var item = new RemoteSearchResult(); item.SearchProviderName = Name; item.Name = result.Title; item.SetProviderId(MetadataProviders.Imdb, result.imdbID); int parsedYear; if (int.TryParse(result.Year, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedYear)) { item.ProductionYear = parsedYear; } if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase)) { item.ImageUrl = result.Poster; } list.Add(item); } } return(list); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool isSearch, CancellationToken cancellationToken) { var episodeSearchInfo = searchInfo as EpisodeInfo; var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); var urlQuery = "plot=full&r=json"; if (type == "episode" && episodeSearchInfo != null) { episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out imdbId); } var name = searchInfo.Name; var year = searchInfo.Year; if (!string.IsNullOrWhiteSpace(name)) { var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year ??= yearInName; } if (string.IsNullOrWhiteSpace(imdbId)) { if (year.HasValue) { urlQuery += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture); } // &s means search and returns a list of results as opposed to t if (isSearch) { urlQuery += "&s=" + WebUtility.UrlEncode(name); } else { urlQuery += "&t=" + WebUtility.UrlEncode(name); } urlQuery += "&type=" + type; } else { urlQuery += "&i=" + imdbId; isSearch = false; } if (type == "episode") { if (searchInfo.IndexNumber.HasValue) { urlQuery += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber); } if (searchInfo.ParentIndexNumber.HasValue) { urlQuery += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber); } } var url = OmdbProvider.GetOmdbUrl(urlQuery); using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var resultList = new List <SearchResult>(); if (isSearch) { var searchResultList = await _jsonSerializer.DeserializeFromStreamAsync <SearchResultList>(stream).ConfigureAwait(false); if (searchResultList != null && searchResultList.Search != null) { resultList.AddRange(searchResultList.Search); } } else { var result = await _jsonSerializer.DeserializeFromStreamAsync <SearchResult>(stream).ConfigureAwait(false); if (string.Equals(result.Response, "true", StringComparison.OrdinalIgnoreCase)) { resultList.Add(result); } } return(resultList.Select(result => { var item = new RemoteSearchResult { IndexNumber = searchInfo.IndexNumber, Name = result.Title, ParentIndexNumber = searchInfo.ParentIndexNumber, SearchProviderName = Name }; if (episodeSearchInfo != null && episodeSearchInfo.IndexNumberEnd.HasValue) { item.IndexNumberEnd = episodeSearchInfo.IndexNumberEnd.Value; } item.SetProviderId(MetadataProvider.Imdb, result.imdbID); if (result.Year.Length > 0 && int.TryParse(result.Year.AsSpan().Slice(0, Math.Min(result.Year.Length, 4)), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) { item.ProductionYear = parsedYear; } if (!string.IsNullOrEmpty(result.Released) && DateTime.TryParse(result.Released, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out var released)) { item.PremiereDate = released; } if (!string.IsNullOrWhiteSpace(result.Poster) && !string.Equals(result.Poster, "N/A", StringComparison.OrdinalIgnoreCase)) { item.ImageUrl = result.Poster; } return item; })); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken) { var name = idInfo.Name; var year = idInfo.Year; if (string.IsNullOrWhiteSpace(name)) { return(new List <RemoteSearchResult>()); } var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original"); if (!string.IsNullOrWhiteSpace(name)) { var parsedName = _libraryManager.ParseName(name); var yearInName = parsedName.Year; name = parsedName.Name; year = year ?? yearInName; } _logger.Info("MovieDbProvider: Finding id for item: " + name); var language = idInfo.MetadataLanguage.ToLower(); //nope - search for it //var searchType = item is BoxSet ? "collection" : "movie"; var results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0) { //try in english if wasn't before if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } if (results.Count == 0) { // try with dot and _ turned to space var originalName = name; name = name.Replace(",", " "); name = name.Replace(".", " "); name = name.Replace("_", " "); name = name.Replace("-", " "); name = name.Replace("!", " "); name = name.Replace("?", " "); var parenthIndex = name.IndexOf('('); if (parenthIndex != -1) { name = name.Substring(0, parenthIndex); } name = name.Trim(); // Search again if the new name is different if (!string.Equals(name, originalName)) { results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { //one more time, in english results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } } return(results.Where(i => { if (year.HasValue && i.ProductionYear.HasValue) { // Allow one year tolerance return Math.Abs(year.Value - i.ProductionYear.Value) <= 1; } return true; })); }
private async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken) { var name = idInfo.Name; var year = idInfo.Year; int?yearInName = null; var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.base_url + "original"; NameParser.ParseName(name, out name, out yearInName); year = year ?? yearInName; _logger.Info("MovieDbProvider: Finding id for item: " + name); var language = idInfo.MetadataLanguage.ToLower(); //nope - search for it //var searchType = item is BoxSet ? "collection" : "movie"; var results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0) { //try in english if wasn't before if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } if (results.Count == 0) { // try with dot and _ turned to space var originalName = name; name = name.Replace(",", " "); name = name.Replace(".", " "); name = name.Replace("_", " "); name = name.Replace("-", " "); name = name.Replace("!", " "); name = name.Replace("?", " "); name = name.Trim(); // Search again if the new name is different if (!string.Equals(name, originalName)) { results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { //one more time, in english results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } } } return(results.Where(i => { if (year.HasValue && i.ProductionYear.HasValue) { return year.Value == i.ProductionYear.Value; } return true; })); }