mirror of
https://github.com/jellyfin/jellyfin-plugin-opensubtitles.git
synced 2024-11-23 06:09:51 +00:00
Merge pull request #87 from MBR-0001/apollo
This commit is contained in:
commit
ee797cbc81
@ -199,12 +199,10 @@ namespace Jellyfin.Plugin.OpenSubtitles
|
||||
Comment = i.Attributes?.Comments,
|
||||
CommunityRating = i.Attributes?.Ratings,
|
||||
DownloadCount = i.Attributes?.DownloadCount,
|
||||
Format = i.Attributes?.Format ?? "srt",
|
||||
Format = "srt",
|
||||
ProviderName = Name,
|
||||
ThreeLetterISOLanguageName = request.Language,
|
||||
|
||||
// new API (currently) does not return the format
|
||||
Id = $"{i.Attributes?.Format ?? "srt"}-{request.Language}-{i.Attributes?.Files[0].FileId}",
|
||||
Id = $"srt-{request.Language}-{i.Attributes?.Files[0].FileId}",
|
||||
Name = i.Attributes?.Release,
|
||||
DateCreated = i.Attributes?.UploadDate,
|
||||
IsHashMatch = i.Attributes?.MovieHashMatch
|
||||
@ -314,7 +312,7 @@ namespace Jellyfin.Plugin.OpenSubtitles
|
||||
|
||||
var res = await OpenSubtitlesHandler.OpenSubtitles.DownloadSubtitleAsync(info.Data.Link, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!res.Ok || string.IsNullOrWhiteSpace(res.Data))
|
||||
if (res.Code != HttpStatusCode.OK || string.IsNullOrWhiteSpace(res.Body))
|
||||
{
|
||||
var msg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
@ -325,7 +323,7 @@ namespace Jellyfin.Plugin.OpenSubtitles
|
||||
throw new HttpRequestException(msg);
|
||||
}
|
||||
|
||||
return new SubtitleResponse { Format = format, Language = language, Stream = new MemoryStream(Encoding.UTF8.GetBytes(res.Data)) };
|
||||
return new SubtitleResponse { Format = format, Language = language, Stream = new MemoryStream(Encoding.UTF8.GetBytes(res.Body)) };
|
||||
}
|
||||
|
||||
private async Task Login(CancellationToken cancellationToken)
|
||||
|
@ -42,12 +42,6 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler.Models
|
||||
Body = response.Reason;
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(string))
|
||||
{
|
||||
Data = (T)(object)Body;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Ok)
|
||||
{
|
||||
// don't bother parsing json if HTTP status code is bad
|
||||
|
@ -15,12 +15,6 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler.Models.Responses
|
||||
[JsonPropertyName("download_count")]
|
||||
public int DownloadCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle format.
|
||||
/// </summary>
|
||||
[JsonPropertyName("format")]
|
||||
public string? Format { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the subtitle rating.
|
||||
/// </summary>
|
||||
|
@ -20,12 +20,6 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler.Models.Responses
|
||||
[JsonPropertyName("remaining")]
|
||||
public int Remaining { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message.
|
||||
/// </summary>
|
||||
[JsonPropertyName("message")]
|
||||
public string? Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the reset time.
|
||||
/// </summary>
|
||||
|
@ -26,7 +26,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
public static async Task<ApiResponse<LoginInfo>> LogInAsync(string username, string password, string apiKey, CancellationToken cancellationToken)
|
||||
{
|
||||
var body = new { username, password };
|
||||
var response = await RequestHandler.SendRequestAsync("/login", HttpMethod.Post, body, null, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
var response = await RequestHandler.SendRequestAsync("/login", HttpMethod.Post, body, null, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<LoginInfo>(response);
|
||||
}
|
||||
@ -47,7 +47,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
|
||||
var headers = new Dictionary<string, string> { { "Authorization", user.Token } };
|
||||
|
||||
var response = await RequestHandler.SendRequestAsync("/logout", HttpMethod.Delete, null, headers, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
var response = await RequestHandler.SendRequestAsync("/logout", HttpMethod.Delete, null, headers, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<object>(response).Ok;
|
||||
}
|
||||
@ -68,7 +68,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
|
||||
var headers = new Dictionary<string, string> { { "Authorization", user.Token } };
|
||||
|
||||
var response = await RequestHandler.SendRequestAsync("/infos/user", HttpMethod.Get, null, headers, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
var response = await RequestHandler.SendRequestAsync("/infos/user", HttpMethod.Get, null, headers, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<EncapsulatedUserInfo>(response);
|
||||
}
|
||||
@ -91,7 +91,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
var headers = new Dictionary<string, string> { { "Authorization", user.Token } };
|
||||
|
||||
var body = new { file_id = file };
|
||||
var response = await RequestHandler.SendRequestAsync("/download", HttpMethod.Post, body, headers, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
var response = await RequestHandler.SendRequestAsync("/download", HttpMethod.Post, body, headers, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<SubtitleDownloadInfo>(response, $"file id: {file}");
|
||||
}
|
||||
@ -101,12 +101,21 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
/// </summary>
|
||||
/// <param name="url">the subtitle url.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The subtitle string.</returns>
|
||||
public static async Task<ApiResponse<string>> DownloadSubtitleAsync(string url, CancellationToken cancellationToken)
|
||||
/// <returns>The Http response.</returns>
|
||||
public static async Task<HttpResponse> DownloadSubtitleAsync(string url, CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await RequestHandler.SendRequestAsync(url, HttpMethod.Get, null, null, null, cancellationToken).ConfigureAwait(false);
|
||||
var response = await OpenSubtitlesRequestHelper.Instance!.SendRequestAsync(
|
||||
url,
|
||||
HttpMethod.Get,
|
||||
null,
|
||||
new Dictionary<string, string>(),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<string>(response);
|
||||
return new HttpResponse
|
||||
{
|
||||
Body = response.body,
|
||||
Code = response.statusCode
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -141,7 +150,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
opts.Add(key.ToLower(CultureInfo.InvariantCulture), value.ToLower(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
response = await RequestHandler.SendRequestAsync($"/subtitles?{opts}", HttpMethod.Get, null, null, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
response = await RequestHandler.SendRequestAsync($"/subtitles?{opts}", HttpMethod.Get, null, null, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
last = new ApiResponse<SearchResult>(response, $"query: {opts}", $"page: {current}");
|
||||
|
||||
@ -177,7 +186,7 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
/// <returns>The list of languages.</returns>
|
||||
public static async Task<ApiResponse<EncapsulatedLanguageList>> GetLanguageList(string apiKey, CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await RequestHandler.SendRequestAsync("/infos/languages", HttpMethod.Get, null, null, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
var response = await RequestHandler.SendRequestAsync("/infos/languages", HttpMethod.Get, null, null, apiKey, 1, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new ApiResponse<EncapsulatedLanguageList>(response);
|
||||
}
|
||||
|
@ -79,7 +79,12 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<(string, Dictionary<string, string>, HttpStatusCode)> SendRequestAsync(string url, HttpMethod method, object? body, Dictionary<string, string> headers, CancellationToken cancellationToken)
|
||||
internal async Task<(string body, Dictionary<string, string> headers, HttpStatusCode statusCode)> SendRequestAsync(
|
||||
string url,
|
||||
HttpMethod method,
|
||||
object? body,
|
||||
Dictionary<string, string> headers,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var client = _clientFactory.CreateClient("Default");
|
||||
|
||||
|
@ -30,18 +30,21 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
/// <param name="body">The request body.</param>
|
||||
/// <param name="headers">The headers.</param>
|
||||
/// <param name="apiKey">The api key.</param>
|
||||
/// <param name="attempt">The request attempt key.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The response.</returns>
|
||||
/// <exception cref="ArgumentException">API Key is empty.</exception>
|
||||
public static async Task<HttpResponse> SendRequestAsync(string endpoint, HttpMethod method, object? body, Dictionary<string, string>? headers, string? apiKey, CancellationToken cancellationToken)
|
||||
public static async Task<HttpResponse> SendRequestAsync(
|
||||
string endpoint,
|
||||
HttpMethod method,
|
||||
object? body,
|
||||
Dictionary<string, string>? headers,
|
||||
string? apiKey,
|
||||
int attempt,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var url = endpoint.StartsWith('/') ? BaseApiUrl + endpoint : endpoint;
|
||||
var isFullUrl = url.StartsWith(BaseApiUrl, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
headers ??= new Dictionary<string, string>();
|
||||
|
||||
if (isFullUrl)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(apiKey))
|
||||
{
|
||||
throw new ArgumentException("Provided API key is blank", nameof(apiKey));
|
||||
@ -75,51 +78,48 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler
|
||||
_windowStart = DateTime.UtcNow;
|
||||
_requestCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var (response, responseHeaders, httpStatusCode) = await OpenSubtitlesRequestHelper.Instance!.SendRequestAsync(url, method, body, headers, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!isFullUrl)
|
||||
{
|
||||
return new HttpResponse
|
||||
{
|
||||
Body = response,
|
||||
Code = httpStatusCode
|
||||
};
|
||||
}
|
||||
var response = await OpenSubtitlesRequestHelper.Instance!.SendRequestAsync(BaseApiUrl + endpoint, method, body, headers, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
_requestCount++;
|
||||
|
||||
if (responseHeaders.TryGetValue("x-ratelimit-remaining-second", out var value))
|
||||
if (response.headers.TryGetValue("x-ratelimit-remaining-second", out var value))
|
||||
{
|
||||
_ = int.TryParse(value, out _hRemaining);
|
||||
}
|
||||
|
||||
if (responseHeaders.TryGetValue("ratelimit-reset", out value))
|
||||
if (response.headers.TryGetValue("ratelimit-reset", out value))
|
||||
{
|
||||
_ = int.TryParse(value, out _hReset);
|
||||
}
|
||||
|
||||
if (httpStatusCode != HttpStatusCode.TooManyRequests)
|
||||
if (response.statusCode == HttpStatusCode.TooManyRequests && attempt <= 4)
|
||||
{
|
||||
if (!responseHeaders.TryGetValue("x-reason", out value))
|
||||
var time = _hReset == -1 ? 5 : _hReset;
|
||||
|
||||
await Task.Delay(time * 1000, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return await SendRequestAsync(endpoint, method, body, headers, apiKey, attempt + 1, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response.statusCode == HttpStatusCode.BadGateway && attempt <= 3)
|
||||
{
|
||||
await Task.Delay(500, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return await SendRequestAsync(endpoint, method, body, headers, apiKey, attempt + 1, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!response.headers.TryGetValue("x-reason", out value))
|
||||
{
|
||||
value = string.Empty;
|
||||
}
|
||||
|
||||
return new HttpResponse
|
||||
{
|
||||
Body = response,
|
||||
Code = httpStatusCode,
|
||||
Body = response.body,
|
||||
Code = response.statusCode,
|
||||
Reason = value
|
||||
};
|
||||
}
|
||||
|
||||
var time = _hReset == -1 ? 5 : _hReset;
|
||||
|
||||
await Task.Delay(time * 1000, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return await SendRequestAsync(endpoint, method, body, headers, apiKey, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user