/// <inheritdoc /> public async Task <IEnumerable <RemoteSubtitleInfo> > Search(SubtitleSearchRequest request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } await Login(cancellationToken).ConfigureAwait(false); if (request.IsAutomated && _login?.User?.RemainingDownloads <= 0) { if (_lastRatelimitLog == null || DateTime.UtcNow.Subtract(_lastRatelimitLog.Value).TotalSeconds > 60) { _logger.LogInformation("Daily download limit reached, returning no results for automated task"); _lastRatelimitLog = DateTime.UtcNow; } return(Enumerable.Empty <RemoteSubtitleInfo>()); } long.TryParse(request.GetProviderId(MetadataProvider.Imdb)?.TrimStart('t') ?? string.Empty, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbId); if (request.ContentType == VideoContentType.Episode && (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName))) { _logger.LogDebug("Episode information missing"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } if (string.IsNullOrEmpty(request.MediaPath)) { _logger.LogDebug("Path Missing"); return(Enumerable.Empty <RemoteSubtitleInfo>()); } var language = await GetLanguage(request.TwoLetterISOLanguageName, cancellationToken).ConfigureAwait(false); string hash; try { #pragma warning disable CA2007 await using var fileStream = File.OpenRead(request.MediaPath); #pragma warning restore CA2007 hash = OpenSubtitlesRequestHelper.ComputeHash(fileStream); } catch (IOException ex) { throw new IOException(string.Format(CultureInfo.InvariantCulture, "IOException while computing hash for {0}", request.MediaPath), ex); } var options = new Dictionary <string, string> { { "languages", language }, { "moviehash", hash }, { "type", request.ContentType == VideoContentType.Episode ? "episode" : "movie" } }; // If we have the IMDb ID we use that, otherwise query with the details if (imdbId != 0) { options.Add("imdb_id", imdbId.ToString(CultureInfo.InvariantCulture)); } else { options.Add("query", Path.GetFileName(request.MediaPath)); if (request.ContentType == VideoContentType.Episode) { if (request.ParentIndexNumber.HasValue) { options.Add("season_number", request.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (request.IndexNumber.HasValue) { options.Add("episode_number", request.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } } } if (request.IsPerfectMatch) { options.Add("moviehash_match", "only"); } _logger.LogDebug("Search query: {Query}", options); var searchResponse = await OpenSubtitlesHandler.OpenSubtitles.SearchSubtitlesAsync(options, ApiKey, cancellationToken).ConfigureAwait(false); if (!searchResponse.Ok) { _logger.LogError("Invalid response: {Code} - {Body}", searchResponse.Code, searchResponse.Body); return(Enumerable.Empty <RemoteSubtitleInfo>()); } bool MediaFilter(ResponseData x) => x.Attributes?.FeatureDetails?.FeatureType == (request.ContentType == VideoContentType.Episode ? "Episode" : "Movie") && request.ContentType == VideoContentType.Episode ? x.Attributes.FeatureDetails.SeasonNumber == request.ParentIndexNumber && x.Attributes.FeatureDetails.EpisodeNumber == request.IndexNumber : x.Attributes?.FeatureDetails?.ImdbId == imdbId; if (searchResponse.Data == null) { return(Enumerable.Empty <RemoteSubtitleInfo>()); } return(searchResponse.Data .Where(x => MediaFilter(x) && (!request.IsPerfectMatch || (x.Attributes?.MovieHashMatch ?? false))) .OrderByDescending(x => x.Attributes?.MovieHashMatch ?? false) .ThenByDescending(x => x.Attributes?.DownloadCount) .ThenByDescending(x => x.Attributes?.Ratings) .ThenByDescending(x => x.Attributes?.FromTrusted) .Select(i => new RemoteSubtitleInfo { Author = i.Attributes?.Uploader?.Name, Comment = i.Attributes?.Comments, CommunityRating = i.Attributes?.Ratings, DownloadCount = i.Attributes?.DownloadCount, Format = "srt", ProviderName = Name, ThreeLetterISOLanguageName = request.Language, Id = $"srt-{request.Language}-{i.Attributes?.Files[0].FileId}", Name = i.Attributes?.Release, DateCreated = i.Attributes?.UploadDate, IsHashMatch = i.Attributes?.MovieHashMatch }) .Where(i => !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase))); }
public void ComputeHash_Success(string filename, string hash) { using var str = File.OpenRead(Path.Join("Test Data", filename)); Assert.Equal(hash, OpenSubtitlesRequestHelper.ComputeHash(str)); }