diff --git a/UptimeSharp.Tests/AccountTest.cs b/UptimeSharp.Tests/AccountTest.cs new file mode 100644 index 0000000..b03687b --- /dev/null +++ b/UptimeSharp.Tests/AccountTest.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Xunit; + +namespace UptimeSharp.Tests +{ + public class AccountTest : TestsBase + { + public AccountTest() : base() { } + + + [Fact] + public async Task IsAvailabilityCheckWorking() + { + Assert.False(await client.IsEmailAvailable("cee@live.at")); + Assert.True(await client.IsEmailAvailable(Guid.NewGuid().ToString() + "@live.at")); + + await ThrowsAsync(async () => + { + await client.IsEmailAvailable(""); + }); + + await ThrowsAsync(async () => + { + await client.IsEmailAvailable(""); + }); + + await ThrowsAsync(async () => + { + await client.IsEmailAvailable("opiu@opiuast"); + }); + } + } +} diff --git a/UptimeSharp.Tests/UptimeSharp.Tests.csproj b/UptimeSharp.Tests/UptimeSharp.Tests.csproj index 3cd11ac..6a7b0ee 100644 --- a/UptimeSharp.Tests/UptimeSharp.Tests.csproj +++ b/UptimeSharp.Tests/UptimeSharp.Tests.csproj @@ -61,6 +61,7 @@ + diff --git a/UptimeSharp/Components/Account.cs b/UptimeSharp/Components/Account.cs new file mode 100644 index 0000000..0824d2c --- /dev/null +++ b/UptimeSharp/Components/Account.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace UptimeSharp +{ + /// + /// UptimeClient + /// + public partial class UptimeClient + { + private Regex isEmailRegex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,10}))$", RegexOptions.IgnoreCase); + + + /// + /// Determines whether a e-mail is available. + /// + /// The email. + /// The cancellation token. + /// + /// Please provide an e-mail address + /// Please provide a valid e-mail address + public async Task IsEmailAvailable(string email, CancellationToken cancellationToken = default(CancellationToken)) + { + if (String.IsNullOrEmpty(email)) + { + throw new ArgumentNullException("Please provide an e-mail address"); + } + + if (!isEmailRegex.IsMatch(email)) + { + throw new ArgumentException("Please provide a valid e-mail address"); + } + + return (await AccountRequest("checkUserEmail", cancellationToken, new Dictionary() + { + { "userEmail", email } + })).Success; + } + } +} \ No newline at end of file diff --git a/UptimeSharp/IUptimeClient.cs b/UptimeSharp/IUptimeClient.cs index 93e03dd..0436c21 100644 --- a/UptimeSharp/IUptimeClient.cs +++ b/UptimeSharp/IUptimeClient.cs @@ -187,5 +187,18 @@ namespace UptimeSharp /// Task DeleteAlert(Alert alert, CancellationToken cancellationToken = default(CancellationToken)); #endregion + + + #region Account + /// + /// Determines whether a e-mail is available. + /// + /// The email. + /// The cancellation token. + /// + /// Please provide an e-mail address + /// Please provide a valid e-mail address + Task IsEmailAvailable(string email, CancellationToken cancellationToken = default(CancellationToken)); + #endregion } } diff --git a/UptimeSharp/Models/Response/AccountRepsonse.cs b/UptimeSharp/Models/Response/AccountRepsonse.cs new file mode 100644 index 0000000..41109a3 --- /dev/null +++ b/UptimeSharp/Models/Response/AccountRepsonse.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace UptimeSharp.Models +{ + /// + /// Account Response + /// + [JsonObject] + internal class AccountResponse : Response { } +} diff --git a/UptimeSharp/UptimeClient.cs b/UptimeSharp/UptimeClient.cs index 1cd6142..6508626 100644 --- a/UptimeSharp/UptimeClient.cs +++ b/UptimeSharp/UptimeClient.cs @@ -22,6 +22,11 @@ namespace UptimeSharp /// protected readonly HttpClient _restClient; + /// + /// REST client used for the account communication + /// + protected readonly HttpClient _accountClient; + /// /// Caches HTTP headers from last response /// @@ -33,10 +38,16 @@ namespace UptimeSharp public string lastResponseData; /// - /// The base URL for the Pocket API + /// The base URL for the UptimeRobot API /// protected static Uri baseUri = new Uri("http://api.uptimerobot.com/"); + /// + /// The account base URL for the UptimeRobot API + /// Does not use the official API endpoint + /// + protected static Uri accountBaseUri = new Uri("http://uptimerobot.com/inc/dml/userDML.php"); + /// /// Accessor for the UptimeRebot API key /// see: http://www.uptimerobot.com/api @@ -77,17 +88,23 @@ namespace UptimeSharp { AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip }); + _accountClient = new HttpClient(handler ?? new HttpClientHandler() + { + AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip + }); if (timeout.HasValue) { _restClient.Timeout = TimeSpan.FromSeconds(timeout.Value); + _accountClient.Timeout = TimeSpan.FromSeconds(timeout.Value); } - // set base target _restClient.BaseAddress = baseUri; + _accountClient.BaseAddress = accountBaseUri; // defines the response format _restClient.DefaultRequestHeaders.Add("Accept", "application/json"); + _accountClient.DefaultRequestHeaders.Add("Accept", "application/json"); } @@ -98,7 +115,10 @@ namespace UptimeSharp /// Requested method (appended to base path) /// The cancellation token. /// Additional POST parameters + /// if set to true [is account request]. /// + /// + /// protected async Task Request(string method, CancellationToken cancellationToken, Dictionary parameters = null) where T : class, new() { HttpRequestMessage request; @@ -150,13 +170,14 @@ namespace UptimeSharp lastHeaders = response.Headers; // read response - var responseString = await response.Content.ReadAsStringAsync(); + string responseString = await response.Content.ReadAsStringAsync(); + T parsedResponse; // cache response lastResponseData = responseString; // deserialize object - T parsedResponse = JsonConvert.DeserializeObject( + parsedResponse = JsonConvert.DeserializeObject( responseString, new JsonSerializerSettings { @@ -181,6 +202,78 @@ namespace UptimeSharp } + /// + /// Fetches a typed resource + /// + /// The action. + /// The cancellation token. + /// Additional POST parameters + /// if set to true [is post]. + /// + /// + /// + internal async Task AccountRequest(string action, CancellationToken cancellationToken, Dictionary parameters = null, bool isPost = false) + { + HttpRequestMessage request; + HttpResponseMessage response = null; + + if (parameters == null) + { + parameters = new Dictionary(); + } + + if (!isPost) + { + IEnumerable paramEnumerable = parameters.Where(item => !String.IsNullOrEmpty(item.Value)).Select(item => Uri.EscapeDataString(item.Key) + "=" + Uri.EscapeDataString(item.Value)); + request = new HttpRequestMessage(HttpMethod.Get, "?action=" + Uri.EscapeDataString(action) + "&" + String.Join("&", paramEnumerable)); + } + else + { + request = new HttpRequestMessage(HttpMethod.Post, "?action=" + Uri.EscapeDataString(action)) + { + Content = new FormUrlEncodedContent(parameters.Where(item => !String.IsNullOrEmpty(item.Value))) + }; + } + + // call pre request action + if (PreRequest != null) + { + PreRequest(action); + } + + // make async request + try + { + response = await _accountClient.SendAsync(request, cancellationToken); + } + catch (HttpRequestException exc) + { + throw new UptimeSharpException(exc.Message, exc); + } + + // HTTP error + if (!response.IsSuccessStatusCode) + { + throw new UptimeSharpException("Request Exception: {0} (Code: {1})", response.ReasonPhrase, response.StatusCode.ToString()); + } + + // cache headers + lastHeaders = response.Headers; + + // read response + string responseString = await response.Content.ReadAsStringAsync(); + + // cache response + lastResponseData = responseString; + + // deserialize object + return new AccountResponse() + { + RawStatus = responseString == "true" ? "ok" : "fail" + }; + } + + /// /// Validates the response. /// @@ -198,7 +291,7 @@ namespace UptimeSharp } // don't raise exceptions for minor error codes - if (successFailCodes.Contains(response.ErrorCode)) + if (!String.IsNullOrEmpty(response.ErrorCode) && successFailCodes.Contains(response.ErrorCode)) { return; } diff --git a/UptimeSharp/UptimeSharp.csproj b/UptimeSharp/UptimeSharp.csproj index 7a9ba7c..e0db1f5 100644 --- a/UptimeSharp/UptimeSharp.csproj +++ b/UptimeSharp/UptimeSharp.csproj @@ -39,6 +39,7 @@ + @@ -48,6 +49,7 @@ +