From 28c5c6a625ada254d2024b4fd687146ee96ee4a6 Mon Sep 17 00:00:00 2001 From: MBR-0001 <55142207+MBR-0001@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:10:28 +0200 Subject: [PATCH] Remove custom api key (#132) --- .../API/OpenSubtitlesController.cs | 9 +++-- .../Configuration/PluginConfiguration.cs | 5 --- .../OpenSubtitleDownloader.cs | 35 ++++++------------- .../Models/LoginInfoInput.cs | 5 --- .../{OpenSubtitles.cs => OpenSubtitlesApi.cs} | 31 +++++++--------- .../OpenSubtitlesHandler/RequestHandler.cs | 13 ++----- .../OpenSubtitlesPlugin.cs | 6 ++-- .../Web/opensubtitles.html | 10 ++---- .../Web/opensubtitles.js | 7 ++-- 9 files changed, 39 insertions(+), 82 deletions(-) rename Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/{OpenSubtitles.cs => OpenSubtitlesApi.cs} (81%) diff --git a/Jellyfin.Plugin.OpenSubtitles/API/OpenSubtitlesController.cs b/Jellyfin.Plugin.OpenSubtitles/API/OpenSubtitlesController.cs index 728a72b..fa1ace9 100644 --- a/Jellyfin.Plugin.OpenSubtitles/API/OpenSubtitlesController.cs +++ b/Jellyfin.Plugin.OpenSubtitles/API/OpenSubtitlesController.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler; using Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -38,8 +39,10 @@ public class OpenSubtitlesController : ControllerBase [ProducesResponseType(StatusCodes.Status401Unauthorized)] public async Task ValidateLoginInfo([FromBody] LoginInfoInput body) { - var key = !string.IsNullOrWhiteSpace(body.CustomApiKey) ? body.CustomApiKey : OpenSubtitlesPlugin.ApiKey; - var response = await OpenSubtitlesHandler.OpenSubtitles.LogInAsync(body.Username, body.Password, key, CancellationToken.None).ConfigureAwait(false); + var response = await OpenSubtitlesApi.LogInAsync( + body.Username, + body.Password, + CancellationToken.None).ConfigureAwait(false); if (!response.Ok) { @@ -59,7 +62,7 @@ public async Task ValidateLoginInfo([FromBody] LoginInfoInput body if (response.Data is not null) { - await OpenSubtitlesHandler.OpenSubtitles.LogOutAsync(response.Data, key, CancellationToken.None).ConfigureAwait(false); + await OpenSubtitlesApi.LogOutAsync(response.Data, CancellationToken.None).ConfigureAwait(false); } return Ok(new { Downloads = response.Data?.User?.AllowedDownloads ?? 0 }); diff --git a/Jellyfin.Plugin.OpenSubtitles/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.OpenSubtitles/Configuration/PluginConfiguration.cs index f2079e9..2ad4fc1 100644 --- a/Jellyfin.Plugin.OpenSubtitles/Configuration/PluginConfiguration.cs +++ b/Jellyfin.Plugin.OpenSubtitles/Configuration/PluginConfiguration.cs @@ -17,11 +17,6 @@ public class PluginConfiguration : BasePluginConfiguration /// public string Password { get; set; } = string.Empty; - /// - /// Gets or sets the custom API Key. - /// - public string CustomApiKey { get; set; } = string.Empty; - /// /// Gets or sets a value indicating whether the credentials are invalid. /// diff --git a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitleDownloader.cs b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitleDownloader.cs index 0f6d105..770bea9 100644 --- a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitleDownloader.cs +++ b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitleDownloader.cs @@ -51,17 +51,6 @@ public OpenSubtitleDownloader(ILogger logger, IHttpClien /// public static OpenSubtitleDownloader? Instance { get; private set; } - /// - /// Gets the API key that will be used for requests. - /// - public string ApiKey - { - get - { - return !string.IsNullOrWhiteSpace(_configuration?.CustomApiKey) ? _configuration.CustomApiKey : OpenSubtitlesPlugin.ApiKey; - } - } - /// public string Name => "Open Subtitles"; @@ -173,7 +162,7 @@ public async Task> Search(SubtitleSearchRequest _logger.LogDebug("Search query: {Query}", options); - var searchResponse = await OpenSubtitlesHandler.OpenSubtitles.SearchSubtitlesAsync(options, ApiKey, cancellationToken).ConfigureAwait(false); + var searchResponse = await OpenSubtitlesApi.SearchSubtitlesAsync(options, cancellationToken).ConfigureAwait(false); if (!searchResponse.Ok) { @@ -183,7 +172,7 @@ public async Task> Search(SubtitleSearchRequest bool MediaFilter(ResponseData x) => x.Attributes?.FeatureDetails?.FeatureType == (request.ContentType == VideoContentType.Episode ? "Episode" : "Movie") - && x.Attributes?.Files?.Count > 0 && x.Attributes.Files[0].FileId != null + && x.Attributes?.Files?.Count > 0 && x.Attributes.Files[0].FileId is not null && (request.ContentType == VideoContentType.Episode ? x.Attributes.FeatureDetails.SeasonNumber == request.ParentIndexNumber && x.Attributes.FeatureDetails.EpisodeNumber == request.IndexNumber @@ -261,8 +250,8 @@ private async Task GetSubtitlesInternal(string id, Cancellatio var language = idParts[1]; var fileId = int.Parse(idParts[2], CultureInfo.InvariantCulture); - var info = await OpenSubtitlesHandler.OpenSubtitles - .GetSubtitleLinkAsync(fileId, format, _login, ApiKey, cancellationToken) + var info = await OpenSubtitlesApi + .GetSubtitleLinkAsync(fileId, format, _login, cancellationToken) .ConfigureAwait(false); if (info.Data?.ResetTime is not null) @@ -321,7 +310,7 @@ private async Task GetSubtitlesInternal(string id, Cancellatio throw new HttpRequestException(msg); } - var res = await OpenSubtitlesHandler.OpenSubtitles.DownloadSubtitleAsync(info.Data.Link, cancellationToken).ConfigureAwait(false); + var res = await OpenSubtitlesApi.DownloadSubtitleAsync(info.Data.Link, cancellationToken).ConfigureAwait(false); if (res.Code != HttpStatusCode.OK || string.IsNullOrWhiteSpace(res.Body)) { @@ -355,20 +344,18 @@ private async Task Login(CancellationToken cancellationToken) return; } - var loginResponse = await OpenSubtitlesHandler.OpenSubtitles.LogInAsync( + var loginResponse = await OpenSubtitlesApi.LogInAsync( _configuration.Username, _configuration.Password, - ApiKey, cancellationToken).ConfigureAwait(false); if (!loginResponse.Ok) { - // 400 = Using email, 401 = invalid credentials, 403 = invalid api key + // 400 = Using email, 401 = invalid credentials if ((loginResponse.Code == HttpStatusCode.BadRequest && _configuration.Username.Contains('@', StringComparison.OrdinalIgnoreCase)) - || loginResponse.Code == HttpStatusCode.Unauthorized - || (loginResponse.Code == HttpStatusCode.Forbidden && ApiKey == _configuration.CustomApiKey)) + || loginResponse.Code == HttpStatusCode.Unauthorized) { - _logger.LogError("Login failed due to invalid credentials/API key, invalidating them ({Code} - {Body})", loginResponse.Code, loginResponse.Body); + _logger.LogError("Login failed due to invalid credentials, invalidating them ({Code} - {Body})", loginResponse.Code, loginResponse.Body); _configuration.CredentialsInvalid = true; OpenSubtitlesPlugin.Instance!.SaveConfiguration(_configuration); } @@ -394,7 +381,7 @@ private async Task UpdateUserInfo(CancellationToken cancellationToken) return; } - var infoResponse = await OpenSubtitlesHandler.OpenSubtitles.GetUserInfo(_login, ApiKey, cancellationToken).ConfigureAwait(false); + var infoResponse = await OpenSubtitlesApi.GetUserInfo(_login, cancellationToken).ConfigureAwait(false); if (infoResponse.Ok) { _login.User = infoResponse.Data?.Data; @@ -415,7 +402,7 @@ private async Task GetLanguage(string language, CancellationToken cancel if (_languages is null || _languages.Count == 0) { - var res = await OpenSubtitlesHandler.OpenSubtitles.GetLanguageList(ApiKey, cancellationToken).ConfigureAwait(false); + var res = await OpenSubtitlesApi.GetLanguageList(cancellationToken).ConfigureAwait(false); if (!res.Ok || res.Data?.Data is null) { diff --git a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/Models/LoginInfoInput.cs b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/Models/LoginInfoInput.cs index 5ea2177..5a31915 100644 --- a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/Models/LoginInfoInput.cs +++ b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/Models/LoginInfoInput.cs @@ -18,9 +18,4 @@ public class LoginInfoInput /// [Required] public string Password { get; set; } = null!; - - /// - /// Gets or sets the custom api key. - /// - public string CustomApiKey { get; set; } = null!; } diff --git a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitles.cs b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitlesApi.cs similarity index 81% rename from Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitles.cs rename to Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitlesApi.cs index aecd04b..7c15476 100644 --- a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitles.cs +++ b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/OpenSubtitlesApi.cs @@ -12,20 +12,19 @@ namespace Jellyfin.Plugin.OpenSubtitles.OpenSubtitlesHandler; /// /// The open subtitles helper class. /// -public static class OpenSubtitles +public static class OpenSubtitlesApi { /// /// Login. /// /// The username. /// The password. - /// The api key. /// The cancellation token. /// The api response. - public static async Task> LogInAsync(string username, string password, string apiKey, CancellationToken cancellationToken) + public static async Task> LogInAsync(string username, string password, CancellationToken cancellationToken) { var body = new { username, password }; - var response = await RequestHandler.SendRequestAsync("/login", HttpMethod.Post, body, null, apiKey, 1, cancellationToken).ConfigureAwait(false); + var response = await RequestHandler.SendRequestAsync("/login", HttpMethod.Post, body, null, 1, cancellationToken).ConfigureAwait(false); return new ApiResponse(response); } @@ -34,16 +33,15 @@ public static async Task> LogInAsync(string username, str /// Logout. /// /// The user information. - /// The api key. /// The cancellation token. /// logout status. - public static async Task LogOutAsync(LoginInfo user, string apiKey, CancellationToken cancellationToken) + public static async Task LogOutAsync(LoginInfo user, CancellationToken cancellationToken) { ArgumentException.ThrowIfNullOrEmpty(user.Token); var headers = new Dictionary { { "Authorization", user.Token } }; - var response = await RequestHandler.SendRequestAsync("/logout", HttpMethod.Delete, null, headers, apiKey, 1, cancellationToken).ConfigureAwait(false); + var response = await RequestHandler.SendRequestAsync("/logout", HttpMethod.Delete, null, headers, 1, cancellationToken).ConfigureAwait(false); return new ApiResponse(response).Ok; } @@ -52,16 +50,15 @@ public static async Task LogOutAsync(LoginInfo user, string apiKey, Cancel /// Get user info. /// /// The user information. - /// The api key. /// The cancellation token. /// The encapsulated user info. - public static async Task> GetUserInfo(LoginInfo user, string apiKey, CancellationToken cancellationToken) + public static async Task> GetUserInfo(LoginInfo user, CancellationToken cancellationToken) { ArgumentException.ThrowIfNullOrEmpty(user.Token); var headers = new Dictionary { { "Authorization", user.Token } }; - var response = await RequestHandler.SendRequestAsync("/infos/user", HttpMethod.Get, null, headers, apiKey, 1, cancellationToken).ConfigureAwait(false); + var response = await RequestHandler.SendRequestAsync("/infos/user", HttpMethod.Get, null, headers, 1, cancellationToken).ConfigureAwait(false); return new ApiResponse(response); } @@ -72,14 +69,12 @@ public static async Task> GetUserInfo(LoginInf /// The subtitle file. /// The subtitle format. /// The user information. - /// The api key. /// The cancellation token. /// The subtitle download info. public static async Task> GetSubtitleLinkAsync( int file, string format, LoginInfo user, - string apiKey, CancellationToken cancellationToken) { ArgumentException.ThrowIfNullOrEmpty(user.Token); @@ -87,7 +82,7 @@ public static async Task> GetSubtitleLinkAsync var headers = new Dictionary { { "Authorization", user.Token } }; var body = new { file_id = file, sub_format = format }; - var response = await RequestHandler.SendRequestAsync("/download", HttpMethod.Post, body, headers, apiKey, 1, cancellationToken).ConfigureAwait(false); + var response = await RequestHandler.SendRequestAsync("/download", HttpMethod.Post, body, headers, 1, cancellationToken).ConfigureAwait(false); return new ApiResponse(response, $"file id: {file}"); } @@ -118,10 +113,9 @@ public static async Task DownloadSubtitleAsync(string url, Cancell /// Search for subtitle. /// /// The search options. - /// The api key. /// The cancellation token. /// The list of response data. - public static async Task>> SearchSubtitlesAsync(Dictionary options, string apiKey, CancellationToken cancellationToken) + public static async Task>> SearchSubtitlesAsync(Dictionary options, CancellationToken cancellationToken) { var opts = new Dictionary(); foreach (var (key, value) in options) @@ -144,7 +138,7 @@ public static async Task>> SearchSubtitl } var url = RequestHandler.AddQueryString("/subtitles", opts); - response = await RequestHandler.SendRequestAsync(url, HttpMethod.Get, null, null, apiKey, 1, cancellationToken).ConfigureAwait(false); + response = await RequestHandler.SendRequestAsync(url, HttpMethod.Get, null, null, 1, cancellationToken).ConfigureAwait(false); last = new ApiResponse(response, $"url: {url}", $"page: {current}"); @@ -175,12 +169,11 @@ public static async Task>> SearchSubtitl /// /// Get language list. /// - /// The api key. /// The cancellation token. /// The list of languages. - public static async Task> GetLanguageList(string apiKey, CancellationToken cancellationToken) + public static async Task> GetLanguageList(CancellationToken cancellationToken) { - var response = await RequestHandler.SendRequestAsync("/infos/languages", HttpMethod.Get, null, null, apiKey, 1, cancellationToken).ConfigureAwait(false); + var response = await RequestHandler.SendRequestAsync("/infos/languages", HttpMethod.Get, null, null, 1, cancellationToken).ConfigureAwait(false); return new ApiResponse(response); } diff --git a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/RequestHandler.cs b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/RequestHandler.cs index a5a7e94..b6048be 100644 --- a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/RequestHandler.cs +++ b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesHandler/RequestHandler.cs @@ -32,7 +32,6 @@ public static class RequestHandler /// The method. /// The request body. /// The headers. - /// The api key. /// The request attempt key. /// The cancellation token. /// The response. @@ -42,18 +41,12 @@ public static async Task SendRequestAsync( HttpMethod method, object? body, Dictionary? headers, - string? apiKey, int attempt, CancellationToken cancellationToken) { headers ??= new Dictionary(); - if (string.IsNullOrWhiteSpace(apiKey)) - { - throw new ArgumentException("Provided API key is blank", nameof(apiKey)); - } - - headers.TryAdd("Api-Key", apiKey); + headers.TryAdd("Api-Key", OpenSubtitlesPlugin.ApiKey); if (_hRemaining == 0) { await Task.Delay(1000 * _hReset, cancellationToken).ConfigureAwait(false); @@ -98,14 +91,14 @@ public static async Task SendRequestAsync( await Task.Delay(time * 1000, cancellationToken).ConfigureAwait(false); - return await SendRequestAsync(endpoint, method, body, headers, apiKey, attempt + 1, cancellationToken).ConfigureAwait(false); + return await SendRequestAsync(endpoint, method, body, headers, 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); + return await SendRequestAsync(endpoint, method, body, headers, attempt + 1, cancellationToken).ConfigureAwait(false); } if (!response.headers.TryGetValue("x-reason", out value)) diff --git a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesPlugin.cs b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesPlugin.cs index 8439bf3..9d0c2fb 100644 --- a/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesPlugin.cs +++ b/Jellyfin.Plugin.OpenSubtitles/OpenSubtitlesPlugin.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Plugin.OpenSubtitles; public class OpenSubtitlesPlugin : BasePlugin, IHasWebPages { /// - /// Default API key to use when performing an API call. + /// API key to use when performing an API call. /// public const string ApiKey = "gUCLWGoAg2PmyseoTM0INFFVPcDCeDlT"; @@ -30,10 +30,10 @@ public OpenSubtitlesPlugin(IApplicationPaths applicationPaths, IXmlSerializer xm ConfigurationChanged += (_, _) => { - OpenSubtitleDownloader.Instance?.ConfigurationChanged(this.Configuration); + OpenSubtitleDownloader.Instance?.ConfigurationChanged(Configuration); }; - OpenSubtitleDownloader.Instance?.ConfigurationChanged(this.Configuration); + OpenSubtitleDownloader.Instance?.ConfigurationChanged(Configuration); } /// diff --git a/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.html b/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.html index cee556f..adcd0b3 100644 --- a/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.html +++ b/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.html @@ -19,14 +19,8 @@

In order for this plugin to work
You can utilize this plugin by editing a library and modifying the options for subtitle downloads.
-
- -
- You can provide an API Key for doing API requests, if left empty the default API key will be used. -
- +
diff --git a/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.js b/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.js index 06e359b..d2ba50f 100644 --- a/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.js +++ b/Jellyfin.Plugin.OpenSubtitles/Web/opensubtitles.js @@ -13,7 +13,6 @@ export default function (view, params) { ApiClient.getPluginConfiguration(OpenSubtitlesConfig.pluginUniqueId).then(function (config) { page.querySelector('#username').value = config.Username || ''; page.querySelector('#password').value = config.Password || ''; - page.querySelector('#apikey').value = config.CustomApiKey || ''; if (config.CredentialsInvalid) { credentialsWarning.style.display = null; } @@ -28,7 +27,6 @@ export default function (view, params) { ApiClient.getPluginConfiguration(OpenSubtitlesConfig.pluginUniqueId).then(function (config) { const username = form.querySelector('#username').value.trim(); const password = form.querySelector('#password').value.trim(); - const apiKey = form.querySelector('#apikey').value.trim(); if (!username || !password) { Dashboard.processErrorResponse({statusText: "Account info is incomplete"}); @@ -37,8 +35,8 @@ export default function (view, params) { const el = form.querySelector('#ossresponse'); const saveButton = form.querySelector('#save-button'); - - const data = JSON.stringify({ Username: username, Password: password, CustomApiKey: apiKey }); + + const data = JSON.stringify({ Username: username, Password: password }); const url = ApiClient.getUrl('Jellyfin.Plugin.OpenSubtitles/ValidateLoginInfo'); const handler = response => response.json().then(res => { @@ -48,7 +46,6 @@ export default function (view, params) { config.Username = username; config.Password = password; - config.CustomApiKey = apiKey; config.CredentialsInvalid = false; ApiClient.updatePluginConfiguration(OpenSubtitlesConfig.pluginUniqueId, config).then(function (result) {