async Task <IEnumerable <RemoteSubtitleInfo> > ISubtitleProvider.Search(SubtitleSearchRequest request, CancellationToken cancellationToken) { var imdbIdText = request.GetProviderId(MetadataProviders.Imdb); long imdbId = 0; _logger.LogDebug($"{ToDump(request)}"); //_logger.LogDebug($"Imdb id: {imdbIdText}"); switch (request.ContentType) { case VideoContentType.Episode: if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName)) { _logger.LogDebug("Episode information missing"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } break; case VideoContentType.Movie: if (string.IsNullOrEmpty(request.Name)) { _logger.LogDebug("Movie name missing"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, _usCulture, out imdbId)) { //_logger.LogDebug($"Imdb id: `{imdbIdText}` - media name: {request.Name}"); _logger.LogDebug("Imdb id missing"); //return Enumerable.Empty<RemoteSubtitleInfo>(); } break; } if (string.IsNullOrEmpty(request.MediaPath)) { _logger.LogDebug("Path Missing"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } await Login(cancellationToken).ConfigureAwait(false); var subLanguageId = NormalizeLanguage(request.Language); string hash; using (var fileStream = File.OpenRead(request.MediaPath)) { hash = Utilities.ComputeHash(fileStream); } var fileInfo = _fileSystem.GetFileInfo(request.MediaPath); var movieByteSize = fileInfo.Length; //For movies, the imdb id is ued. var searchImdbId = request.ContentType == VideoContentType.Movie && imdbId != 0 ? imdbId.ToString(_usCulture) : ""; var subtitleSearchParameters = new List <SubtitleSearchParameters>(); switch (request.ContentType) { case VideoContentType.Episode: subtitleSearchParameters = new List <SubtitleSearchParameters> { new SubtitleSearchParameters(subLanguageId, query: request.SeriesName, season: request.ParentIndexNumber.Value.ToString(_usCulture), episode: request.IndexNumber.Value.ToString(_usCulture)) }; break; case VideoContentType.Movie: subtitleSearchParameters = new List <SubtitleSearchParameters> { }; if (!string.IsNullOrEmpty(searchImdbId)) { subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId)); subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId)); } else { subtitleSearchParameters.Add(new SubtitleSearchParameters(subLanguageId, query: request.Name)); } break; } var parms = new List <SubtitleSearchParameters> { new SubtitleSearchParameters(subLanguageId, movieHash: hash, movieByteSize: movieByteSize, imdbid: searchImdbId), }; parms.AddRange(subtitleSearchParameters); if (_rateLimitLeft == 0) { await Task.Delay(1000); } //_logger.LogDebug($"Search params: {ToDump(parms)}"); IMethodResponse searchResult = null; try { var searchResponse = await OpenSubtitlesHandler.OpenSubtitles .SearchSubtitlesAsync(parms.ToArray(), cancellationToken) .ConfigureAwait(false); searchResult = searchResponse.Item1; //_logger.LogDebug($"Search result: {ToDump(searchResult)}"); _rateLimitLeft = searchResponse.Item2 ?? _rateLimitLeft; if (searchResponse.Item2 != null) { if (_rateLimitLeft <= 4) { await Task.Delay(250); } } } catch (Exception ex) { _logger.LogError($"Error while fetching subtitles from opensubtitles.\n{ex}\n{ex.StackTrace}"); } if (!(searchResult is MethodResponseSubtitleSearch)) { _logger.LogError("Invalid response type"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } //Check if we got a 401 error from opensubtitles if (searchResult.Status.Contains("401")) { _logger.LogError("Not authorized to OpenSubtitles"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } Predicate <SubtitleSearchResult> mediaFilter = x => { switch (request.ContentType) { case VideoContentType.Episode: return(!string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) && int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber && int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber); case VideoContentType.Movie: if (imdbId == 0) { return(x.MovieName.Contains(request.Name)); } else { return(!string.IsNullOrEmpty(x.IDMovieImdb) && long.Parse(x.IDMovieImdb, _usCulture) == imdbId); } } return(false); }; var results = ((MethodResponseSubtitleSearch)searchResult).Results; // Avoid implicitly captured closure var hasCopy = hash; return(results.Where(x => x.SubBad == "0" && mediaFilter(x) && (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase))) .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1)) .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize)) .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture)) .ThenByDescending(x => double.Parse(x.SubRating, _usCulture)) .Select(i => new RemoteSubtitleInfo { Author = i.UserNickName, Comment = i.SubAuthorComment, CommunityRating = float.Parse(i.SubRating, _usCulture), DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture), Format = i.SubFormat, ProviderName = Name, ThreeLetterISOLanguageName = i.SubLanguageID, Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile, Name = i.SubFileName, DateCreated = DateTime.Parse(i.SubAddDate, _usCulture), IsHashMatch = i.MovieHash == hasCopy }).Where(i => !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase))); }
private void FillDataGrid(IMethodResponse<Northwind.CustomersDataTable> methodResponse) { if(CustomersDataGridView.InvokeRequired) { CustomersDataGridView.BeginInvoke(new Action<IMethodResponse<Northwind.CustomersDataTable>>(FillDataGrid), methodResponse); return; } CustomersDataGridView.DataSource = methodResponse.ReturnValue; CustomersDataGridView.Update(); }