diff --git a/Akismet.Net/Akismet.Net.csproj b/Akismet.Net/Akismet.Net.csproj index cb673df..e043a97 100644 --- a/Akismet.Net/Akismet.Net.csproj +++ b/Akismet.Net/Akismet.Net.csproj @@ -8,26 +8,28 @@ MIT https://github.com/ahwm/Akismet.Net https://github.com/ahwm/Akismet.Net - net452;net6.0;netstandard2.0;net7.0 + net462;netstandard2.0; (c) 2021 Adam Humpherys akismet spam antispam - Dropped explicit support for .NET Core 3.1 and .NET 5 and added support for .NET 7 + Dropped explicit support for .NET Core; dropped dependency on RestSharp AkismetApi.Net - 3.0.0.1 - 3.0.0.0 + 4.0.0 + 4.0.0.0 README.md + + + NETSTANDARD;NETSTANDARD2_0 + + + + + - - 106.15.0 - - - 13.0.3 - - - 4.7.0 - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -35,6 +37,12 @@ + + + + <_Parameter1>GodaddyWrapper.Tests + + diff --git a/Akismet.Net/AkismetClient.cs b/Akismet.Net/AkismetClient.cs index 4a60811..84a0383 100644 --- a/Akismet.Net/AkismetClient.cs +++ b/Akismet.Net/AkismetClient.cs @@ -1,11 +1,16 @@ using Akismet.Net.Helpers; -using Newtonsoft.Json; -using RestSharp; +#if NETSTANDARD +using Microsoft.Extensions.Options; +#endif using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; using System.Reflection; +using System.Text.Json; using System.Threading.Tasks; +using System.Xml.Linq; namespace Akismet.Net { @@ -18,8 +23,9 @@ public class AkismetClient private readonly string apiKey; private readonly string[] allowedIntervals = new[] { "60-days", "6-months", "all" }; - private readonly RestClient client; + private readonly HttpClient client; +#if !NETSTANDARD /// /// /// @@ -31,38 +37,42 @@ public AkismetClient(string apiKey, Uri blogUrl, string applicationName) this.apiKey = apiKey; this.blogUrl = blogUrl?.ToString() ?? throw new ArgumentNullException("blogUrl"); - client = new RestClient($"https://{apiKey}.rest.akismet.com/1.1") + client = new HttpClient() { - UserAgent = $"{applicationName} | Akismet.NET/{Assembly.GetExecutingAssembly().GetName().Version} (https://github.com/ahwm/Akismet.Net)", + BaseAddress = new Uri($"https://{apiKey}.rest.akismet.com/1.1/"), }; + client.DefaultRequestHeaders.Add("User-Agent", $"{applicationName} | Akismet.NET/{Assembly.GetExecutingAssembly().GetName().Version} (https://github.com/ahwm/Akismet.Net)"); } - +#else /// - /// Verify key + /// /// - /// - public async Task VerifyKeyAsync() + /// + /// + /// + public AkismetClient(HttpClient _httpClient, IOptions options) { - var req = new RestRequest("verify-key", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - var resp = await client.ExecuteAsync(req); + this.apiKey = options.Value.Key; + this.blogUrl = options.Value.BlogUrl; - return resp.Content == "valid"; + client = _httpClient; } +#endif /// /// Verify key /// /// - public bool VerifyKey() + public async Task VerifyKeyAsync() { - var req = new RestRequest("verify-key", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - var resp = client.Execute(req); + var formData = new FormUrlEncodedContent(new List> + { + new KeyValuePair("key", apiKey), + new KeyValuePair("blog", blogUrl) + }); + var resp = await client.PostAsync("verify-key", formData); - return resp.Content == "valid"; + return await resp.Content.ReadAsStringAsync() == "valid"; } /// @@ -72,67 +82,32 @@ public bool VerifyKey() /// public async Task CheckAsync(AkismetComment comment) { - var req = new RestRequest("comment-check", Method.POST) - .AddParameter("blog", blogUrl); - - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); - - var resp = await client.ExecuteAsync(req); - - AkismetResponse response = new AkismetResponse(); - - if (!Boolean.TryParse(resp.Content, out bool result)) + var data = new List> { - response.AkismetErrors.Add(resp.Content); - response.SpamStatus = SpamStatus.Unspecified; - } - else - response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); - - return response; - } - - /// - /// Check comment - /// - /// - /// - public AkismetResponse Check(AkismetComment comment) - { - var req = new RestRequest("comment-check", Method.POST) - .AddParameter("blog", blogUrl); + new KeyValuePair("blog", blogUrl) + }; - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); + data.AddRange(AttributeHelper.GetAttributes(comment)); - var resp = client.Execute(req); + var resp = await client.PostAsync("comment-check", new FormUrlEncodedContent(data)); AkismetResponse response = new AkismetResponse(); + var responseData = await resp.Content.ReadAsStringAsync(); - if (!Boolean.TryParse(resp.Content, out bool result)) + if (!Boolean.TryParse(responseData, out bool result)) { - response.AkismetErrors.Add(resp.Content); + response.AkismetErrors.Add(responseData); response.SpamStatus = SpamStatus.Unspecified; } else response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-debug-help")) + response.AkismetDebugHelp = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-debug-help").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-pro-tip")) + response.ProTip = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-alert-code")) + response.AkismetErrors.Add(resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); return response; } @@ -144,67 +119,32 @@ public AkismetResponse Check(AkismetComment comment) /// public async Task SubmitSpamAsync(AkismetComment comment) { - var req = new RestRequest("submit-spam", Method.POST) - .AddParameter("blog", blogUrl); - - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); - - var resp = await client.ExecuteAsync(req); - - AkismetResponse response = new AkismetResponse(); - - if (!Boolean.TryParse(resp.Content, out bool result)) + var data = new List> { - response.AkismetErrors.Add(resp.Content); - response.SpamStatus = SpamStatus.Unspecified; - } - else - response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); - - return response; - } - - /// - /// Submit missed spam - /// - /// - /// - public AkismetResponse SubmitSpam(AkismetComment comment) - { - var req = new RestRequest("submit-spam", Method.POST) - .AddParameter("blog", blogUrl); + new KeyValuePair("blog", blogUrl) + }; - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); + data.AddRange(AttributeHelper.GetAttributes(comment)); - var resp = client.Execute(req); + var resp = await client.PostAsync("submit-spam", new FormUrlEncodedContent(data)); AkismetResponse response = new AkismetResponse(); + var responseData = await resp.Content.ReadAsStringAsync(); - if (!Boolean.TryParse(resp.Content, out bool result)) + if (!Boolean.TryParse(responseData, out bool result)) { - response.AkismetErrors.Add(resp.Content); + response.AkismetErrors.Add(responseData); response.SpamStatus = SpamStatus.Unspecified; } else response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-debug-help")) + response.AkismetDebugHelp = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-debug-help").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-pro-tip")) + response.ProTip = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-alert-code")) + response.AkismetErrors.Add(resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); return response; } @@ -216,67 +156,32 @@ public AkismetResponse SubmitSpam(AkismetComment comment) /// public async Task SubmitHamAsync(AkismetComment comment) { - var req = new RestRequest("submit-ham", Method.POST) - .AddParameter("blog", blogUrl); - - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); - - var resp = await client.ExecuteAsync(req); - - AkismetResponse response = new AkismetResponse(); - - if (!Boolean.TryParse(resp.Content, out bool result)) + var data = new List> { - response.AkismetErrors.Add(resp.Content); - response.SpamStatus = SpamStatus.Unspecified; - } - else - response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); - - return response; - } - - /// - /// Submit false positive (ham marked as spam) - /// - /// - /// - public AkismetResponse SubmitHam(AkismetComment comment) - { - var req = new RestRequest("submit-ham", Method.POST) - .AddParameter("blog", blogUrl); + new KeyValuePair("blog", blogUrl) + }; - var attributes = AttributeHelper.GetAttributes(comment); - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); + data.AddRange(AttributeHelper.GetAttributes(comment)); - var resp = client.Execute(req); + var resp = await client.PostAsync("submit-ham", new FormUrlEncodedContent(data)); AkismetResponse response = new AkismetResponse(); + var responseData = await resp.Content.ReadAsStringAsync(); - if (!Boolean.TryParse(resp.Content, out bool result)) + if (!Boolean.TryParse(responseData, out bool result)) { - response.AkismetErrors.Add(resp.Content); + response.AkismetErrors.Add(responseData); response.SpamStatus = SpamStatus.Unspecified; } else response.SpamStatus = result ? SpamStatus.Spam : SpamStatus.Ham; - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-debug-help")) - response.AkismetDebugHelp = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-debug-help").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-pro-tip")) - response.ProTip = resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); - if (resp.Headers.Any(r => r.Name.ToLower() == "x-akismet-alert-code")) - response.AkismetErrors.Add(resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Name.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-debug-help")) + response.AkismetDebugHelp = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-debug-help").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-pro-tip")) + response.ProTip = resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-pro-tip").First().Value.ToString(); + if (resp.Headers.Any(r => r.Key.ToLower() == "x-akismet-alert-code")) + response.AkismetErrors.Add(resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-code").First().Value.ToString() + ": " + resp.Headers.Where(r => r.Key.ToLower() == "x-akismet-alert-msg").First().Value.ToString()); return response; } @@ -287,39 +192,13 @@ public AkismetResponse SubmitHam(AkismetComment comment) /// public async Task GetAccountStatusAsync() { - var req = new RestRequest("get-subscription", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - var resp = await client.ExecuteAsync(req); - dynamic data = JsonConvert.DeserializeObject(resp.Content); - - AkismetAccount account = new AkismetAccount + var formData = new FormUrlEncodedContent(new List> { - AccountId = (int)data["account_id"], - AccountName = (string)data["account_name"], - AccountType = (string)data["account_type"], - Status = (string)data["status"], - LimitReached = (bool)data["limit_reached"] - }; - if (!(data["next_billing_date"] is bool)) - account.NextBillingDate = DateTimeHelper.UnixTimeStampToDateTime(Convert.ToInt32(data["next_billing_date"])); - - return account; - } - - /// - /// - /// - /// - public AkismetAccount GetAccountStatus() - { - var req = new RestRequest("get-subscription", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - var resp = client.Execute(req); - dynamic data = JsonConvert.DeserializeObject(resp.Content); + new KeyValuePair("key", apiKey), + new KeyValuePair("blog", blogUrl) + }); + var resp = await client.PostAsync("get-subscription", formData); + var data = JsonSerializer.Deserialize>(await resp.Content.ReadAsStringAsync()); AkismetAccount account = new AkismetAccount { @@ -345,40 +224,18 @@ public async Task GetStatisticsAsync(string interval = "") if (!String.IsNullOrWhiteSpace(interval) && !allowedIntervals.Contains(interval)) throw new ArgumentException("Invalid interval", nameof(interval)); - var req = new RestRequest("get-stats", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - if (!String.IsNullOrWhiteSpace(interval)) - req.AddParameter("from", interval); - - var resp = await client.ExecuteAsync(req); - var data = JsonConvert.DeserializeObject(resp.Content); - - return data; - } - - /// - /// - /// - /// Allowed options: 60-days, 6-months, all - /// - public SpamStats GetStatistics(string interval = "") - { - if (!String.IsNullOrWhiteSpace(interval) && !allowedIntervals.Contains(interval)) - throw new ArgumentException("Invalid interval", nameof(interval)); - - var req = new RestRequest("get-stats", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - + var data = new List> + { + new KeyValuePair("key", apiKey), + new KeyValuePair("blog", blogUrl) + }; if (!String.IsNullOrWhiteSpace(interval)) - req.AddParameter("from", interval); + data.Add(new KeyValuePair("from", interval)); + var resp = await client.PostAsync("get-stats", new FormUrlEncodedContent(data)); - var resp = client.Execute(req); - var data = JsonConvert.DeserializeObject(resp.Content); + var stats = JsonSerializer.Deserialize(await resp.Content.ReadAsStringAsync()); - return data; + return stats; } /// @@ -387,64 +244,38 @@ public SpamStats GetStatistics(string interval = "") /// public async Task DecativateAsync() { - var req = new RestRequest("deactivate", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - var resp = await client.ExecuteAsync(req); - - return resp.Content; - } - - /// - /// - /// - /// - public string Deactivate() - { - var req = new RestRequest("deactivate", Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); + var formData = new FormUrlEncodedContent(new List> + { + new KeyValuePair("key", apiKey), + new KeyValuePair("blog", blogUrl) + }); - var resp = client.Execute(req); + var resp = await client.PostAsync("deactivate", formData); - return resp.Content; + return await resp.Content.ReadAsStringAsync(); } /// /// /// /// - public async Task CustomCallAsync(string command, Dictionary attributes) + public async Task CustomCallAsync(string command, Dictionary attributes) { - var req = new RestRequest(command, Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); - - RestResponse resp = (RestResponse)await client.ExecuteAsync(req); + var data = new List> + { + new KeyValuePair("key", apiKey), + new KeyValuePair("blog", blogUrl) + }; + data.AddRange(attributes); + var resp = await client.PostAsync(command, new FormUrlEncodedContent(data)); - return resp; + return await resp.Content.ReadAsStringAsync(); } + } - /// - /// - /// - /// - public RestResponse CustomCall(string command, Dictionary attributes) - { - var req = new RestRequest(command, Method.POST) - .AddParameter("key", apiKey) - .AddParameter("blog", blogUrl); - - foreach (var kv in attributes) - req.AddParameter(kv.Key, kv.Value); - - RestResponse resp = (RestResponse)client.Execute(req); - - return resp; - } + public class AkismetClientOptions + { + public string Key { get; set; } = ""; + public string BlogUrl { get; set; } = ""; } } diff --git a/Akismet.Net/AkismetComment.cs b/Akismet.Net/AkismetComment.cs index e06c309..3a3b5b7 100644 --- a/Akismet.Net/AkismetComment.cs +++ b/Akismet.Net/AkismetComment.cs @@ -1,7 +1,8 @@ using Akismet.Net.Attributes; using Akismet.Net.Helpers; -using Newtonsoft.Json; using System; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Akismet.Net { @@ -123,14 +124,14 @@ public override string ToString() { var attributes = AttributeHelper.GetAttributes(this); - return JsonConvert.SerializeObject(attributes); + return JsonSerializer.Serialize(attributes); } } /// /// /// - public class CommentTypeConverter : JsonConverter + public class CommentTypeConverter : JsonConverter { /// /// @@ -142,35 +143,15 @@ public override bool CanConvert(Type objectType) return objectType == typeof(AkismentCommentType); } - /// - /// - /// - public override bool CanRead => false; - - /// - /// - /// - /// - /// - /// - /// - /// - /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + public override AkismentCommentType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { throw new NotImplementedException(); } - /// - /// - /// - /// - /// - /// - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + public override void Write(Utf8JsonWriter writer, AkismentCommentType value, JsonSerializerOptions options) { string commentType = (AkismentCommentType)value; - writer.WriteValue(commentType); + writer.WriteStringValue(commentType); } } } diff --git a/Akismet.Net/Helpers/AttributeHelper.cs b/Akismet.Net/Helpers/AttributeHelper.cs index 4d108e7..9c9ba7a 100644 --- a/Akismet.Net/Helpers/AttributeHelper.cs +++ b/Akismet.Net/Helpers/AttributeHelper.cs @@ -1,5 +1,4 @@ using Akismet.Net.Attributes; -using RestSharp.Extensions; using System.Collections.Generic; using System.Reflection; @@ -25,7 +24,7 @@ public static List> GetAttributes(object model) } else { - if (property.GetAttribute() is AkismetNameAttribute attribute) + if (property.GetCustomAttribute(typeof(AkismetNameAttribute)) is AkismetNameAttribute attribute) l.Add(new KeyValuePair(attribute.AkismetName, property.GetValue(model).ToString())); else l.Add(new KeyValuePair(property.Name, property.GetValue(model).ToString())); diff --git a/Akismet.Net/Services.cs b/Akismet.Net/Services.cs new file mode 100644 index 0000000..e4d6199 --- /dev/null +++ b/Akismet.Net/Services.cs @@ -0,0 +1,36 @@ +#if NETSTANDARD +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Reflection; + +namespace Akismet.Net +{ + public static class ServicesExtension + { + /// + /// + /// + /// + /// + /// + /// + /// + public static IServiceCollection AddAkismet(this IServiceCollection services, string key, string applicationName, string blogUrl) + { + // https://stackoverflow.com/a/79111722/1892993 + services.AddOptions() + .Configure(options => { + options.Key = key; + options.BlogUrl = blogUrl; + }); + services.AddHttpClient(client => + { + client.BaseAddress = new Uri($"https://{key}.rest.akismet.com/1.1/"); + client.DefaultRequestHeaders.Add("User-Agent", $"{applicationName} | Akismet.NET/{Assembly.GetExecutingAssembly().GetName().Version} (https://github.com/ahwm/Akismet.Net)"); + }); + + return services; + } + } +} +#endif \ No newline at end of file diff --git a/Akismet.Net/SpamStatistics.cs b/Akismet.Net/SpamStatistics.cs index e210704..3919ad5 100644 --- a/Akismet.Net/SpamStatistics.cs +++ b/Akismet.Net/SpamStatistics.cs @@ -1,7 +1,7 @@ -using Newtonsoft.Json; -using System; +using System; using System.Collections.Generic; using System.Text; +using System.Text.Json.Serialization; namespace Akismet.Net { @@ -23,13 +23,13 @@ public partial class SpamStats /// /// /// - [JsonProperty("missed_spam")] + [JsonPropertyName("missed_spam")] public long MissedSpam { get; set; } /// /// /// - [JsonProperty("false_positives")] + [JsonPropertyName("false_positives")] public long FalsePositives { get; set; } /// @@ -45,7 +45,7 @@ public partial class SpamStats /// /// /// - [JsonProperty("time_saved")] + [JsonPropertyName("time_saved")] public long TimeSaved { get; set; } } @@ -67,13 +67,13 @@ public partial class Breakdown /// /// /// - [JsonProperty("missed_spam")] + [JsonPropertyName("missed_spam")] public long MissedSpam { get; set; } /// /// /// - [JsonProperty("false_positives")] + [JsonPropertyName("false_positives")] public long FalsePositives { get; set; } /// diff --git a/Akismet.Tests/Akismet.Tests.csproj b/Akismet.Tests/Akismet.Tests.csproj index d206d64..3235fce 100644 --- a/Akismet.Tests/Akismet.Tests.csproj +++ b/Akismet.Tests/Akismet.Tests.csproj @@ -1,11 +1,15 @@  - net7.0;net6.0;net462 + net9.0;net8.0;net6.0;net462 false + + NETCORE + + @@ -19,6 +23,8 @@ all + + diff --git a/Akismet.Tests/AkismetTests.cs b/Akismet.Tests/AkismetTests.cs index 74c3caf..8ed4cd6 100644 --- a/Akismet.Tests/AkismetTests.cs +++ b/Akismet.Tests/AkismetTests.cs @@ -1,10 +1,6 @@ using Akismet.Net; using Shouldly; using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; using System.Threading.Tasks; using Xunit; @@ -12,9 +8,15 @@ namespace Akismet.Tests { public class AkismetTests { - private readonly string ApiKey; private readonly string ApiKeyUrl; private readonly AkismetClient Client; +#if NETCORE + public AkismetTests(AkismetClient akismetClient) + { + Client = akismetClient; + } +#else + private readonly string ApiKey; public AkismetTests() { @@ -23,12 +25,7 @@ public AkismetTests() Client = new AkismetClient(ApiKey, new Uri(ApiKeyUrl), "Akismet Test Application"); } - - [Fact] - public void VerifyKeyTest() - { - Client.VerifyKey().ShouldBe(true); - } +#endif [Fact] public async Task VerifyKeyAsyncTest() @@ -38,29 +35,6 @@ public async Task VerifyKeyAsyncTest() isValid.ShouldBe(true); } - [Fact] - public void CheckSpamComment() - { - AkismetComment comment = new AkismetComment -{ - CommentAuthor = "viagra-test-123", - CommentAuthorEmail = "akismet-guaranteed-spam@example.com", - CommentAuthorUrl = "http://www.spamwebsite.com", - Referrer = "https://www.google.com", - UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36", - CommentContent = "This is a test spam comment", - CommentType = AkismentCommentType.ContactForm, // multiple defined values, or use new AkismetCommentType("new-comment-type") for a custom option - Permalink = $"{ApiKeyUrl}/contact", - IsTest = "true", - BlogCharset = "UTF-8", - BlogLanguage = "en-US", - CommentDate = DateTime.UtcNow.ToString("s"), // ISO-8601 format - CommentPostModified = DateTime.UtcNow.ToString("s") // ISO-8601 format - }; - var spamResult = Client.Check(comment); - spamResult.SpamStatus.ShouldBe(SpamStatus.Spam); - } - [Fact] public async Task CheckSpamCommentAsync() { @@ -84,30 +58,6 @@ public async Task CheckSpamCommentAsync() spamResult.SpamStatus.ShouldBe(SpamStatus.Spam); } - [Fact] - public void CheckHamComment() - { - AkismetComment comment = new AkismetComment - { - CommentAuthor = "Test", - CommentAuthorEmail = "test@example.com", - CommentAuthorUrl = "http://www.spamwebsite.com", - Referrer = "https://www.google.com", - UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36", - CommentContent = "This is a test ham comment", - CommentType = AkismentCommentType.ContactForm, - Permalink = $"{ApiKeyUrl}/contact", - IsTest = "true", - BlogCharset = "UTF-8", - BlogLanguage = "en-US", - CommentDate = DateTime.UtcNow.ToString("s"), - CommentPostModified = DateTime.UtcNow.ToString("s"), - UserRole = "administrator" - }; - var spamResult = Client.Check(comment); - spamResult.SpamStatus.ShouldBe(SpamStatus.Ham); - } - [Fact] public async Task CheckHamCommentAsync() { diff --git a/Akismet.Tests/Startup.cs b/Akismet.Tests/Startup.cs new file mode 100644 index 0000000..ef841fd --- /dev/null +++ b/Akismet.Tests/Startup.cs @@ -0,0 +1,18 @@ +#if NETCORE +using Akismet.Net; +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace Akismet.Tests +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + string apiKey = Environment.GetEnvironmentVariable("AKISMET_API_KEY").Trim(); + string blogUrl = Environment.GetEnvironmentVariable("AKISMET_API_KEY_URL").Trim(); + services.AddAkismet(apiKey, "Akismet Test Application", blogUrl); + } + } +} +#endif \ No newline at end of file diff --git a/README.md b/README.md index 148d1f3..69ebc6c 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ AkismetComment comment = new AkismetComment HoneypotFieldValue = "blah" }; -var akismetResult = akismet.Check(comment); +var akismetResult = await akismet.CheckAsync(comment); bool isSpam = akismetResult.SpamStatus == SpamStatus.Spam; // Options: Ham, Spam, Unspecified (in the case of an error) // "invalid" and/or combination of X-akismet-alert-code and X-akismet-alert-msg header values @@ -56,7 +56,20 @@ foreach (string err in akismetResult.Errors) ### .NET Core/.NET 5+ Usage Modifications +#### Program.cs / Startup.cs + +```charp +builder.Services.AddAkismet( + configuration.ApiKey, + configuration.AkismetApplicationName, + configuration.BlogUrl); +``` + +#### Service Class / Controller + ```csharp +public class ContactFormController(AkismetClient akismetClient) + string ip = Request.Headers["CF-Connecting-IP"].ToString() ?? _contextAccessor.HttpContext?.Connection.RemoteIpAddress?.ToString() ?? ""; if (String.IsNullOrWhiteSpace(ip)) ip = _contextAccessor.HttpContext?.GetServerVariable("REMOTE_HOST") ?? ""; @@ -66,6 +79,7 @@ AkismetComment comment = new AkismetComment UserAgent = Request.Headers[HeaderNames.UserAgent], Referrer = Request.Headers[HeaderNames.Referer] }; +var akismetResult = await akismetClient.CheckAsync(comment) ``` ### Notes @@ -73,3 +87,10 @@ AkismetComment comment = new AkismetComment If `HoneypotFieldName` and `HoneypotFieldValue` are supplied then the library will add these two values to the request: `honeypot_field_name=honeypot&honeypot=blah` + +#### ⚠️Breaking Changes + +Version 4.0 has a breaking change: + +- Dropped RestClient in favor of HttpClient directly +- .NET Core/.NET 5+ now utilize dependency injection