public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var tmdbId)) { var series = await _tmdbClientManager .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); if (series != null) { var remoteResult = MapTvShowToRemoteSearchResult(series); return(new[] { remoteResult }); } } if (searchInfo.TryGetProviderId(MetadataProvider.Imdb, out var imdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); var tvResults = findResult?.TvResults; if (tvResults != null) { var imdbIdResults = new RemoteSearchResult[tvResults.Count]; for (var i = 0; i < tvResults.Count; i++) { var remoteResult = MapSearchTvToRemoteSearchResult(tvResults[i]); remoteResult.SetProviderId(MetadataProvider.Imdb, imdbId); imdbIdResults[i] = remoteResult; } return(imdbIdResults); } } if (searchInfo.TryGetProviderId(MetadataProvider.Tvdb, out var tvdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(tvdbId, FindExternalSource.TvDb, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); var tvResults = findResult?.TvResults; if (tvResults != null) { var tvIdResults = new RemoteSearchResult[tvResults.Count]; for (var i = 0; i < tvResults.Count; i++) { var remoteResult = MapSearchTvToRemoteSearchResult(tvResults[i]); remoteResult.SetProviderId(MetadataProvider.Tvdb, tvdbId); tvIdResults[i] = remoteResult; } return(tvIdResults); } } var tvSearchResults = await _tmdbClientManager.SearchSeriesAsync(searchInfo.Name, searchInfo.MetadataLanguage, cancellationToken : cancellationToken) .ConfigureAwait(false); var remoteResults = new RemoteSearchResult[tvSearchResults.Count]; for (var i = 0; i < tvSearchResults.Count; i++) { remoteResults[i] = MapSearchTvToRemoteSearchResult(tvSearchResults[i]); } return(remoteResults); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } if (searchDate.HasValue) { searchTitle += $"&year={searchDate.Value.Year}"; } var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodes("//div[contains(@class, 'item')]"); foreach (var searchResult in searchResults) { var sceneURL = searchResult.SelectSingleNode(".//a").Attributes["href"].Value; if (!sceneURL.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { sceneURL = Helper.GetSearchBaseURL(siteNum) + sceneURL; } if (sceneURL.Contains("/films/", StringComparison.OrdinalIgnoreCase) || sceneURL.Contains("/massage/", StringComparison.OrdinalIgnoreCase)) { string curID = $"{siteNum[0]}#{siteNum[1]}#{Helper.Encode(sceneURL)}", sceneName = searchResult.SelectSingleNode(".//img").Attributes["alt"].Value, scenePoster = searchResult.SelectSingleNode(".//img").Attributes["data-src"].Value, sceneDate = searchResult.SelectSingleNode(".//div[@class='details']/span[last()]").InnerText.Trim(); var res = new RemoteSearchResult { Name = sceneName, ImageUrl = scenePoster, }; if (!string.IsNullOrEmpty(sceneDate)) { sceneDate = sceneDate .Replace("nd", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("th", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("rd", string.Empty, StringComparison.OrdinalIgnoreCase) .Replace("st", string.Empty, StringComparison.OrdinalIgnoreCase); if (DateTime.TryParseExact(sceneDate, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } } res.ProviderIds.Add(Plugin.Instance.Name, curID); result.Add(res); } } return(result); }
private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) { lookupInfo.ProviderIds = result.ProviderIds; lookupInfo.Name = result.Name; lookupInfo.Year = result.ProductionYear; }
private async Task <Series> AutoDetectSeries( string seriesName, int?seriesYear, TvFileOrganizationOptions options, CancellationToken cancellationToken) { if (options.AutoDetectSeries) { RemoteSearchResult finalResult = null; #region Search One var seriesInfo = new SeriesInfo { Name = seriesName, Year = seriesYear }; var searchResultsTask = await _providerManager.GetRemoteSearchResults <Series, SeriesInfo>(new RemoteSearchQuery <SeriesInfo> { SearchInfo = seriesInfo }, cancellationToken); #endregion // Group series by name and year (if 2 series with the exact same name, the same year ...) var groupedResult = searchResultsTask.GroupBy(p => new { p.Name, p.ProductionYear }, p => p, (key, g) => new { Key = key, Result = g.ToList() }).ToList(); if (groupedResult.Count == 1) { finalResult = groupedResult.First().Result.First(); } else if (groupedResult.Count > 1) { var filtredResult = groupedResult .Select(i => new { Ref = i, Score = NameUtils.GetMatchScore(seriesName, seriesYear, i.Key.Name, i.Key.ProductionYear) }) .Where(i => i.Score > 0) .OrderByDescending(i => i.Score) .Select(i => i.Ref) .FirstOrDefault(); finalResult = filtredResult?.Result.First(); } if (finalResult != null) { // We are in the good position, we can create the item var organizationRequest = new EpisodeFileOrganizationRequest { NewSeriesName = finalResult.Name, NewSeriesProviderIds = finalResult.ProviderIds, NewSeriesYear = finalResult.ProductionYear, TargetFolder = options.DefaultSeriesLibraryPath }; return(await CreateNewSeries(organizationRequest, finalResult, options, cancellationToken).ConfigureAwait(false)); } } return(null); }
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, _appHost, cancellationToken); using (var response = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false)) { using (var stream = response.Content) { 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.Substring(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> > FindSeriesInternal(string name, string language, CancellationToken cancellationToken) { var url = string.Format(SeriesSearchUrl, WebUtility.UrlEncode(name), language.ToLower()); var doc = new XmlDocument(); using (var results = await _httpClient.Get(new HttpRequestOptions { Url = url, ResourcePool = TvDbResourcePool, CancellationToken = cancellationToken }).ConfigureAwait(false)) { doc.Load(results); } var searchResults = new List <RemoteSearchResult>(); if (doc.HasChildNodes) { var nodes = doc.SelectNodes("//Series"); var comparableName = GetComparableName(name); if (nodes != null) { foreach (XmlNode node in nodes) { var searchResult = new RemoteSearchResult { SearchProviderName = Name }; var titles = new List <string>(); var nameNode = node.SelectSingleNode("./SeriesName"); if (nameNode != null) { titles.Add(GetComparableName(nameNode.InnerText)); } var aliasNode = node.SelectSingleNode("./AliasNames"); if (aliasNode != null) { var alias = aliasNode.InnerText.Split('|').Select(GetComparableName); titles.AddRange(alias); } var imdbIdNode = node.SelectSingleNode("./IMDB_ID"); if (imdbIdNode != null) { var val = imdbIdNode.InnerText; if (!string.IsNullOrWhiteSpace(val)) { searchResult.SetProviderId(MetadataProviders.Imdb, val); } } var bannerNode = node.SelectSingleNode("./banner"); if (bannerNode != null) { var val = bannerNode.InnerText; if (!string.IsNullOrWhiteSpace(val)) { searchResult.ImageUrl = TVUtils.BannerUrl + val; } } if (titles.Any(t => string.Equals(t, comparableName, StringComparison.OrdinalIgnoreCase))) { var id = node.SelectSingleNode("./seriesid") ?? node.SelectSingleNode("./id"); if (id != null) { searchResult.Name = titles.FirstOrDefault(); searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText); searchResults.Add(searchResult); } } foreach (var title in titles) { _logger.Info("TVDb Provider - " + title + " did not match " + comparableName); } } } } _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org."); return(searchResults); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); if (!data.SelectSingleText("//title").Contains("Search for", StringComparison.OrdinalIgnoreCase)) { var sceneURL = new Uri(data.SelectSingleText("//div[@class='user--guest']//a/@href")); var sceneID = new string[] { Helper.Encode(sceneURL.AbsolutePath) }; var searchResult = await Helper.GetSearchResultsFromUpdate(this, siteNum, sceneID, searchDate, cancellationToken).ConfigureAwait(false); if (searchResult.Any()) { result.AddRange(searchResult); } } else { var searchResults = data.SelectNodesSafe("//div[@class='thumbnails']/div"); foreach (var searchResult in searchResults) { var sceneURL = new Uri(searchResult.SelectSingleText(".//a/@href")); string curID = Helper.Encode(sceneURL.AbsolutePath), sceneName = searchResult.SelectSingleText(".//div[contains(@class, 'thumbnail-title')]//a"), sceneDate = searchResult.SelectSingleText("./@release"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, }; if (DateTime.TryParseExact(sceneDate, "yyyy/MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } var scenePoster = searchResult.SelectSingleText(".//div[@class='thumbnail-image']/a/@style"); if (!string.IsNullOrEmpty(scenePoster)) { scenePoster = scenePoster.Split('(')[1].Split(')')[0]; } if (!string.IsNullOrEmpty(scenePoster)) { res.ImageUrl = scenePoster; } result.Add(res); } } return(result); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } string searchJAVID = null; var splitedTitle = searchTitle.Split(); if (splitedTitle.Length > 1 && int.TryParse(splitedTitle[1], out _)) { searchJAVID = $"{splitedTitle[0]}-{splitedTitle[1]}"; } if (!string.IsNullOrEmpty(searchJAVID)) { searchTitle = searchJAVID; } foreach (var site in Database.SiteList.Sites[siteNum[0]]) { siteNum[1] = site.Key; var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodesSafe("//div[@class='videos']//div[@class='video']"); if (searchResults.Any()) { foreach (var searchResult in searchResults) { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + $"/en/?v={searchResult.SelectSingleText(".//a/@id")}"); string curID = Helper.Encode(sceneURL.PathAndQuery), sceneName = searchResult.SelectSingleText(".//div[@class='title']"), scenePoster = $"http:{searchResult.SelectSingleText(".//img/@src").Replace("ps.", "pl.", StringComparison.OrdinalIgnoreCase)}", javID = searchResult.SelectSingleText(".//div[@class='id']"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = $"{javID} {sceneName}", ImageUrl = scenePoster, }; if (!string.IsNullOrEmpty(searchJAVID)) { res.IndexNumber = 100 - LevenshteinDistance.Calculate(searchJAVID, javID, StringComparison.OrdinalIgnoreCase); } result.Add(res); } } else { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + data.SelectSingleText("//div[@id='video_title']//a/@href")); var sceneID = new string[] { Helper.Encode(sceneURL.PathAndQuery) }; var searchResult = await Helper.GetSearchResultsFromUpdate(this, siteNum, sceneID, searchDate, cancellationToken).ConfigureAwait(false); if (searchResult.Any()) { result.AddRange(searchResult); } } if (result.Any()) { break; } } return(result); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = Convert.ToInt32(searchInfo.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture); if (tmdbId == 0) { var movieResults = await _tmdbClientManager .SearchMovieAsync(searchInfo.Name, searchInfo.Year ?? 0, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); var remoteSearchResults = new List <RemoteSearchResult>(); for (var i = 0; i < movieResults.Count; i++) { var movieResult = movieResults[i]; var remoteSearchResult = new RemoteSearchResult { Name = movieResult.Title ?? movieResult.OriginalTitle, ImageUrl = _tmdbClientManager.GetPosterUrl(movieResult.PosterPath), Overview = movieResult.Overview, SearchProviderName = Name }; var releaseDate = movieResult.ReleaseDate?.ToUniversalTime(); remoteSearchResult.PremiereDate = releaseDate; remoteSearchResult.ProductionYear = releaseDate?.Year; remoteSearchResult.SetProviderId(MetadataProvider.Tmdb, movieResult.Id.ToString(CultureInfo.InvariantCulture)); remoteSearchResults.Add(remoteSearchResult); } return(remoteSearchResults); } var movie = await _tmdbClientManager .GetMovieAsync(tmdbId, searchInfo.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(searchInfo.MetadataLanguage), cancellationToken) .ConfigureAwait(false); var remoteResult = new RemoteSearchResult { Name = movie.Title ?? movie.OriginalTitle, SearchProviderName = Name, ImageUrl = _tmdbClientManager.GetPosterUrl(movie.PosterPath), Overview = movie.Overview }; if (movie.ReleaseDate != null) { var releaseDate = movie.ReleaseDate.Value.ToUniversalTime(); remoteResult.PremiereDate = releaseDate; remoteResult.ProductionYear = releaseDate.Year; } remoteResult.SetProviderId(MetadataProvider.Tmdb, movie.Id.ToString(CultureInfo.InvariantCulture)); if (!string.IsNullOrWhiteSpace(movie.ImdbId)) { remoteResult.SetProviderId(MetadataProvider.Imdb, movie.ImdbId); } return(new[] { remoteResult }); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var splitedSearchTitle = searchTitle.Split(); var movieID = string.Empty; if (int.TryParse(splitedSearchTitle[0], out _) && int.TryParse(splitedSearchTitle[1], out _)) { var separator = string.Empty; switch (siteNum[1]) { case 0: separator = "-"; break; case 1: separator = "_"; break; } if (!string.IsNullOrEmpty(separator)) { movieID = splitedSearchTitle[0] + separator + splitedSearchTitle[1]; } } if (!string.IsNullOrEmpty(movieID)) { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + $"/eng/moviepages/{movieID}/index.html"); var sceneID = new string[] { Helper.Encode(sceneURL.AbsolutePath) }; var searchResult = await Helper.GetSearchResultsFromUpdate(this, siteNum, sceneID, searchDate, cancellationToken).ConfigureAwait(false); if (searchResult.Any()) { result.AddRange(searchResult); } } else { var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodesSafe("//div[contains(@class, 'list') or contains(@class, 'is-movie')]//div[@class='grid-item']"); foreach (var searchResult in searchResults) { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + searchResult.SelectSingleText(".//div[@class='meta-title']/a/@href")); string curID = Helper.Encode(sceneURL.AbsolutePath), sceneName = searchResult.SelectSingleText(".//div[@class='meta-title']"), sceneDate = searchResult.SelectSingleText(".//div[@class='meta-data']"), scenePoster = Helper.GetSearchBaseURL(siteNum) + searchResult.SelectSingleText(".//div[@class='media-thum']//img/@src"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, ImageUrl = scenePoster, }; if (DateTime.TryParseExact(sceneDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } result.Add(res); } } return(result); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var tmdbId)) { var series = await _tmdbClientManager .GetSeriesAsync(Convert.ToInt32(tmdbId, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); if (series != null) { var remoteResult = MapTvShowToRemoteSearchResult(series); return(new[] { remoteResult }); } } if (searchInfo.TryGetProviderId(MetadataProvider.Imdb, out var imdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(imdbId, FindExternalSource.Imdb, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); var tvResults = findResult?.TvResults; if (tvResults != null) { var imdbIdResults = new RemoteSearchResult[tvResults.Count]; for (var i = 0; i < tvResults.Count; i++) { var remoteResult = MapSearchTvToRemoteSearchResult(tvResults[i]); remoteResult.SetProviderId(MetadataProvider.Imdb, imdbId); imdbIdResults[i] = remoteResult; } return(imdbIdResults); } } if (searchInfo.TryGetProviderId(MetadataProvider.Tvdb, out var tvdbId)) { var findResult = await _tmdbClientManager .FindByExternalIdAsync(tvdbId, FindExternalSource.TvDb, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); var tvResults = findResult?.TvResults; if (tvResults != null) { var tvIdResults = new RemoteSearchResult[tvResults.Count]; for (var i = 0; i < tvResults.Count; i++) { var remoteResult = MapSearchTvToRemoteSearchResult(tvResults[i]); remoteResult.SetProviderId(MetadataProvider.Tvdb, tvdbId); tvIdResults[i] = remoteResult; } return(tvIdResults); } } var tvSearchResults = await _tmdbClientManager.SearchSeriesAsync(searchInfo.Name, searchInfo.MetadataLanguage, cancellationToken : cancellationToken) .ConfigureAwait(false); var tmdbSearchResults = new TMDbLib.Objects.TvShows.TvShow[tvSearchResults.Count]; var remoteResults = new RemoteSearchResult[tvSearchResults.Count]; for (var i = 0; i < tvSearchResults.Count; i++) { tmdbSearchResults[i] = await _tmdbClientManager .GetSeriesAsync(Convert.ToInt32(tvSearchResults[i].Id, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); remoteResults[i] = MapTvShowToRemoteSearchResult(tmdbSearchResults[i]); } int resultCountHelper = 0; for (var i = 0; i < remoteResults.Length; i++) { resultCountHelper += 1 + remoteResults[i].EpisodeGroups.Results.Count; } var remoteResultEpisodeGroups = new RemoteSearchResult[resultCountHelper]; for (var i = 0; i < remoteResultEpisodeGroups.Length; i++) { for (var j = 0; j < tmdbSearchResults.Length; j++) { remoteResultEpisodeGroups[i++] = MapTvShowToRemoteSearchResult(tmdbSearchResults[j]); for (var k = 0; k < tmdbSearchResults[j].EpisodeGroups.Results.Count; k++) { remoteResultEpisodeGroups[i++] = MapTvShowEpisodeGroupToRemoteSearchResult(tmdbSearchResults[j], k); } } } return(remoteResultEpisodeGroups); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } if (searchDate.HasValue) { var date = searchDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); var url = $"{Helper.GetSearchSearchURL(siteNum)}/date/{date}/{date}"; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodesSafe("//div[contains(@class, 'content-grid-item')]"); foreach (var searchResult in searchResults) { string sceneID = searchResult.SelectSingleText(".//span[@class='title']/a/@href").Split('/')[3], curID = $"{siteNum[0]}#{siteNum[1]}#{sceneID}", sceneName = searchResult.SelectSingleText(".//span[@class='title']/a | //h2"), posterURL = searchResult.SelectSingleText(".//noscript/picture/img/@src"), sceneDate = searchResult.SelectSingleText(".//span[@class='date']"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, ImageUrl = posterURL, }; if (DateTime.TryParseExact(sceneDate, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } result.Add(res); } } else { if (int.TryParse(searchTitle.Split()[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var sceneID)) { var sceneURL = $"{Helper.GetSearchSearchURL(siteNum)}watch/{sceneID}"; var data = await HTML.ElementFromURL(sceneURL, cancellationToken).ConfigureAwait(false); var sceneData = data.SelectSingleNode("//div[contains(@class, 'content-pane-title')]"); if (sceneData != null) { string curID = $"{siteNum[0]}#{siteNum[1]}#{sceneID.ToString(CultureInfo.InvariantCulture)}", sceneName = sceneData.SelectSingleText("//h2"), posterURL = sceneData.SelectSingleText("//video/@poster"), sceneDate = sceneData.SelectSingleText("//span[@class='date']"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, ImageUrl = posterURL, }; if (DateTime.TryParseExact(sceneDate, "MMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } result.Add(res); } } } return(result); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken) { var results = new List <RemoteSearchResult>(); var httpRequestOptions = new HttpRequestOptions { CancellationToken = cancellationToken, }; if (searchInfo.ProviderIds.TryGetValue("isbn", out string isbn)) { httpRequestOptions.Url = $"{baseUrl}ISBN:{isbn}"; using (var resp = await _httpClient.GetResponse(httpRequestOptions).ConfigureAwait(false)) { var openLibrarySearch = await _json.DeserializeFromStreamAsync <Dictionary <string, OpenLibraryResp> >(resp.Content).ConfigureAwait(false); foreach (var book in openLibrarySearch) { var remoteSearchResult = new RemoteSearchResult { Name = book.Value.title, SearchProviderName = Name }; if (book.Value.authors != null) { remoteSearchResult.AlbumArtist = new RemoteSearchResult { Name = book.Value.authors.FirstOrDefault().name, SearchProviderName = Name }; var artists = new List <RemoteSearchResult>(); foreach (var author in book.Value.authors) { artists.Add(new RemoteSearchResult { Name = author.name, SearchProviderName = Name }); } remoteSearchResult.Artists = artists.ToArray(); } if (book.Key != null) { remoteSearchResult.ProviderIds.Add("isbn", book.Key); } if (book.Value.cover != null) { remoteSearchResult.ImageUrl = book.Value.cover.large; } results.Add(remoteSearchResult); } } } else { httpRequestOptions.Url = $"{searchUrl}\"{HttpUtility.UrlEncode(searchInfo.Name)}\""; using (var resp = await _httpClient.GetResponse(httpRequestOptions).ConfigureAwait(false)) { var openLibrarySearch = await _json.DeserializeFromStreamAsync <OpenLibrarySearch>(resp.Content).ConfigureAwait(false); foreach (var doc in openLibrarySearch.docs) { var remoteSearchResult = new RemoteSearchResult { Name = doc.title, SearchProviderName = Name }; if (doc.isbn != null) { remoteSearchResult.ProviderIds.Add("isbn", doc.isbn.FirstOrDefault()); } if (doc.cover_i != null) { remoteSearchResult.ImageUrl = $"https://covers.openlibrary.org/b/id/{doc.cover_i}-L.jpg"; } if (doc.author_name != null) { remoteSearchResult.AlbumArtist = new RemoteSearchResult { Name = doc.author_name.FirstOrDefault(), SearchProviderName = Name }; var artists = new List <RemoteSearchResult>(); foreach (var author in doc.author_name) { artists.Add(new RemoteSearchResult { Name = author, SearchProviderName = Name }); } remoteSearchResult.Artists = artists.ToArray(); } if (doc.first_publish_year != null) { remoteSearchResult.ProductionYear = doc.first_publish_year; } results.Add(remoteSearchResult); } } } return(results); }
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>()); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(ItemLookupInfo searchInfo, string type, CancellationToken cancellationToken) { bool isSearch = false; 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); } // &s means search and returns a list of results as opposed to t url += "&s=" + WebUtility.UrlEncode(name); url += "&type=" + type; isSearch = true; } 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 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(); item.SearchProviderName = Name; item.Name = result.Title; 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; } 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> > FindSeriesInternal(string name, CancellationToken cancellationToken) { // TODO: Support returning more data, including image url's for the identify function var url = string.Format(RootUrl + SeriesQuery, WebUtility.UrlEncode(name)); var doc = new XmlDocument(); using (var results = await _httpClient.Get(new HttpRequestOptions { Url = url, ResourcePool = TvDbResourcePool, CancellationToken = cancellationToken }).ConfigureAwait(false)) { doc.Load(results); } var searchResults = new List <RemoteSearchResult>(); if (doc.HasChildNodes) { var nodes = doc.SelectNodes("//Series"); var comparableName = GetComparableName(name); if (nodes != null) { foreach (XmlNode node in nodes) { var titles = new List <string>(); var nameNode = node.SelectSingleNode("./SeriesName"); if (nameNode != null) { titles.Add(GetComparableName(nameNode.InnerText)); } var aliasNode = node.SelectSingleNode("./AliasNames"); if (aliasNode != null) { var alias = aliasNode.InnerText.Split('|').Select(GetComparableName); titles.AddRange(alias); } if (titles.Any(t => string.Equals(t, comparableName, StringComparison.OrdinalIgnoreCase))) { var id = node.SelectSingleNode("./seriesid"); if (id != null) { var searchResult = new RemoteSearchResult { Name = titles.FirstOrDefault(), SearchProviderName = Name }; searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText); searchResults.Add(searchResult); } } foreach (var title in titles) { _logger.Info("TVDb Provider - " + title + " did not match " + comparableName); } } } } _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org."); return(searchResults); }
private async Task <Tuple <Movie, RemoteSearchResult> > AutoDetectMovie(string movieName, int?movieYear, FileOrganizationResult result, MovieFileOrganizationOptions options, CancellationToken cancellationToken) { if (options.AutoDetectMovie) { var parsedName = _libraryManager.ParseName(movieName); var yearInName = parsedName.Year; var nameWithoutYear = parsedName.Name; RemoteSearchResult finalResult = null; if (string.IsNullOrWhiteSpace(nameWithoutYear)) { nameWithoutYear = movieName; } if (!yearInName.HasValue) { yearInName = movieYear; } #region Search One var movieInfo = new MovieInfo { Name = nameWithoutYear, Year = yearInName, }; var searchResultsTask = await _providerManager.GetRemoteSearchResults <Movie, MovieInfo>(new RemoteSearchQuery <MovieInfo> { SearchInfo = movieInfo }, cancellationToken); #endregion // Group movies by name and year (if 2 movie with the exact same name, the same year ...) var groupedResult = searchResultsTask.GroupBy(p => new { p.Name, p.ProductionYear }, p => p, (key, g) => new { Key = key, Result = g.ToList() }).ToList(); if (groupedResult.Count == 1) { finalResult = groupedResult.First().Result.First(); } else if (groupedResult.Count > 1) { var filtredResult = groupedResult .Select(i => new { Ref = i, Score = NameUtils.GetMatchScore(nameWithoutYear, yearInName, i.Key.Name, i.Key.ProductionYear) }) .Where(i => i.Score > 0) .OrderByDescending(i => i.Score) .Select(i => i.Ref) .FirstOrDefault(); finalResult = filtredResult?.Result.First(); } if (finalResult != null) { // We are in the good position, we can create the item var organizationRequest = new MovieFileOrganizationRequest { NewMovieName = finalResult.Name, NewMovieProviderIds = finalResult.ProviderIds, NewMovieYear = finalResult.ProductionYear, TargetFolder = options.DefaultMovieLibraryPath }; var movie = CreateNewMovie(organizationRequest, result.OriginalPath, options, cancellationToken); return(new Tuple <Movie, RemoteSearchResult>(movie, finalResult)); } } return(null); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) { if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var id)) { var movie = await _tmdbClientManager .GetMovieAsync( int.Parse(id, CultureInfo.InvariantCulture), searchInfo.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(searchInfo.MetadataLanguage), cancellationToken) .ConfigureAwait(false); var remoteResult = new RemoteSearchResult { Name = movie.Title ?? movie.OriginalTitle, SearchProviderName = Name, ImageUrl = _tmdbClientManager.GetPosterUrl(movie.PosterPath), Overview = movie.Overview }; if (movie.ReleaseDate != null) { var releaseDate = movie.ReleaseDate.Value.ToUniversalTime(); remoteResult.PremiereDate = releaseDate; remoteResult.ProductionYear = releaseDate.Year; } remoteResult.SetProviderId(MetadataProvider.Tmdb, movie.Id.ToString(CultureInfo.InvariantCulture)); if (!string.IsNullOrWhiteSpace(movie.ImdbId)) { remoteResult.SetProviderId(MetadataProvider.Imdb, movie.ImdbId); } return(new[] { remoteResult }); } IReadOnlyList <SearchMovie> movieResults; if (searchInfo.TryGetProviderId(MetadataProvider.Imdb, out id)) { var result = await _tmdbClientManager.FindByExternalIdAsync( id, FindExternalSource.Imdb, TmdbUtils.GetImageLanguagesParam(searchInfo.MetadataLanguage), cancellationToken).ConfigureAwait(false); movieResults = result.MovieResults; } else if (searchInfo.TryGetProviderId(MetadataProvider.Tvdb, out id)) { var result = await _tmdbClientManager.FindByExternalIdAsync( id, FindExternalSource.TvDb, TmdbUtils.GetImageLanguagesParam(searchInfo.MetadataLanguage), cancellationToken).ConfigureAwait(false); movieResults = result.MovieResults; } else { movieResults = await _tmdbClientManager .SearchMovieAsync(searchInfo.Name, searchInfo.Year ?? 0, searchInfo.MetadataLanguage, cancellationToken) .ConfigureAwait(false); } var len = movieResults.Count; var remoteSearchResults = new RemoteSearchResult[len]; for (var i = 0; i < len; i++) { var movieResult = movieResults[i]; var remoteSearchResult = new RemoteSearchResult { Name = movieResult.Title ?? movieResult.OriginalTitle, ImageUrl = _tmdbClientManager.GetPosterUrl(movieResult.PosterPath), Overview = movieResult.Overview, SearchProviderName = Name }; var releaseDate = movieResult.ReleaseDate?.ToUniversalTime(); remoteSearchResult.PremiereDate = releaseDate; remoteSearchResult.ProductionYear = releaseDate?.Year; remoteSearchResult.SetProviderId(MetadataProvider.Tmdb, movieResult.Id.ToString(CultureInfo.InvariantCulture)); remoteSearchResults[i] = remoteSearchResult; } return(remoteSearchResults); }
private async Task <List <RemoteSearchResult> > GetSearchResultsTv(string name, int?year, string language, string baseImageUrl, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("String can't be null or empty.", nameof(name)); } string url3; if (year == null) { url3 = string.Format( CultureInfo.InvariantCulture, SearchUrl, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv"); } else { url3 = string.Format( CultureInfo.InvariantCulture, SearchUrlTvWithYear, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, year); } using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3); foreach (var header in TmdbUtils.AcceptHeaders) { requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header)); } using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var searchResults = await _json.DeserializeFromStreamAsync <TmdbSearchResult <TvResult> >(stream).ConfigureAwait(false); var results = searchResults.Results ?? new List <TvResult>(); return(results .Select(i => { var remoteResult = new RemoteSearchResult { SearchProviderName = TmdbMovieProvider.Current.Name, Name = i.Name ?? i.Original_Name, ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path }; if (!string.IsNullOrWhiteSpace(i.First_Air_Date)) { // These dates are always in this exact format if (DateTime.TryParseExact(i.First_Air_Date, "yyyy-MM-dd", _usCulture, DateTimeStyles.None, out var r)) { remoteResult.PremiereDate = r.ToUniversalTime(); remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; } } remoteResult.SetProviderId(MetadataProvider.Tmdb, i.Id.ToString(_usCulture)); return remoteResult; }) .ToList()); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var splitedSearchTitle = searchTitle.Split(); var movieID = string.Empty; if (int.TryParse(splitedSearchTitle[0], out _)) { movieID = splitedSearchTitle[0]; } if (!string.IsNullOrEmpty(movieID)) { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + $"/moviepages/{movieID}/index.html"); var sceneID = new string[] { Helper.Encode(sceneURL.AbsolutePath) }; var searchResult = await Helper.GetSearchResultsFromUpdate(this, siteNum, sceneID, searchDate, cancellationToken).ConfigureAwait(false); if (searchResult.Any()) { result.AddRange(searchResult); } } else { var url = string.Format(CultureInfo.InvariantCulture, Helper.GetSearchSearchURL(siteNum), searchTitle); var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodesSafe("//div[@id='movies']//div[contains(@class, 'movie')]"); foreach (var searchResult in searchResults) { var sceneURL = new Uri(Helper.GetSearchBaseURL(siteNum) + $"/en/?v={searchResult.SelectSingleText(".//a/@href")}"); string curID = Helper.Encode(sceneURL.AbsolutePath), sceneName = searchResult.SelectSingleText(".//a[@class='actor']"), sceneDate = searchResult.SelectSingleText(".//p[@class='release']").Replace("Release:", string.Empty, StringComparison.OrdinalIgnoreCase).Trim(), scenePoster = Helper.GetSearchBaseURL(siteNum) + searchResult.SelectSingleText(".//img/@data-original"); var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, ImageUrl = scenePoster, }; if (DateTime.TryParseExact(sceneDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } result.Add(res); } } return(result); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var searchSceneID = searchTitle.Split()[0]; if (!int.TryParse(searchSceneID, out _)) { searchSceneID = null; } string apiKEY = await GetAPIKey(siteNum, cancellationToken).ConfigureAwait(false), searchParams; var sceneTypes = new List <string> { "scenes", "movies" }; foreach (var sceneType in sceneTypes) { if (!string.IsNullOrEmpty(searchSceneID)) { if (sceneType == "scenes") { searchParams = $"filters=clip_id={searchSceneID}"; } else { searchParams = $"filters=movie_id={searchSceneID}"; } } else { searchParams = $"query={searchTitle}"; } var url = $"{Helper.GetSearchSearchURL(siteNum)}?x-algolia-application-id=TSMKFA364Q&x-algolia-api-key={apiKEY}"; var searchResults = await GetDataFromAPI(url, $"all_{sceneType}", Helper.GetSearchBaseURL(siteNum), searchParams, cancellationToken).ConfigureAwait(false); if (searchResults == null) { return(result); } foreach (JObject searchResult in searchResults["results"].First["hits"]) { string sceneID, sceneName = (string)searchResult["title"], curID; DateTime?sceneDateObj; if (sceneType == "scenes") { sceneDateObj = (DateTime?)searchResult["release_date"]; sceneID = (string)searchResult["clip_id"]; } else { var dateField = searchResult["last_modified"] != null ? "last_modified" : "date_created"; sceneDateObj = (DateTime?)searchResult[dateField]; sceneID = (string)searchResult["movie_id"]; } var res = new RemoteSearchResult { Name = sceneName, }; curID = $"{siteNum[0]}#{siteNum[1]}#{sceneType}#{sceneID}"; if (sceneDateObj.HasValue) { var sceneDate = sceneDateObj.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); curID += $"#{sceneDate}"; res.PremiereDate = sceneDateObj; } res.ProviderIds.Add(Plugin.Instance.Name, curID); if (searchResult.ContainsKey("pictures")) { var images = searchResult["pictures"].Where(o => !o.ToString().Contains("resized", StringComparison.OrdinalIgnoreCase)); if (images.Any()) { res.ImageUrl = $"https://images-fame.gammacdn.com/movies/{(string)images.Last()}"; } } result.Add(res); } } return(result); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null) { return(result); } var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); var searchResults = data.SelectNodesSafe("//div[contains(@class, 'item') and contains(@class, 'hover')]"); foreach (var searchResult in searchResults) { string sceneURL = searchResult.SelectSingleText(".//a/@href"), curID = $"{siteNum[0]}#{siteNum[1]}#{Helper.Encode(sceneURL)}", sceneName = searchResult.SelectSingleText(".//div[contains(@class, 'item-info')]//a"), sceneDate = searchResult.SelectSingleText(".//span[@class='date']"), scenePoster = string.Empty; var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, }; var scenePosterNode = searchResult.SelectSingleNode(".//img"); if (scenePosterNode.Attributes.Contains("src0_1x")) { scenePoster = scenePosterNode.Attributes["src0_1x"].Value; } else { if (scenePosterNode.Attributes.Contains("src")) { scenePoster = scenePosterNode.Attributes["src"].Value; } } if (!string.IsNullOrEmpty(scenePoster)) { if (!scenePoster.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { scenePoster = Helper.GetSearchBaseURL(siteNum) + scenePoster; } res.ImageUrl = scenePoster; } if (DateTime.TryParseExact(sceneDate, "MMMM d, yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } result.Add(res); } return(result); }
private async Task <List <RemoteSearchResult> > FindSeriesInternal(string name, string language, CancellationToken cancellationToken) { var comparableName = GetComparableName(name); var list = new List <Tuple <List <string>, RemoteSearchResult> >(); TvDbResponse <SeriesSearchResult[]> result; try { result = await _tvdbClientManager.GetSeriesByNameAsync(comparableName, language, cancellationToken) .ConfigureAwait(false); } catch (TvDbServerException e) { _logger.LogError(e, "No series results found for {Name}", comparableName); return(new List <RemoteSearchResult>()); } foreach (var seriesSearchResult in result.Data) { var tvdbTitles = new List <string> { GetComparableName(seriesSearchResult.SeriesName) }; tvdbTitles.AddRange(seriesSearchResult.Aliases.Select(GetComparableName)); DateTime.TryParse(seriesSearchResult.FirstAired, out var firstAired); var remoteSearchResult = new RemoteSearchResult { Name = tvdbTitles.FirstOrDefault(), ProductionYear = firstAired.Year, SearchProviderName = Name }; if (!string.IsNullOrEmpty(seriesSearchResult.Banner)) { // Results from their Search endpoints already include the /banners/ part in the url, because reasons... remoteSearchResult.ImageUrl = TvdbUtils.TvdbImageBaseUrl + seriesSearchResult.Banner; } try { var seriesSesult = await _tvdbClientManager.GetSeriesByIdAsync(seriesSearchResult.Id, language, cancellationToken) .ConfigureAwait(false); remoteSearchResult.SetProviderId(MetadataProvider.Imdb, seriesSesult.Data.ImdbId); remoteSearchResult.SetProviderId(MetadataProvider.Zap2It, seriesSesult.Data.Zap2itId); } catch (TvDbServerException e) { _logger.LogError(e, "Unable to retrieve series with id {TvdbId}", seriesSearchResult.Id); } remoteSearchResult.SetProviderId(MetadataProvider.Tvdb, seriesSearchResult.Id.ToString()); list.Add(new Tuple <List <string>, RemoteSearchResult>(tvdbTitles, remoteSearchResult)); } return(list .OrderBy(i => i.Item1.Contains(comparableName, StringComparer.OrdinalIgnoreCase) ? 0 : 1) .ThenBy(i => list.IndexOf(i)) .Select(i => i.Item2) .ToList()); }
private async Task <List <RemoteSearchResult> > FindSeriesInternal(string name, string language, CancellationToken cancellationToken) { var parsedName = _libraryManager.ParseName(name); var comparableName = GetComparableName(parsedName.Name); var list = new List <Tuple <List <string>, RemoteSearchResult> >(); TvDbResponse <SeriesSearchResult[]> result; try { result = await _tvdbClientManager.GetSeriesByNameAsync(comparableName, language, cancellationToken) .ConfigureAwait(false); } catch (TvDbServerException e) { _logger.LogError(e, "No series results found for {Name}", comparableName); return(new List <RemoteSearchResult>()); } foreach (var seriesSearchResult in result.Data) { var tvdbTitles = new List <string> { seriesSearchResult.SeriesName }; tvdbTitles.AddRange(seriesSearchResult.Aliases); DateTime?firstAired = null; if (DateTime.TryParse(seriesSearchResult.FirstAired, out var parsedFirstAired)) { firstAired = parsedFirstAired; } var remoteSearchResult = new RemoteSearchResult { Name = tvdbTitles.FirstOrDefault(), ProductionYear = firstAired?.Year, SearchProviderName = Name }; if (!string.IsNullOrEmpty(seriesSearchResult.Poster)) { // Results from their Search endpoints already include the /banners/ part in the url, because reasons... remoteSearchResult.ImageUrl = TvdbUtils.TvdbBaseUrl + seriesSearchResult.Poster.TrimStart('/'); } try { var seriesSesult = await _tvdbClientManager.GetSeriesByIdAsync(seriesSearchResult.Id, language, cancellationToken) .ConfigureAwait(false); remoteSearchResult.SetProviderId(MetadataProvider.Imdb, seriesSesult.Data.ImdbId); remoteSearchResult.SetProviderId(MetadataProvider.Zap2It, seriesSesult.Data.Zap2itId); } catch (TvDbServerException e) { _logger.LogError(e, "Unable to retrieve series with id {TvdbId}", seriesSearchResult.Id); } remoteSearchResult.SetProviderId(TvdbPlugin.ProviderId, seriesSearchResult.Id.ToString(CultureInfo.InvariantCulture)); list.Add(new Tuple <List <string>, RemoteSearchResult>(tvdbTitles, remoteSearchResult)); } return(list .OrderBy(i => i.Item1.Contains(name, StringComparer.OrdinalIgnoreCase) ? 0 : 1) .ThenBy(i => i.Item1.Any(title => title.Contains(parsedName.Name, StringComparison.OrdinalIgnoreCase)) ? 0 : 1) .ThenBy(i => i.Item2.ProductionYear.HasValue && i.Item2.ProductionYear.Equals(parsedName.Year) ? 0 : 1) .ThenBy(i => i.Item1.Any(title => title.Contains(comparableName, StringComparison.OrdinalIgnoreCase)) ? 0 : 1) .ThenBy(i => list.IndexOf(i)) .Select(i => i.Item2) .Take(MaxSearchResults) // TVDB returns a lot of unrelated results .ToList()); }
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); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; if (!string.IsNullOrEmpty(tmdbId)) { await EnsurePersonInfo(tmdbId, cancellationToken).ConfigureAwait(false); var dataFilePath = GetPersonDataFilePath(_configurationManager.ApplicationPaths, tmdbId); var info = _jsonSerializer.DeserializeFromFile <PersonResult>(dataFilePath); var images = (info.images ?? new Images()).profiles ?? new List <Profile>(); var result = new RemoteSearchResult { Name = info.name, SearchProviderName = Name, ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path) }; result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture)); result.SetProviderId(MetadataProviders.Imdb, info.imdb_id); return(new[] { result }); } if (searchInfo.IsAutomated) { lock (_requestCountLock) { if ((DateTime.UtcNow - _lastRequestCountReset).TotalHours >= 1) { _requestCount = 0; _lastRequestCountReset = DateTime.UtcNow; } var requestCount = _requestCount; if (requestCount >= 40) { //_logger.Debug("Throttling Tmdb people"); // This needs to be throttled return(new List <RemoteSearchResult>()); } _requestCount = requestCount + 1; } } var url = string.Format(@"https://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey); using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { Url = url, CancellationToken = cancellationToken, AcceptHeader = MovieDbProvider.AcceptHeader }).ConfigureAwait(false)) { var result = _jsonSerializer.DeserializeFromStream <PersonSearchResults>(json) ?? new PersonSearchResults(); return(result.Results.Select(i => GetSearchResult(i, tmdbImageUrl))); } }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var searchSceneID = searchTitle.Split()[0]; var sceneTypes = new List <string> { "scene", "movie", "serie" }; if (!int.TryParse(searchSceneID, out _)) { searchSceneID = null; } var instanceToken = await GetToken(siteNum, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(instanceToken)) { return(result); } foreach (var sceneType in sceneTypes) { string url; if (string.IsNullOrEmpty(searchSceneID)) { url = $"/v2/releases?type={sceneType}&search={searchTitle}"; } else { url = $"/v2/releases?type={sceneType}&id={searchSceneID}"; } var searchResults = await GetDataFromAPI(Helper.GetSearchSearchURL(siteNum) + url, instanceToken, cancellationToken).ConfigureAwait(false); if (searchResults == null) { break; } foreach (var searchResult in searchResults["result"]) { string sceneID = (string)searchResult["id"], curID = $"{sceneID}#{sceneType}", sceneName = (string)searchResult["title"], scenePoster = string.Empty; var sceneDateObj = (DateTime)searchResult["dateReleased"]; var imageTypes = new List <string> { "poster", "cover" }; foreach (var imageType in imageTypes) { if (searchResult["images"].Type == JTokenType.Object && searchResult["images"][imageType] != null) { foreach (var image in searchResult["images"][imageType]) { scenePoster = (string)image["xx"]["url"]; } } } var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, ImageUrl = scenePoster, PremiereDate = sceneDateObj, }; result.Add(res); } } return(result); }
public async Task <IEnumerable <RemoteSearchResult> > GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb); if (!string.IsNullOrEmpty(tmdbId)) { cancellationToken.ThrowIfCancellationRequested(); await EnsureSeriesInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage); var obj = _jsonSerializer.DeserializeFromFile <SeriesResult>(dataFilePath); var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); var tmdbImageUrl = tmdbSettings.images.GetImageUrl("original"); var remoteResult = new RemoteSearchResult { Name = obj.Name, SearchProviderName = Name, ImageUrl = string.IsNullOrWhiteSpace(obj.Poster_Path) ? null : tmdbImageUrl + obj.Poster_Path }; remoteResult.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture)); remoteResult.SetProviderId(MetadataProvider.Imdb, obj.External_Ids.Imdb_Id); if (obj.External_Ids.Tvdb_Id > 0) { remoteResult.SetProviderId(MetadataProvider.Tvdb, obj.External_Ids.Tvdb_Id.Value.ToString(_usCulture)); } return(new[] { remoteResult }); } var imdbId = searchInfo.GetProviderId(MetadataProvider.Imdb); if (!string.IsNullOrEmpty(imdbId)) { var searchResult = await FindByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false); if (searchResult != null) { return(new[] { searchResult }); } } var tvdbId = searchInfo.GetProviderId(MetadataProvider.Tvdb); if (!string.IsNullOrEmpty(tvdbId)) { var searchResult = await FindByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false); if (searchResult != null) { return(new[] { searchResult }); } } return(await new TmdbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false)); }
public async Task <List <RemoteSearchResult> > Search(int[] siteNum, string searchTitle, DateTime?searchDate, CancellationToken cancellationToken) { var result = new List <RemoteSearchResult>(); if (siteNum == null || string.IsNullOrEmpty(searchTitle)) { return(result); } var url = Helper.GetSearchSearchURL(siteNum) + searchTitle; var data = await HTML.ElementFromURL(url, cancellationToken).ConfigureAwait(false); if (!data.SelectSingleNode("//title").InnerText.Contains("Search for", StringComparison.OrdinalIgnoreCase)) { string sceneURL = data.SelectSingleNode("//div[@class='user--guest']//a").Attributes["href"].Value, curID = $"{siteNum[0]}#{siteNum[1]}#{Helper.Encode(sceneURL)}"; var sceneID = curID.Split('#').Skip(2).ToArray(); var searchResult = await Helper.GetSearchResultsFromUpdate(this, siteNum, sceneID, cancellationToken).ConfigureAwait(false); if (searchResult.Any()) { result.AddRange(searchResult); } } else { var searchResults = data.SelectNodes("//div[@class='thumbnails']/div"); foreach (var searchResult in searchResults) { string sceneURL = searchResult.SelectSingleNode(".//a").Attributes["href"].Value, curID = $"{siteNum[0]}#{siteNum[1]}#{Helper.Encode(sceneURL)}", sceneName = searchResult.SelectSingleNode(".//div[contains(@class, 'thumbnail-title')]//a").InnerText, scenePoster = string.Empty, sceneDate = searchResult.SelectSingleNode(".").Attributes["release"].Value; var res = new RemoteSearchResult { ProviderIds = { { Plugin.Instance.Name, curID } }, Name = sceneName, }; if (DateTime.TryParseExact(sceneDate, "yyyy/MM/dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var sceneDateObj)) { res.PremiereDate = sceneDateObj; } var scenePosterNode = searchResult.SelectSingleNode(".//div[@class='thumbnail-image']/a"); if (scenePosterNode != null && scenePosterNode.Attributes.Contains("style")) { scenePoster = scenePosterNode.Attributes["style"].Value.Split('(')[1].Split(')')[0]; } if (!string.IsNullOrEmpty(scenePoster)) { res.ImageUrl = scenePoster; } result.Add(res); } } return(result); }