From 978b384759dfdea1d93898c06239be3324823a3a Mon Sep 17 00:00:00 2001 From: glax Date: Sun, 11 Feb 2024 22:57:23 +0100 Subject: [PATCH] Create ApiHttpClient Use Useragent from Assembly. --- CShocker/CShocker.csproj | 2 +- CShocker/Devices/APIs/OpenShockHttp.cs | 41 ++++++--------- CShocker/Devices/APIs/PiShockHttp.cs | 38 +++++--------- CShocker/Devices/Abstract/OpenShockApi.cs | 53 ++++++-------------- CShocker/Devices/Additional/ApiHttpClient.cs | 40 +++++++++++++++ 5 files changed, 83 insertions(+), 91 deletions(-) create mode 100644 CShocker/Devices/Additional/ApiHttpClient.cs diff --git a/CShocker/CShocker.csproj b/CShocker/CShocker.csproj index 2cd882e..f3868f4 100644 --- a/CShocker/CShocker.csproj +++ b/CShocker/CShocker.csproj @@ -7,7 +7,7 @@ Glax https://github.com/C9Glax/CShocker git - 2.2.0 + 2.3.0 diff --git a/CShocker/Devices/APIs/OpenShockHttp.cs b/CShocker/Devices/APIs/OpenShockHttp.cs index 19bee59..0337e43 100644 --- a/CShocker/Devices/APIs/OpenShockHttp.cs +++ b/CShocker/Devices/APIs/OpenShockHttp.cs @@ -1,6 +1,4 @@ -using System.Net.Http.Headers; -using System.Text; -using CShocker.Devices.Abstract; +using CShocker.Devices.Abstract; using CShocker.Devices.Additional; using CShocker.Shockers; using CShocker.Shockers.Abstract; @@ -18,30 +16,19 @@ public class OpenShockHttp : OpenShockApi return; } - HttpRequestMessage request = new (HttpMethod.Post, $"{Endpoint}/2/shockers/control") - { - Headers = - { - UserAgent = { new ProductInfoHeaderValue("CShocker", "1") }, - Accept = { new MediaTypeWithQualityHeaderValue("application/json") } - }, - Content = new StringContent("{" + - " \"shocks\": [" + - " {" + - $" \"id\": \"{openShockShocker.id}\"," + - $" \"type\": {ControlActionToByte(action)}," + - $" \"intensity\": {intensity}," + - $" \"duration\": {duration}" + - " }" + - " ]," + - " \"customName\": \"CShocker\"" + - "}", Encoding.UTF8, new MediaTypeHeaderValue("application/json")) - }; - request.Headers.Add("OpenShockToken", ApiKey); - this.Logger?.Log(LogLevel.Debug, $"Request-Content: {request.Content.ReadAsStringAsync().Result}"); - HttpResponseMessage response = HttpClient.Send(request); - this.Logger?.Log(!response.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug, - $"{request.RequestUri} response: {response.StatusCode}"); + string json = "{" + + " \"shocks\": [" + + " {" + + $" \"id\": \"{openShockShocker.id}\"," + + $" \"type\": {ControlActionToByte(action)}," + + $" \"intensity\": {intensity}," + + $" \"duration\": {duration}" + + " }" + + " ]," + + " \"customName\": \"CShocker\"" + + "}"; + + ApiHttpClient.MakeAPICall(HttpMethod.Post, $"{Endpoint}/2/shockers/control", json, this.Logger, new ValueTuple("OpenShockToken", ApiKey)); } private byte ControlActionToByte(ControlAction action) diff --git a/CShocker/Devices/APIs/PiShockHttp.cs b/CShocker/Devices/APIs/PiShockHttp.cs index b86dea4..958c76d 100644 --- a/CShocker/Devices/APIs/PiShockHttp.cs +++ b/CShocker/Devices/APIs/PiShockHttp.cs @@ -1,6 +1,4 @@ -using System.Net.Http.Headers; -using System.Text; -using CShocker.Devices.Abstract; +using CShocker.Devices.Abstract; using CShocker.Devices.Additional; using CShocker.Shockers; using CShocker.Shockers.Abstract; @@ -12,7 +10,6 @@ public class PiShockHttp : PiShockApi { // ReSharper disable twice MemberCanBePrivate.Global external usage public string Username, Endpoint, ApiKey; - protected readonly HttpClient HttpClient = new(); public PiShockHttp(string apiKey, string username, string endpoint = "https://do.pishock.com/api/apioperate", ILogger? logger = null) : base(DeviceApi.PiShockHttp, logger) { @@ -28,27 +25,18 @@ public class PiShockHttp : PiShockApi this.Logger?.Log(LogLevel.Warning, $"Shocker {shocker} is not {typeof(OpenShockShocker).FullName}"); return; } - - HttpRequestMessage request = new (HttpMethod.Post, $"{Endpoint}") - { - Headers = - { - UserAgent = { new ProductInfoHeaderValue("CShocker", "1") }, - Accept = { new MediaTypeWithQualityHeaderValue("text/plain") } - }, - Content = new StringContent("{" + - $"\"Username\":\"{Username}\"," + - "\"Name\":\"CShocker\"," + - $"\"Code\":\"{piShockShocker.Code}\"," + - $"\"Intensity\":\"{intensity}\"," + - $"\"Duration\":\"{duration/1000}\"," + //duration is in seconds no ms - $"\"Apikey\":\"{ApiKey}\"," + - $"\"Op\":\"{ControlActionToByte(action)}\"" + - "}", Encoding.UTF8, new MediaTypeHeaderValue("application/json")) - }; - HttpResponseMessage response = HttpClient.Send(request); - this.Logger?.Log(!response.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug, - $"{request.RequestUri} response: {response.StatusCode}"); + + string json = "{" + + $"\"Username\":\"{Username}\"," + + "\"Name\":\"CShocker\"," + + $"\"Code\":\"{piShockShocker.Code}\"," + + $"\"Intensity\":\"{intensity}\"," + + $"\"Duration\":\"{duration / 1000}\"," + //duration is in seconds no ms + $"\"Apikey\":\"{ApiKey}\"," + + $"\"Op\":\"{ControlActionToByte(action)}\"" + + "}"; + + ApiHttpClient.MakeAPICall(HttpMethod.Post, $"{Endpoint}", json, this.Logger); } private byte ControlActionToByte(ControlAction action) diff --git a/CShocker/Devices/Abstract/OpenShockApi.cs b/CShocker/Devices/Abstract/OpenShockApi.cs index 1763cb8..6ee6a32 100644 --- a/CShocker/Devices/Abstract/OpenShockApi.cs +++ b/CShocker/Devices/Abstract/OpenShockApi.cs @@ -1,5 +1,4 @@ -using System.Net.Http.Headers; -using CShocker.Devices.Additional; +using CShocker.Devices.Additional; using CShocker.Ranges; using CShocker.Shockers; using Microsoft.Extensions.Logging; @@ -9,7 +8,6 @@ namespace CShocker.Devices.Abstract; public abstract class OpenShockApi : Api { - protected readonly HttpClient HttpClient = new(); public string Endpoint { get; init; } public string ApiKey { get; init; } private const string DefaultEndpoint = "https://api.shocklink.net"; @@ -43,21 +41,8 @@ public abstract class OpenShockApi : Api public static List GetShockers(string apiKey, OpenShockApi api, string apiEndpoint = DefaultEndpoint, ILogger? logger = null) { List shockers = new(); - - HttpClient httpClient = new(); - HttpRequestMessage requestOwnShockers = new (HttpMethod.Get, $"{apiEndpoint}/1/shockers/own") - { - Headers = - { - UserAgent = { new ProductInfoHeaderValue("CShocker", "1") }, - Accept = { new MediaTypeWithQualityHeaderValue("application/json") } - } - }; - requestOwnShockers.Headers.Add("OpenShockToken", apiKey); - logger?.Log(LogLevel.Debug, $"Requesting {requestOwnShockers.RequestUri}"); - HttpResponseMessage ownResponse = httpClient.Send(requestOwnShockers); - logger?.Log(!ownResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug, - $"{requestOwnShockers.RequestUri} response: {ownResponse.StatusCode}"); + + HttpResponseMessage ownResponse = ApiHttpClient.MakeAPICall(HttpMethod.Get, $"{apiEndpoint}/1/shockers/own", null, logger, new ValueTuple("OpenShockToken", apiKey)); if (!ownResponse.IsSuccessStatusCode) return shockers; @@ -66,23 +51,13 @@ public abstract class OpenShockApi : Api logger?.Log(LogLevel.Debug,ownShockerJson); JObject ownShockerListJObj = JObject.Parse(ownShockerJson); shockers.AddRange(ownShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t => - { - return new OpenShockShocker(api, t["name"]!.Value()!, t["id"]!.Value()!, t["rfId"]!.Value(), Enum.Parse(t["model"]!.Value()!), t["createdOn"]!.ToObject(), t["isPaused"]!.Value()); - })); + new OpenShockShocker( + api, + t["name"]!.Value()!, t["id"]!.Value()!, t["rfId"]!.Value(), + Enum.Parse(t["model"]!.Value()!), + t["createdOn"]!.ToObject(), t["isPaused"]!.Value()))); - HttpRequestMessage requestSharedShockers = new (HttpMethod.Get, $"{apiEndpoint}/1/shockers/shared") - { - Headers = - { - UserAgent = { new ProductInfoHeaderValue("CShocker", "1") }, - Accept = { new MediaTypeWithQualityHeaderValue("application/json") } - } - }; - requestSharedShockers.Headers.Add("OpenShockToken", apiKey); - logger?.Log(LogLevel.Debug, $"Requesting {requestSharedShockers.RequestUri}"); - HttpResponseMessage sharedResponse = httpClient.Send(requestSharedShockers); - logger?.Log(!sharedResponse.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug, - $"{requestSharedShockers.RequestUri} response: {sharedResponse.StatusCode}"); + HttpResponseMessage sharedResponse = ApiHttpClient.MakeAPICall(HttpMethod.Get, $"{apiEndpoint}/1/shockers/shared", null, logger, new ValueTuple("OpenShockToken", apiKey)); if (!sharedResponse.IsSuccessStatusCode) return shockers; @@ -90,10 +65,12 @@ public abstract class OpenShockApi : Api string sharedShockerJson = sharedShockerStreamReader.ReadToEnd(); logger?.Log(LogLevel.Debug, sharedShockerJson); JObject sharedShockerListJObj = JObject.Parse(sharedShockerJson); - shockers.AddRange(sharedShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t => - { - return new OpenShockShocker(api, t["name"]!.Value()!, t["id"]!.Value()!, t["rfId"]!.Value(),Enum.Parse(t["model"]!.Value()!), t["createdOn"]!.ToObject(), t["isPaused"]!.Value()); - })); + shockers.AddRange(sharedShockerListJObj.SelectTokens("$.data..shockers[*]").Select(t => + new OpenShockShocker( + api, + t["name"]!.Value()!, t["id"]!.Value()!, t["rfId"]!.Value(), + Enum.Parse(t["model"]!.Value()!), + t["createdOn"]!.ToObject(), t["isPaused"]!.Value()))); return shockers; } } \ No newline at end of file diff --git a/CShocker/Devices/Additional/ApiHttpClient.cs b/CShocker/Devices/Additional/ApiHttpClient.cs new file mode 100644 index 0000000..48357c5 --- /dev/null +++ b/CShocker/Devices/Additional/ApiHttpClient.cs @@ -0,0 +1,40 @@ +using System.Diagnostics; +using System.Net.Http.Headers; +using System.Reflection; +using System.Text; +using Microsoft.Extensions.Logging; + +namespace CShocker.Devices.Additional; + +public static class ApiHttpClient +{ + internal static HttpResponseMessage MakeAPICall(HttpMethod method, string uri, string? jsonContent, ILogger? logger = null, params ValueTuple[] customHeaders) + { + Assembly assembly = Assembly.GetExecutingAssembly(); + FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); + ProductInfoHeaderValue userAgent = new (fvi.ProductName ?? fvi.FileName, fvi.ProductVersion); + HttpRequestMessage request = new (method, uri) + { + Headers = + { + UserAgent = { userAgent }, + Accept = { new MediaTypeWithQualityHeaderValue("application/json") } + } + }; + if (jsonContent is not null && jsonContent.Length > 0) + request.Content = + new StringContent(jsonContent, Encoding.UTF8, new MediaTypeHeaderValue("application/json")); + foreach ((string, string) customHeader in customHeaders) + request.Headers.Add(customHeader.Item1, customHeader.Item2); + logger?.Log(LogLevel.Debug, $"Request-URI: {request.RequestUri}\n\r" + + $"Request-Headers: \n\t{string.Join("\n\t", request.Headers.Select(h => $"{h.Key} {string.Join(", ", h.Value)}"))}\n\r" + + $"Request-Content: {request.Content?.ReadAsStringAsync().Result}"); + + HttpClient httpClient = new(); + HttpResponseMessage response = httpClient.Send(request); + logger?.Log(!response.IsSuccessStatusCode ? LogLevel.Error : LogLevel.Debug, + $"{request.RequestUri} response: {response.StatusCode}"); + httpClient.Dispose(); + return response; + } +} \ No newline at end of file