diff --git a/code generation/OpenLibraryNET.Diagnostics/OpenLibraryNET.Diagnostics.csproj b/code generation/OpenLibraryNET.Diagnostics/OpenLibraryNET.Diagnostics.csproj index 3ce0ea5..9ee7001 100644 --- a/code generation/OpenLibraryNET.Diagnostics/OpenLibraryNET.Diagnostics.csproj +++ b/code generation/OpenLibraryNET.Diagnostics/OpenLibraryNET.Diagnostics.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net9.0 true true diff --git a/code generation/OpenLibraryNET.GeneratorAttributes/OpenLibraryNET.GeneratorAttributes.csproj b/code generation/OpenLibraryNET.GeneratorAttributes/OpenLibraryNET.GeneratorAttributes.csproj index c9ac0e3..7b4ae56 100644 --- a/code generation/OpenLibraryNET.GeneratorAttributes/OpenLibraryNET.GeneratorAttributes.csproj +++ b/code generation/OpenLibraryNET.GeneratorAttributes/OpenLibraryNET.GeneratorAttributes.csproj @@ -1,6 +1,6 @@  - netstandard2.0 + net9.0 diff --git a/code generation/OpenLibraryNET.RemoveGeneratorAttributes/OpenLibraryNET.RemoveGeneratorAttributes.csproj b/code generation/OpenLibraryNET.RemoveGeneratorAttributes/OpenLibraryNET.RemoveGeneratorAttributes.csproj index 03cc9c8..93dd0e8 100644 --- a/code generation/OpenLibraryNET.RemoveGeneratorAttributes/OpenLibraryNET.RemoveGeneratorAttributes.csproj +++ b/code generation/OpenLibraryNET.RemoveGeneratorAttributes/OpenLibraryNET.RemoveGeneratorAttributes.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net9.0 enable enable diff --git a/code generation/OpenLibraryNET.SourceGenerators/OpenLibraryNET.SourceGenerators.csproj b/code generation/OpenLibraryNET.SourceGenerators/OpenLibraryNET.SourceGenerators.csproj index 4838dc1..5406d74 100644 --- a/code generation/OpenLibraryNET.SourceGenerators/OpenLibraryNET.SourceGenerators.csproj +++ b/code generation/OpenLibraryNET.SourceGenerators/OpenLibraryNET.SourceGenerators.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net9.0 true true diff --git a/src/OLLoader/IOLMyBooksLoader.cs b/src/OLLoader/IOLMyBooksLoader.cs index 11b4d70..9ce2f69 100644 --- a/src/OLLoader/IOLMyBooksLoader.cs +++ b/src/OLLoader/IOLMyBooksLoader.cs @@ -13,7 +13,7 @@ public interface IOLMyBooksLoader /// /// The user to get the reading log of. null to use the username of the logged in account. /// The task object representing the asynchronous operation. - public Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(string? username = null); + public Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(string? username = null, params KeyValuePair[] parameters); /// /// Get data about a user's Want-To-Read reading log. @@ -24,14 +24,14 @@ public interface IOLMyBooksLoader /// /// /// - public Task GetWantToReadAsync(string? username = null); + public Task GetWantToReadAsync(string? username = null, params KeyValuePair[] parameters); /// /// Attempt to get data about a user's Currently-Reading reading log. /// /// The user to get the reading log of. null to use the username of the logged in account. /// The task object representing the asynchronous operation. - public Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(string? username = null); + public Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(string? username = null, params KeyValuePair[] parameters); /// /// Get data about a user's Currently-Reading reading log. @@ -42,14 +42,14 @@ public interface IOLMyBooksLoader /// /// /// - public Task GetCurrentlyReadingAsync(string? username = null); + public Task GetCurrentlyReadingAsync(string? username = null, params KeyValuePair[] parameters); /// /// Attempt to get data about a user's Already-Read reading log. /// /// The user to get the reading log of. null to use the username of the logged in account. /// The task object representing the asynchronous operation. - public Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(string? username = null); + public Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(string? username = null, params KeyValuePair[] parameters); /// /// Get data about a user's Already-Read reading log. @@ -60,7 +60,7 @@ public interface IOLMyBooksLoader /// /// /// - public Task GetAlreadyReadAsync(string? username = null); + public Task GetAlreadyReadAsync(string? username = null, params KeyValuePair[] parameters); /// /// Attempt to get data about a user's specified reading log. diff --git a/src/OLLoader/OLMyBooksLoader.cs b/src/OLLoader/OLMyBooksLoader.cs index f0b6c1c..8da2f99 100644 --- a/src/OLLoader/OLMyBooksLoader.cs +++ b/src/OLLoader/OLMyBooksLoader.cs @@ -17,9 +17,10 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// Attempt to get data about a user's Want-To-Read reading log. /// /// The user to get the reading log of. null to use the username of the logged in account. + /// /// The task object representing the asynchronous operation. - public async Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(string? username = null) - => await TryGetWantToReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(string? username = null, params KeyValuePair[] parameters) + => await TryGetWantToReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username , parameters); /// /// Get data about a user's Want-To-Read reading log. /// @@ -29,16 +30,16 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async Task GetWantToReadAsync(string? username = null) - => await GetWantToReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task GetWantToReadAsync(string? username = null, params KeyValuePair[] parameters) + => await GetWantToReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username,parameters); /// /// Attempt to get data about a user's Currently-Reading reading log. /// /// The user to get the reading log of. null to use the username of the logged in account. /// The task object representing the asynchronous operation. - public async Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(string? username = null) - => await TryGetCurrentlyReadingAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(string? username = null, params KeyValuePair[] parameters) + => await TryGetCurrentlyReadingAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username, parameters); /// /// Get data about a user's Currently-Reading reading log. /// @@ -48,16 +49,16 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async Task GetCurrentlyReadingAsync(string? username = null) - => await GetCurrentlyReadingAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task GetCurrentlyReadingAsync(string? username = null, params KeyValuePair[] parameters) + => await GetCurrentlyReadingAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username, parameters); /// /// Attempt to get data about a user's Already-Read reading log. /// /// The user to get the reading log of. null to use the username of the logged in account. /// The task object representing the asynchronous operation. - public async Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(string? username = null) - => await TryGetAlreadyReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(string? username = null, params KeyValuePair[] parameters) + => await TryGetAlreadyReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username, parameters ); /// /// Get data about a user's Already-Read reading log. /// @@ -67,8 +68,8 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async Task GetAlreadyReadAsync(string? username = null) - => await GetAlreadyReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username); + public async Task GetAlreadyReadAsync(string? username = null, params KeyValuePair[] parameters ) + => await GetAlreadyReadAsync(_client.BackingClient, username == null ? _client.Username?.ToLower()! : username,parameters); /// /// Attempt to get data about a user's specified reading log. @@ -131,9 +132,9 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// An HttpClient instance which will be used to make the request. /// The user to get the reading log of. /// The task object representing the asynchronous operation. - public async static Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(HttpClient client, string username) + public async static Task<(bool, OLMyBooksData?)> TryGetWantToReadAsync(HttpClient client, string username, params KeyValuePair[] parameters) { - try { return (true, await GetWantToReadAsync(client, username)); } + try { return (true, await GetWantToReadAsync(client, username, parameters)); } catch { return (false, null); } } @@ -147,12 +148,12 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async static Task GetWantToReadAsync(HttpClient client, string username) + public async static Task GetWantToReadAsync(HttpClient client, string username, params KeyValuePair[] parameters) { return await OpenLibraryUtility.LoadAsync ( client, - OpenLibraryUtility.BuildMyBooksUri(username, "want-to-read") + OpenLibraryUtility.BuildMyBooksUri(username, "want-to-read",parameters) ); } @@ -162,9 +163,9 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// An HttpClient instance which will be used to make the request. /// The user to get the reading log of. /// The task object representing the asynchronous operation. - public async static Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(HttpClient client, string username) + public async static Task<(bool, OLMyBooksData?)> TryGetCurrentlyReadingAsync(HttpClient client, string username, params KeyValuePair[] parameters) { - try { return (true, await GetCurrentlyReadingAsync(client, username)); } + try { return (true, await GetCurrentlyReadingAsync(client, username,parameters)); } catch { return (false, null); } } @@ -178,12 +179,12 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async static Task GetCurrentlyReadingAsync(HttpClient client, string username) + public async static Task GetCurrentlyReadingAsync(HttpClient client, string username, params KeyValuePair[] parameters) { return await OpenLibraryUtility.LoadAsync ( client, - OpenLibraryUtility.BuildMyBooksUri(username, "currently-reading") + OpenLibraryUtility.BuildMyBooksUri(username, "currently-reading",parameters) ); } @@ -193,9 +194,9 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// An HttpClient instance which will be used to make the request. /// The user to get the reading log of. /// The task object representing the asynchronous operation. - public async static Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(HttpClient client, string username) + public async static Task<(bool, OLMyBooksData?)> TryGetAlreadyReadAsync(HttpClient client, string username, params KeyValuePair[] parameters) { - try { return (true, await GetAlreadyReadAsync(client, username)); } + try { return (true, await GetAlreadyReadAsync(client, username, parameters)); } catch { return (false, null); } } @@ -209,12 +210,12 @@ public class OLMyBooksLoader : IOLMyBooksLoader /// /// /// - public async static Task GetAlreadyReadAsync(HttpClient client, string username) + public async static Task GetAlreadyReadAsync(HttpClient client, string username, params KeyValuePair[] parameters) { return await OpenLibraryUtility.LoadAsync ( client, - OpenLibraryUtility.BuildMyBooksUri(username, "already-read") + OpenLibraryUtility.BuildMyBooksUri(username, "already-read", parameters) ); } diff --git a/src/OpenLibraryClient.cs b/src/OpenLibraryClient.cs index ca42b11..a7e8248 100644 --- a/src/OpenLibraryClient.cs +++ b/src/OpenLibraryClient.cs @@ -1,4 +1,5 @@ -using System.Formats.Asn1; +using System; +using System.Formats.Asn1; using System.Net; using System.Net.Http.Json; using System.Text.RegularExpressions; @@ -10,6 +11,9 @@ namespace OpenLibraryNET { + + + /// /// The main interface to OpenLibrary.
/// Instantiates HttpClient internally, as OpenLibraryClient uses cookies.
@@ -17,6 +21,9 @@ namespace OpenLibraryNET ///
public class OpenLibraryClient : IOpenLibraryClient { + + + /// public bool LoggedIn => _httpHandler.CookieContainer.GetCookies(OpenLibraryUtility.BaseUri).SingleOrDefault(cookie => cookie.Name == "session") != null; /// @@ -46,15 +53,46 @@ public class OpenLibraryClient : IOpenLibraryClient /// public HttpClient BackingClient => _httpClient; + private class OperationKeyHandler : DelegatingHandler + { + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + ResilienceContext context = ResilienceContextPool.Shared.Get(cancellationToken); + string uri = request.RequestUri.ToString(); + ResilienceContextExtensions.SetRequestMetadata(context, new RequestMetadata("OperationKey", uri, "Additional information if needed")); + return await base.SendAsync(request, cancellationToken); + } + } + + private const string httpClientName = "OpenLibraryNET.OpenLibraryClient"; + + private readonly CookieContainer? _cookieContainer = new CookieContainer(); + + private readonly IHttpClientFactory _httpClientFactory; + /// /// Create a new instance of the OpenLibraryClient.
/// Instantiates HttpClient internally, as OpenLibraryClient uses cookies.
/// To reuse the backing HttpClient, reuse the OpenLibrary instance. ///
- public OpenLibraryClient() + public OpenLibraryClient(Action? configureOptions = null, Action? logBuilder = null) { - _httpHandler = new HttpClientHandler() { AllowAutoRedirect = true, UseCookies = true }; - _httpClient = new HttpClient(_httpHandler); + ServiceCollection services = new ServiceCollection(); + _httpHandler = new HttpClientHandler + { + AllowAutoRedirect = true, + UseCookies = true, + CookieContainer = _cookieContainer + }; + services.AddHttpClient(httpClientName).ConfigurePrimaryHttpMessageHandler(() => _httpHandler).AddHttpMessageHandler() + .AddStandardResilienceHandler(configureOptions); + if (logBuilder != null) + { + services.AddLogging(logBuilder); + } + ServiceProvider provider = services.BuildServiceProvider(); + _httpClientFactory = provider.GetService(); + _httpClient = _httpClientFactory.CreateClient(httpClientName);// +"-standard"); _work = new OLWorkLoader(_httpClient); _author = new OLAuthorLoader(_httpClient); diff --git a/src/OpenLibraryNET.csproj b/src/OpenLibraryNET.csproj index 0071a3a..9c4d04c 100644 --- a/src/OpenLibraryNET.csproj +++ b/src/OpenLibraryNET.csproj @@ -1,7 +1,7 @@  - net6.0 + net9.0 enable enable @@ -41,14 +41,14 @@ - + - "$(CodeGen)OpenLibraryNET.RemoveGeneratorAttributes\bin\$(Configuration)\net6.0\OpenLibraryNET.RemoveGeneratorAttributes.exe" + "$(CodeGen)OpenLibraryNET.RemoveGeneratorAttributes\bin\$(Configuration)\$(TargetFramework)\OpenLibraryNET.RemoveGeneratorAttributes.exe" "$(TargetPath)" - "$(CodeGen)OpenLibraryNET.GeneratorAttributes\bin\$(Configuration)\netstandard2.0\OpenLibraryNET.GeneratorAttributes.dll" + "$(CodeGen)OpenLibraryNET.GeneratorAttributes\bin\$(Configuration)\$(TargetFramework)\OpenLibraryNET.GeneratorAttributes.dll" diff --git a/src/Utility/OpenLibraryUtility.cs b/src/Utility/OpenLibraryUtility.cs index e444914..2b87e24 100644 --- a/src/Utility/OpenLibraryUtility.cs +++ b/src/Utility/OpenLibraryUtility.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using System.Text.RegularExpressions; using System.Collections.Immutable; +using System.Diagnostics; namespace OpenLibraryNET.Utility { @@ -315,12 +316,13 @@ public static Uri BuildListsUri(string username, string? id = null, string? path /// The user whose reading logs you want to get. /// The path of the Uri. Should be "want-to-read", "currently-reading" or "already-read". /// A MyBooks API Uri. - public static Uri BuildMyBooksUri(string username, string path) + public static Uri BuildMyBooksUri(string username, string path, params KeyValuePair[] parameters) { return BuildUri ( BaseURL, - "people/" + username + "/books/" + path + ".json" + "people/" + username + "/books/" + path + ".json", + parameters ); } @@ -583,6 +585,7 @@ public async static Task RequestAsync(HttpClient client, Uri uri) return JsonConvert.DeserializeObject(response); else { + if (response == "{}") return default; JToken token = JToken.Parse(response); return token[path]!.ToObject(); } diff --git a/tests/OpenLibraryNET.Tests.csproj b/tests/OpenLibraryNET.Tests.csproj index f21c76f..715caf0 100644 --- a/tests/OpenLibraryNET.Tests.csproj +++ b/tests/OpenLibraryNET.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net9.0 enable enable