diff --git a/.gitignore b/.gitignore index 5f1fa96..b09f534 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ */obj *.csproj.user !.gitkeep -/smsapiTests/App.Config diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5516a92 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +# CHANGELOG.md + +## 2.2.1 (unreleased) + +- Basic authentication deprecation + +## 2.2.0 (2023-05-16) + +- Http Client fixes [#36](https://github.com/smsapi/smsapi-csharp-client/issues/36), [#32](https://github.com/smsapi/smsapi-csharp-client/issues/32) +- RestSharp dependency update to 109.0.1 +- Abandoned support for .NET < 6 + +## 2.1.0 (2023-04-12) + +- Support for templates in SMS [#37](https://github.com/smsapi/smsapi-csharp-client/issues/33) + +## 2.0.0 (2023-01-18) + +- Support for smsapi.io diff --git a/README.md b/README.md index 485e39a..107b71d 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,17 @@ SMSAPI C# client may be used by *SMSAPI.pl* and *SMSAPI.com* clients. ## How to pick a service? -### *SMSAPI.PL* (default) +### *SMSAPI.IO* (default) ```c# var smsApi = new SMSApi.Api.SMSFactory(client); //or +var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiIo); +``` + +### *SMSAPI.PL* + +```c# var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiPl); ``` @@ -34,7 +40,7 @@ try var result = smsApi.ActionSend() .SetText("test message") - .SetTo("694562829") + .SetTo("0000000000") .SetSender("Test") //Sender name .Execute(); @@ -62,19 +68,7 @@ try foreach (var status in result.List) { - System.Console.WriteLine("ID: " + status.ID + " NUmber: " + status.Number + " Points:" + status.Points + " Status:" + status.Status + " IDx: " + status.IDx); - } - - for (int i = 0, l = 0; i < result.List.Count; i++) - { - if (!result.List[i].isError()) - { - var deleted = - smsApi.ActionDelete() - .Id(result.List[i].ID) - .Execute(); - System.Console.WriteLine("Deleted: " + deleted.Count); - } + System.Console.WriteLine("ID: " + status.ID + " Number: " + status.Number + " Points:" + status.Points + " Status:" + status.Status + " IDx: " + status.IDx); } } catch (SMSApi.Api.ActionException e) @@ -112,7 +106,7 @@ catch (SMSApi.Api.ProxyException e) } ``` -## Wymagania +## Requirements * C# >= 3.5 + System.Runtime.Serialization, System.ServiceModel.Web * C# >= 4.0 diff --git a/csharp-smsapi.sln b/csharp-smsapi.sln index fa4d160..06e0fce 100644 --- a/csharp-smsapi.sln +++ b/csharp-smsapi.sln @@ -27,14 +27,13 @@ Global {05C2A720-2CD1-401B-A832-9CE85313C248}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {05C2A720-2CD1-401B-A832-9CE85313C248}.Release|Mixed Platforms.Build.0 = Release|Any CPU {05C2A720-2CD1-401B-A832-9CE85313C248}.Release|x86.ActiveCfg = Release|Any CPU + {05C2A720-2CD1-401B-A832-9CE85313C248}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|x86.ActiveCfg = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Debug|x86.Build.0 = Debug|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Release|Any CPU.Build.0 = Release|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Release|Mixed Platforms.Build.0 = Release|Any CPU {A0C118D0-9435-477B-92B5-0918E1CDADAF}.Release|x86.ActiveCfg = Release|Any CPU diff --git a/dll_files.zip b/dll_files.zip new file mode 100644 index 0000000..68d17f8 Binary files /dev/null and b/dll_files.zip differ diff --git a/examples/mfa/CreateMFACode.cs b/examples/mfa/CreateMFACode.cs new file mode 100644 index 0000000..f90bc9b --- /dev/null +++ b/examples/mfa/CreateMFACode.cs @@ -0,0 +1,33 @@ +using SMSApi.Api; +using smsapi.Api.Response.REST.Exception; +using SMSApi.Api.Response.MFA.Exception; + +var client = new ClientOAuth("token"); +var features = new Features(client); + +const string phoneNumber = "48100100100"; + +try +{ + var mfaCode = features.MFA() + .CreateMfaCode(phoneNumber) + .AsFast() //Send code in fast message (optional) + .FromSendername("SMSAPI") //Send code from sendername (optional) + .WithContent("Your code is [%code%]") //Send code with custom content (optional) + .Execute(); + + Console.WriteLine(mfaCode.Id); + Console.WriteLine(mfaCode.Code); + Console.WriteLine(mfaCode.PhoneNumber); + Console.WriteLine(mfaCode.From); +} +catch (ValidationException ex) +{ + var errors = ex.ValidationErrors; +} +catch (TooManyRequestsException) +{ +} +catch (ClientException ex) +{ +} diff --git a/examples/mfa/VerifyMFACode.cs b/examples/mfa/VerifyMFACode.cs new file mode 100644 index 0000000..916463a --- /dev/null +++ b/examples/mfa/VerifyMFACode.cs @@ -0,0 +1,29 @@ +using SMSApi.Api; +using SMSApi.Api.Response.MFA; +using smsapi.Api.Response.REST.Exception; +using SMSApi.Api.Response.MFA.Exception; + +var client = new ClientOAuth("token"); +var features = new Features(client); + +const string phoneNumber = "48100100100"; +const string code = "123456"; + +try +{ + features.MFA() + .VerifyMfaCode(phoneNumber, code) + .Execute(); + + //code is valid at this point +} +catch (ValidationException ex) +{ + var errors = ex.ValidationErrors; +} +catch (InvalidVerificationCodeException) +{ +} +catch (ExpiredVerificationCodeException) +{ +} diff --git a/examples/ping/PingService.cs b/examples/ping/PingService.cs new file mode 100644 index 0000000..e8fb4ab --- /dev/null +++ b/examples/ping/PingService.cs @@ -0,0 +1,15 @@ +using SMSApi.Api; + +var client = new ClientOAuth("token"); +var features = new Features(client); + +var result = features.Ping() + .PingService() + .Execute(); + +Console.WriteLine(result.Authorized); + +foreach (var unavailableService in result.UnavailableServices) +{ + Console.WriteLine($"Unavailable service: {unavailableService}"); +} diff --git a/examples/profile/prices/GetPrices.cs b/examples/profile/prices/GetPrices.cs new file mode 100644 index 0000000..a073874 --- /dev/null +++ b/examples/profile/prices/GetPrices.cs @@ -0,0 +1,15 @@ +using SMSApi.Api; + +var client = new ClientOAuth("token"); +var features = new Features(client); + +var result = features.Prices() + .GetPrices() + .Execute(); + +result.Collection + .ToList() + .ForEach(p => + { + Console.WriteLine($"Price for {p.Country.Name} / {p.Network.Name} is {p.Price.Amount} {p.Price.Currency}"); + }); diff --git a/smsapi/ActionException.cs b/smsapi/ActionException.cs index 044da23..f133a90 100644 --- a/smsapi/ActionException.cs +++ b/smsapi/ActionException.cs @@ -1,11 +1,11 @@ - -namespace SMSApi.Api +using System; + +namespace SMSApi.Api { - public class ActionException : SMSApi.Api.SmsapiException - { - public ActionException(string message, int code) - : base(message, code) - { - } - } -} + public class ActionException : SmsapiException + { + public ActionException(string message, int code) + : base(message, Convert.ToString(code)) + { } + } +} diff --git a/smsapi/Api/Action/Action.cs b/smsapi/Api/Action/Action.cs new file mode 100644 index 0000000..2f8b9de --- /dev/null +++ b/smsapi/Api/Action/Action.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using SMSApi.Api.Response.Deserialization; +using smsapi.Api.Response.Deserialization.Exception; + +namespace SMSApi.Api.Action; + +public abstract class Action +{ + protected BaseJsonDeserializer BaseJsonDeserializer = new(); //TODO remove after further refactor + private Proxy _proxy; + + protected abstract RequestMethod Method { get; } + + protected virtual ApiType ApiType() + { + return Action.ApiType.Legacy; + } + + public T Execute() + { + Validate(); + return ProcessResponse(_proxy.Execute(Uri(), GetValues(), Files(), Method)); + } + + public async Task ExecuteAsync(CancellationToken cancellationToken = default) + { + Validate(); + return ProcessResponse(await _proxy.ExecuteAsync(Uri(), GetValues(), Files(), Method, cancellationToken)); + } + + public void Proxy(Proxy proxy) + { + this._proxy = proxy; + } + + protected virtual Dictionary Files() + { + return new Dictionary(); + } + + protected virtual T ResponseToObject(HttpResponseEntity data) //TODO get rid of overriding + { + IDeserializer deserializer = ApiType() switch + { + Action.ApiType.Rest => new RestJsonResponseDeserializer( + new LegacyJsonResponseDeserializer(), + new ValidationErrorsResolver(new BaseJsonDeserializer()), + new TooManyRequestsErrorResolver(), + new AccessErrorResolver() + ), + Action.ApiType.Legacy => new LegacyJsonResponseDeserializer(), + _ => throw new Exception("Unknown api type") + }; + + var deserializationResult = deserializer.Deserialize(data); + + deserializationResult.ThrowErrors(); + + return deserializationResult.Result; + } + + protected abstract string Uri(); + + protected virtual void Validate() + { + } + + protected virtual NameValueCollection Values() + { + return new NameValueCollection(); + } + + private T ProcessResponse(HttpResponseEntity responseEntity) + { + return ResponseToObject(responseEntity); + } + + private NameValueCollection GetValues() + { + var values = Values(); + return values.Count > 0 + ? new NameValueCollection { { "format", "json" }, values } + : HttpUtility.ParseQueryString(string.Empty); + } +} diff --git a/smsapi/Api/Action/ApiType.cs b/smsapi/Api/Action/ApiType.cs new file mode 100644 index 0000000..c1faac9 --- /dev/null +++ b/smsapi/Api/Action/ApiType.cs @@ -0,0 +1,8 @@ +namespace SMSApi.Api.Action +{ + public enum ApiType + { + Legacy, + Rest, + } +} diff --git a/smsapi/Api/Action/Base.cs b/smsapi/Api/Action/Base.cs deleted file mode 100644 index d89ecde..0000000 --- a/smsapi/Api/Action/Base.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System.IO; -using System.Runtime.Serialization.Json; -using System.Collections.Specialized; -using System.Collections.Generic; -using System; - -namespace SMSApi.Api.Action -{ - public abstract class Base - { - protected IClient client; - protected Proxy proxy; - - abstract protected string Uri(); - - protected virtual RequestMethod Method { get { return RequestMethod.POST; } } - - public void Client(IClient client) - { - this.client = client; - } - - public void Proxy(Proxy proxy) - { - this.proxy = proxy; - } - - protected TT ResponseToObject(Stream data) - { - TT result; - if (data.Length > 0) - { - data.Position = 0; - var serializer = new DataContractJsonSerializer(typeof(TT)); - result = (TT)serializer.ReadObject(data); - data.Position = 0; - } - else - { - result = Activator.CreateInstance(); - } - return result; - } - - abstract protected NameValueCollection Values(); - protected virtual void Validate() { } - - protected virtual Dictionary Files() - { - return null; - } - - protected abstract TResult ConvertResponse(T response); - -/* protected virtual TResult ConvertResponse(T response) - { - return (TResult)Convert.ChangeType(response, typeof(TResult)); - }*/ - - public TResult Execute() - { - Validate(); - - Stream data = proxy.Execute(Uri(), Values(), Files(), Method); - - TResult result = default(TResult); - - HandleError(data); - - try - { - T response = ResponseToObject(data); - result = ConvertResponse(response); - } - catch (System.Runtime.Serialization.SerializationException e) - { - //Problem z prasowaniem json'a - throw new HostException(e.Message + " /" + Uri(), HostException.E_JSON_DECODE); - } - - data.Close(); - - return result; - } - - protected void HandleError(Stream data) { - - data.Position = 0; - - try - { - var error = ResponseToObject(data); - - if (error.Code != 0) - { - if (isHostError(error.Code)) - { - throw new HostException(error.Message, error.Code); - } - if (isClientError(error.Code)) - { - throw new ClientException(error.Message, error.Code); - } - else - { - throw new ActionException(error.Message, error.Code); - } - } - } - catch (System.Runtime.Serialization.SerializationException) { } - - data.Position = 0; - } - - /** - * 101 Niepoprawne lub brak danych autoryzacji. - * 102 Nieprawidłowy login lub hasło - * 103 Brak punków dla tego użytkownika - * 105 Błędny adres IP - * 110 Usługa nie jest dostępna na danym koncie - * 1000 Akcja dostępna tylko dla użytkownika głównego - * 1001 Nieprawidłowa akcja - */ - private bool isClientError(int code) - { - if (code == 101) return true; - if (code == 102) return true; - if (code == 103) return true; - if (code == 105) return true; - if (code == 110) return true; - if (code == 1000) return true; - if (code == 1001) return true; - - return false; - } - - /** - * 8 Błąd w odwołaniu - * 666 Wewnętrzny błąd systemu - * 999 Wewnętrzny błąd systemu - * 201 Wewnętrzny błąd systemu - */ - private bool isHostError(int code) - { - if (code == 8) return true; - if (code == 201) return true; - if (code == 666) return true; - if (code == 999) return true; - - return false; - } - } -} diff --git a/smsapi/Api/Action/BaseArray.cs b/smsapi/Api/Action/BaseArray.cs deleted file mode 100644 index a87b732..0000000 --- a/smsapi/Api/Action/BaseArray.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Collections.Generic; - -namespace SMSApi.Api.Action -{ - public abstract class BaseArray : Base, SMSApi.Api.Response.Array> - { - protected override SMSApi.Api.Response.Array ConvertResponse(List response) - { - return new SMSApi.Api.Response.Array(response); - } - } -} diff --git a/smsapi/Api/Action/BaseSimple.cs b/smsapi/Api/Action/BaseSimple.cs deleted file mode 100644 index d91181d..0000000 --- a/smsapi/Api/Action/BaseSimple.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace SMSApi.Api.Action -{ - public abstract class BaseSimple : Base - { - protected override T ConvertResponse(T response) - { - return response; - } - } -} diff --git a/smsapi/Api/Action/Contacts/BindContactToGroup.cs b/smsapi/Api/Action/Contacts/BindContactToGroup.cs index f746823..ae2f955 100644 --- a/smsapi/Api/Action/Contacts/BindContactToGroup.cs +++ b/smsapi/Api/Action/Contacts/BindContactToGroup.cs @@ -1,25 +1,37 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class BindContactToGroup : Rest - { - public BindContactToGroup(string contactId, string groupId) - : base() - { - ContactId = contactId; - GroupId = groupId; - } + public class BindContactToGroup : Action + { + private readonly string contactId; + private readonly string groupId; - protected override string Resource { get { return "contacts/" + contactId + "/groups/" + groupId; } } + public BindContactToGroup(string contactId, string groupId) + { + this.contactId = contactId; + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.PUT; } } + protected override RequestMethod Method => RequestMethod.PUT; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } + protected override string Uri() + { + return "contacts/" + contactId + "/groups/" + groupId; + } - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override void Validate() + { + if (string.IsNullOrEmpty(contactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/CreateContact.cs b/smsapi/Api/Action/Contacts/CreateContact.cs index 3adfa7f..95d69ef 100644 --- a/smsapi/Api/Action/Contacts/CreateContact.cs +++ b/smsapi/Api/Action/Contacts/CreateContact.cs @@ -1,98 +1,132 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class CreateContact : Rest - { - public CreateContact() - : base() - { - } - - protected override string Resource { get { return "contacts"; } } - - protected override RequestMethod Method { get { return RequestMethod.POST; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (PhoneNumber != null) parameters.Add("phone_number", PhoneNumber); - if (Email != null) parameters.Add("email", Email); - if (FirstName != null) parameters.Add("first_name", FirstName); - if (LastName != null) parameters.Add("last_name", LastName); - if (Gender != null) parameters.Add("gender", Gender); - if (BirthdayDate != null) parameters.Add("birthday_date", BirthdayDate.Value.ToString("Y-m-d")); - if (Description != null) parameters.Add("description", Description); - if (City != null) parameters.Add("city", City); - if (Source != null) parameters.Add("source", Source); - return parameters; - } - } - - public string PhoneNumber; - public CreateContact SetPhoneNumber(string phoneNumber) - { - PhoneNumber = phoneNumber; - return this; - } - - public string Email; - public CreateContact SetEmail(string email) - { - Email = email; - return this; - } - - public string FirstName; - public CreateContact SetFirstName(string firstName) - { - FirstName = firstName; - return this; - } - - public string LastName; - public CreateContact SetLastName(string lastName) - { - LastName = lastName; - return this; - } - - public string Gender; - public CreateContact SetGender(string gender) - { - Gender = gender; - return this; - } - - public DateTime? BirthdayDate; - public CreateContact SetBirthdayDate(DateTime? birthdayDate) - { - BirthdayDate = birthdayDate; - return this; - } - - public string Description; - public CreateContact SetDescription(string description) - { - Description = description; - return this; - } - - public string City; - public CreateContact SetCity(string city) - { - City = city; - return this; - } - - public string Source; - public CreateContact SetSource(string source) - { - Source = source; - return this; - } - } + public class CreateContact : Action + { + private DateTime? birthdayDate; + private string city; + private string description; + private string email; + private string firstName; + private string gender; + private string lastName; + private string phoneNumber; + private string source; + + protected override RequestMethod Method => RequestMethod.POST; + + public CreateContact SetBirthdayDate(DateTime birthdayDate) + { + this.birthdayDate = birthdayDate; + return this; + } + + public CreateContact SetCity(string city) + { + this.city = city; + return this; + } + + public CreateContact SetDescription(string description) + { + this.description = description; + return this; + } + + public CreateContact SetEmail(string email) + { + this.email = email; + return this; + } + + public CreateContact SetFirstName(string firstName) + { + this.firstName = firstName; + return this; + } + + public CreateContact SetGender(string gender) + { + this.gender = gender; + return this; + } + + public CreateContact SetLastName(string lastName) + { + this.lastName = lastName; + return this; + } + + public CreateContact SetPhoneNumber(string phoneNumber) + { + this.phoneNumber = phoneNumber; + return this; + } + + public CreateContact SetSource(string source) + { + this.source = source; + return this; + } + + protected override string Uri() + { + return "contacts"; + } + + protected override NameValueCollection Values() + { + var values = new NameValueCollection(); + + if (birthdayDate != null) + { + values.Add("birthday_date", birthdayDate.Value.ToString("yyyy-MM-dd")); + } + + if (phoneNumber != null) + { + values.Add("phone_number", phoneNumber); + } + + if (email != null) + { + values.Add("email", email); + } + + if (firstName != null) + { + values.Add("first_name", firstName); + } + + if (lastName != null) + { + values.Add("last_name", lastName); + } + + if (gender != null) + { + values.Add("gender", gender); + } + + if (description != null) + { + values.Add("description", description); + } + + if (city != null) + { + values.Add("city", city); + } + + if (source != null) + { + values.Add("source", source); + } + + return values; + } + } } diff --git a/smsapi/Api/Action/Contacts/CreateField.cs b/smsapi/Api/Action/Contacts/CreateField.cs index 9c78d29..e1bf428 100644 --- a/smsapi/Api/Action/Contacts/CreateField.cs +++ b/smsapi/Api/Action/Contacts/CreateField.cs @@ -1,42 +1,46 @@ -using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class CreateField : Rest - { - public CreateField() - : base() - { - } - - protected override string Resource { get { return "contacts/fields"; } } - - protected override RequestMethod Method { get { return RequestMethod.POST; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Name != null) parameters.Add("name", Name); - if (Type != null) parameters.Add("type", Type); - return parameters; - } - } - - public string Name; - public CreateField SetName(string name) - { - Name = name; - return this; - } - - public string Type; - public CreateField SetType(string type) - { - Type = type; - return this; - } - } + public class CreateField : Action + { + private string name; + private string type; + + protected override RequestMethod Method => RequestMethod.POST; + + public CreateField SetName(string name) + { + this.name = name; + return this; + } + + public CreateField SetType(string type) + { + this.type = type; + return this; + } + + protected override string Uri() + { + return "contacts/fields"; + } + + protected override NameValueCollection Values() + { + var values = new NameValueCollection(); + if (name != null) + { + values.Add("name", name); + } + + if (type != null) + { + values.Add("type", type); + } + + return values; + } + } } diff --git a/smsapi/Api/Action/Contacts/CreateGroup.cs b/smsapi/Api/Action/Contacts/CreateGroup.cs index 709ba8b..4cc4fcf 100644 --- a/smsapi/Api/Action/Contacts/CreateGroup.cs +++ b/smsapi/Api/Action/Contacts/CreateGroup.cs @@ -1,50 +1,58 @@ -using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class CreateGroup : Rest - { - public CreateGroup() - : base() - { - } - - protected override string Resource { get { return "contacts/groups"; } } - - protected override RequestMethod Method { get { return RequestMethod.POST; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Name != null) parameters.Add("name", Name); - if (Description != null) parameters.Add("desciption", Description); - if (Idx != null) parameters.Add("idx", Idx); - return parameters; - } - } - - public string Name; - public CreateGroup SetName(string name) - { - Name = name; - return this; - } - - public string Description; - public CreateGroup SetDescription(string description) - { - Description = description; - return this; - } - - public string Idx; - public CreateGroup SetIdx(string idx) - { - Idx = idx; - return this; - } - } + public class CreateGroup : Action + { + private string description; + private string idx; + private string name; + + protected override RequestMethod Method => RequestMethod.POST; + + public CreateGroup SetDescription(string description) + { + this.description = description; + return this; + } + + public CreateGroup SetIdx(string idx) + { + this.idx = idx; + return this; + } + + public CreateGroup SetName(string name) + { + this.name = name; + return this; + } + + protected override string Uri() + { + return "contacts/groups"; + } + + protected override NameValueCollection Values() + { + var values = new NameValueCollection(); + if (name != null) + { + values.Add("name", name); + } + + if (description != null) + { + values.Add("desciption", description); + } + + if (idx != null) + { + values.Add("idx", idx); + } + + return values; + } + } } diff --git a/smsapi/Api/Action/Contacts/CreateGroupPermission.cs b/smsapi/Api/Action/Contacts/CreateGroupPermission.cs index cc6886b..7fb7797 100644 --- a/smsapi/Api/Action/Contacts/CreateGroupPermission.cs +++ b/smsapi/Api/Action/Contacts/CreateGroupPermission.cs @@ -1,62 +1,68 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class CreateGroupPermission : Rest - { - public CreateGroupPermission(string groupId) - : base() - { - GroupId = groupId; - } - - protected override string Resource { get { return "contacts/groups/" + GroupId + "/permissions"; } } - - protected override RequestMethod Method { get { return RequestMethod.POST; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Username != null) parameters.Add("username", Username); - if (Read != null) parameters.Add("read", Convert.ToInt32(Read.Value).ToString()); - if (Write != null) parameters.Add("write", Convert.ToInt32(Write.Value).ToString()); - if (Send != null) parameters.Add("send", Convert.ToInt32(Send.Value).ToString()); - return parameters; - } - } - - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - - public string Username; - public CreateGroupPermission SetUsername(string username) - { - Username = username; - return this; - } - - public bool? Read; - public CreateGroupPermission SetRead(bool? read) - { - Read = read; - return this; - } - - public bool? Write; - public CreateGroupPermission SetWrite(bool? write) - { - Write = write; - return this; - } - - public bool? Send; - public CreateGroupPermission SetSend(bool? send) - { - Send = send; - return this; - } - } + public class CreateGroupPermission : Action + { + private string groupId; + private bool read; + private bool send; + private string username; + private bool write; + + protected override RequestMethod Method => RequestMethod.POST; + + public CreateGroupPermission(string groupId) + { + this.groupId = groupId; + } + + public CreateGroupPermission SetRead(bool read) + { + this.read = read; + return this; + } + + public CreateGroupPermission SetSend(bool send) + { + this.send = send; + return this; + } + + public CreateGroupPermission SetUsername(string username) + { + this.username = username; + return this; + } + + public CreateGroupPermission SetWrite(bool write) + { + this.write = write; + return this; + } + + protected override string Uri() + { + return "contacts/groups/" + groupId + "/permissions"; + } + + protected override NameValueCollection Values() + { + var values = new NameValueCollection + { + { "read", Convert.ToInt32(read).ToString() }, + { "write", Convert.ToInt32(write).ToString() }, + { "send", Convert.ToInt32(send).ToString() } + }; + + if (username != null) + { + values.Add("username", username); + } + + return values; + } + } } diff --git a/smsapi/Api/Action/Contacts/DeleteContact.cs b/smsapi/Api/Action/Contacts/DeleteContact.cs index 200fd63..e096a70 100644 --- a/smsapi/Api/Action/Contacts/DeleteContact.cs +++ b/smsapi/Api/Action/Contacts/DeleteContact.cs @@ -1,21 +1,30 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class DeleteContact : Rest - { - public DeleteContact(string contactId) - : base() - { - ContactId = contactId; - } + public class DeleteContact : Action + { + private readonly string contactId; - protected override string Resource { get { return "contacts/" + ContactId; } } + public DeleteContact(string contactId) + { + this.contactId = contactId; + } - protected override RequestMethod Method { get { return RequestMethod.DELETE; } } + protected override RequestMethod Method => RequestMethod.DELETE; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } - } + protected override string Uri() + { + return "contacts/" + contactId; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(contactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/DeleteField.cs b/smsapi/Api/Action/Contacts/DeleteField.cs index d04a5f8..c041cb7 100644 --- a/smsapi/Api/Action/Contacts/DeleteField.cs +++ b/smsapi/Api/Action/Contacts/DeleteField.cs @@ -1,21 +1,31 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class DeleteField : Rest - { - public DeleteField(string fieldId) - : base() - { - FieldId = fieldId; - } + public class DeleteField : Action + { + private readonly string fieldId; - protected override string Resource { get { return "contacts/fields/" + FieldId; } } + public DeleteField(string fieldId) + { + this.fieldId = fieldId; + } - protected override RequestMethod Method { get { return RequestMethod.DELETE; } } + protected override RequestMethod Method => RequestMethod.DELETE; - private string fieldId; - public string FieldId { get { return fieldId; } private set { fieldId = value; } } - } + protected override string Uri() + { + return "contacts/fields/" + fieldId; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(fieldId)) + { + throw new ArgumentException("FieldId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/DeleteGroup.cs b/smsapi/Api/Action/Contacts/DeleteGroup.cs index b54024c..d2c27ae 100644 --- a/smsapi/Api/Action/Contacts/DeleteGroup.cs +++ b/smsapi/Api/Action/Contacts/DeleteGroup.cs @@ -1,21 +1,31 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class DeleteGroup : Rest - { - public DeleteGroup(string groupId) - : base() - { - GroupId = groupId; - } + public class DeleteGroup : Action + { + private readonly string groupId; - protected override string Resource { get { return "contacts/groups/" + GroupId; } } + public DeleteGroup(string groupId) + { + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.DELETE; } } + protected override RequestMethod Method => RequestMethod.DELETE; - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override string Uri() + { + return "contacts/groups/" + groupId; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/DeleteGroupPermission.cs b/smsapi/Api/Action/Contacts/DeleteGroupPermission.cs index f7a3f0c..4c95bc6 100644 --- a/smsapi/Api/Action/Contacts/DeleteGroupPermission.cs +++ b/smsapi/Api/Action/Contacts/DeleteGroupPermission.cs @@ -1,25 +1,37 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class DeleteGroupPermission : Rest - { - public DeleteGroupPermission(string groupId, string username) - : base() - { - GroupId = groupId; - Username = username; - } + public class DeleteGroupPermission : Action + { + private readonly string groupId; + private readonly string username; - protected override string Resource { get { return "contacts/groups/" + GroupId + "/permissions/" + Username; } } + public DeleteGroupPermission(string groupId, string username) + { + this.groupId = groupId; + this.username = username; + } - protected override RequestMethod Method { get { return RequestMethod.DELETE; } } + protected override RequestMethod Method => RequestMethod.DELETE; - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } + protected override string Uri() + { + return "contacts/groups/" + groupId + "/permissions/" + username; + } - private string username; - public string Username { get { return username; } private set { username = value; } } - } + protected override void Validate() + { + if (string.IsNullOrEmpty(username)) + { + throw new ArgumentException("Username cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/EditContact.cs b/smsapi/Api/Action/Contacts/EditContact.cs index 4635421..5df4491 100644 --- a/smsapi/Api/Action/Contacts/EditContact.cs +++ b/smsapi/Api/Action/Contacts/EditContact.cs @@ -1,102 +1,147 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class EditContact : Rest - { - public EditContact(string contactId) - : base() - { - ContactId = contactId; - } - - protected override string Resource { get { return "contacts/" + ContactId; } } - - protected override RequestMethod Method { get { return RequestMethod.PUT; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (PhoneNumber != null) parameters.Add("phone_number", PhoneNumber); - if (Email != null) parameters.Add("email", Email); - if (FirstName != null) parameters.Add("first_name", FirstName); - if (LastName != null) parameters.Add("last_name", LastName); - if (Gender != null) parameters.Add("gender", Gender); - if (BirthdayDate != null) parameters.Add("birthday_date", BirthdayDate.Value.ToString("Y-m-d")); - if (Description != null) parameters.Add("description", Description); - if (City != null) parameters.Add("city", City); - if (Source != null) parameters.Add("source", Source); - return parameters; - } - } - - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } - - public string PhoneNumber; - public EditContact SetPhoneNumber(string phoneNumber) - { - PhoneNumber = phoneNumber; - return this; - } - - public string Email; - public EditContact SetEmail(string email) - { - Email = email; - return this; - } - - public string FirstName; - public EditContact SetFirstName(string firstName) - { - FirstName = firstName; - return this; - } - - public string LastName; - public EditContact SetLastName(string lastName) - { - LastName = lastName; - return this; - } - - public string Gender; - public EditContact SetGender(string gender) - { - Gender = gender; - return this; - } - - public DateTime? BirthdayDate; - public EditContact SetBirthdayDate(DateTime? birthdayDate) - { - BirthdayDate = birthdayDate; - return this; - } - - public string Description; - public EditContact SetDescription(string description) - { - Description = description; - return this; - } - - public string City; - public EditContact SetCity(string city) - { - City = city; - return this; - } - - public string Source; - public EditContact SetSource(string source) - { - Source = source; - return this; - } - } + public class EditContact : Action + { + private DateTime? birthdayDate; + private string city; + private string description; + private string email; + private string firstName; + private string gender; + private string lastName; + private string phoneNumber; + private string source; + + public EditContact(string contactId) + { + ContactId = contactId; + } + + public string ContactId { get; } + + protected override RequestMethod Method => RequestMethod.PUT; + + public EditContact SetBirthdayDate(DateTime birthdayDate) + { + this.birthdayDate = birthdayDate; + return this; + } + + public EditContact SetCity(string city) + { + this.city = city; + return this; + } + + public EditContact SetDescription(string description) + { + this.description = description; + return this; + } + + public EditContact SetEmail(string email) + { + this.email = email; + return this; + } + + public EditContact SetFirstName(string firstName) + { + this.firstName = firstName; + return this; + } + + public EditContact SetGender(string gender) + { + this.gender = gender; + return this; + } + + public EditContact SetLastName(string lastName) + { + this.lastName = lastName; + return this; + } + + public EditContact SetPhoneNumber(string phoneNumber) + { + this.phoneNumber = phoneNumber; + return this; + } + + public EditContact SetSource(string source) + { + this.source = source; + return this; + } + + protected override string Uri() + { + return "contacts/" + ContactId; + } + + protected override NameValueCollection Values() + { + var values = new NameValueCollection(); + + if (birthdayDate != null) + { + values.Add("birthday_date", birthdayDate.Value.ToString("yyyy-MM-dd")); + } + + if (phoneNumber != null) + { + values.Add("phone_number", phoneNumber); + } + + if (email != null) + { + values.Add("email", email); + } + + if (firstName != null) + { + values.Add("first_name", firstName); + } + + if (lastName != null) + { + values.Add("last_name", lastName); + } + + if (gender != null) + { + values.Add("gender", gender); + } + + if (description != null) + { + values.Add("description", description); + } + + if (city != null) + { + values.Add("city", city); + } + + if (source != null) + { + values.Add("source", source); + } + + return values; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(ContactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/EditField.cs b/smsapi/Api/Action/Contacts/EditField.cs index 428a0ce..d886403 100644 --- a/smsapi/Api/Action/Contacts/EditField.cs +++ b/smsapi/Api/Action/Contacts/EditField.cs @@ -1,38 +1,50 @@ using System; using System.Collections.Specialized; +using System.Text.RegularExpressions; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class EditField : Rest - { - public EditField(string fieldId) - : base() - { - FieldId = fieldId; - } - - protected override string Resource { get { return "contacts/fields/" + FieldId; } } - - protected override RequestMethod Method { get { return RequestMethod.PUT; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Name != null) parameters.Add("name", Name); - return parameters; - } - } - - private string fieldId; - public string FieldId { get { return fieldId; } private set { fieldId = value; } } - - public string Name; - public EditField SetName(string name) - { - Name = name; - return this; - } - } + public class EditField : Action + { + private string fieldId; + private string name; + + public EditField(string fieldId) + { + this.fieldId = fieldId; + } + + protected override RequestMethod Method => RequestMethod.PUT; + + public EditField SetName(string name) + { + this.name = name; + return this; + } + + protected override string Uri() + { + return "contacts/fields/" + fieldId; + } + + protected override NameValueCollection Values() + { + var parameters = new NameValueCollection(); + if (name != null) + { + parameters.Add("name", name); + } + + return parameters; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(fieldId)) + { + throw new ArgumentException("FieldId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/EditGroup.cs b/smsapi/Api/Action/Contacts/EditGroup.cs index 85bf232..b0d4125 100644 --- a/smsapi/Api/Action/Contacts/EditGroup.cs +++ b/smsapi/Api/Action/Contacts/EditGroup.cs @@ -1,54 +1,73 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class EditGroup : Rest - { - public EditGroup(string groupId) - : base() - { - GroupId = groupId; - } - - protected override string Resource { get { return "contacts/groups/" + GroupId; } } - - protected override RequestMethod Method { get { return RequestMethod.PUT; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Name != null) parameters.Add("name", Name); - if (Description != null) parameters.Add("desciption", Description); - if (Idx != null) parameters.Add("idx", Idx); - return parameters; - } - } - - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - - public string Name; - public EditGroup SetName(string name) - { - Name = name; - return this; - } - - public string Description; - public EditGroup SetDescription(string description) - { - Description = description; - return this; - } - - public string Idx; - public EditGroup SetIdx(string idx) - { - Idx = idx; - return this; - } - } + public class EditGroup : Action + { + private string description; + private string groupId; + private string idx; + private string name; + + public EditGroup(string groupId) + { + this.groupId = groupId; + } + + protected override RequestMethod Method => RequestMethod.PUT; + + public EditGroup SetDescription(string description) + { + this.description = description; + return this; + } + + public EditGroup SetIdx(string idx) + { + this.idx = idx; + return this; + } + + public EditGroup SetName(string name) + { + this.name = name; + return this; + } + + protected override string Uri() + { + return "contacts/groups/" + groupId; + } + + protected override NameValueCollection Values() + { + var parameters = new NameValueCollection(); + if (name != null) + { + parameters.Add("name", name); + } + + if (description != null) + { + parameters.Add("description", description); + } + + if (idx != null) + { + parameters.Add("idx", idx); + } + + return parameters; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/EditGroupPermission.cs b/smsapi/Api/Action/Contacts/EditGroupPermission.cs index 55f052f..9288f93 100644 --- a/smsapi/Api/Action/Contacts/EditGroupPermission.cs +++ b/smsapi/Api/Action/Contacts/EditGroupPermission.cs @@ -1,58 +1,69 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class EditGroupPermission : Rest - { - public EditGroupPermission(string groupId, string username) - : base() - { - GroupId = groupId; - Username = username; - } - - protected override string Resource { get { return "contacts/groups/" + GroupId + "/permissions/" + Username; } } - - protected override RequestMethod Method { get { return RequestMethod.PUT; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Read != null) parameters.Add("read", Convert.ToInt32(Read.Value).ToString()); - if (Write != null) parameters.Add("write", Convert.ToInt32(Write.Value).ToString()); - if (Send != null) parameters.Add("send", Convert.ToInt32(Send.Value).ToString()); - return parameters; - } - } - - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - - private string username; - public string Username { get { return username; } private set { username = value; } } - - public bool? Read; - public EditGroupPermission SetRead(bool? read) - { - Read = read; - return this; - } - - public bool? Write; - public EditGroupPermission SetWrite(bool? write) - { - Write = write; - return this; - } - - public bool? Send; - public EditGroupPermission SetSend(bool? send) - { - Send = send; - return this; - } - } + public class EditGroupPermission : Action + { + private string groupId; + private bool read; + private bool send; + private string username; + private bool write; + + public EditGroupPermission(string groupId, string username) + { + this.groupId = groupId; + this.username = username; + } + + protected override RequestMethod Method => RequestMethod.PUT; + + public EditGroupPermission SetRead(bool read) + { + this.read = read; + return this; + } + + public EditGroupPermission SetSend(bool send) + { + this.send = send; + return this; + } + + public EditGroupPermission SetWrite(bool write) + { + this.write = write; + return this; + } + + protected override string Uri() + { + return "contacts/groups/" + groupId + "/permissions/" + username; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "read", Convert.ToInt32(read).ToString() }, + { "write", Convert.ToInt32(write).ToString() }, + { "send", Convert.ToInt32(send).ToString() } + }; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(username)) + { + throw new ArgumentException("Username cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/GetContact.cs b/smsapi/Api/Action/Contacts/GetContact.cs index 4bad4ab..581688e 100644 --- a/smsapi/Api/Action/Contacts/GetContact.cs +++ b/smsapi/Api/Action/Contacts/GetContact.cs @@ -1,21 +1,30 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class GetContact : Rest - { - public GetContact(string contactId) - : base() - { - ContactId = contactId; - } + public class GetContact : Action + { + private readonly string contactId; - protected override string Resource { get { return "contacts/" + ContactId; } } + public GetContact(string contactId) + { + this.contactId = contactId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } - } + protected override string Uri() + { + return "contacts/" + contactId; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(contactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/GetContactGroup.cs b/smsapi/Api/Action/Contacts/GetContactGroup.cs index 8bf4eb4..e6161e2 100644 --- a/smsapi/Api/Action/Contacts/GetContactGroup.cs +++ b/smsapi/Api/Action/Contacts/GetContactGroup.cs @@ -1,25 +1,37 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class GetContactGroup : Rest - { - public GetContactGroup(string contactId, string groupId) - : base() - { - ContactId = contactId; - GroupId = groupId; - } + public class GetContactGroup : Action + { + private readonly string contactId; + private readonly string groupId; - protected override string Resource { get { return "contacts/" + contactId + "/groups/" + groupId; } } + public GetContactGroup(string contactId, string groupId) + { + this.contactId = contactId; + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } + protected override string Uri() + { + return "contacts/" + contactId + "/groups/" + groupId; + } - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override void Validate() + { + if (string.IsNullOrEmpty(contactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/GetGroup.cs b/smsapi/Api/Action/Contacts/GetGroup.cs index 24f7d4f..cf3d3d3 100644 --- a/smsapi/Api/Action/Contacts/GetGroup.cs +++ b/smsapi/Api/Action/Contacts/GetGroup.cs @@ -1,21 +1,30 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class GetGroup : Rest - { - public GetGroup(string groupId) - : base() - { - GroupId = groupId; - } + public class GetGroup : Action + { + private string groupId; - protected override string Resource { get { return "contacts/groups/" + GroupId; } } + public GetGroup(string groupId) + { + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override string Uri() + { + return "contacts/groups/" + groupId; + } + + protected override void Validate() + { + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/GetGroupPermission.cs b/smsapi/Api/Action/Contacts/GetGroupPermission.cs index bf1304a..5d24349 100644 --- a/smsapi/Api/Action/Contacts/GetGroupPermission.cs +++ b/smsapi/Api/Action/Contacts/GetGroupPermission.cs @@ -1,25 +1,37 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class GetGroupPermission : Rest - { - public GetGroupPermission(string groupId, string username) - : base() - { - GroupId = groupId; - Username = username; - } + public class GetGroupPermission : Action + { + private readonly string groupId; + private readonly string username; - protected override string Resource { get { return "contacts/groups/" + GroupId + "/permissions/" + Username; } } + public GetGroupPermission(string groupId, string username) + { + this.groupId = groupId; + this.username = username; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } + protected override string Uri() + { + return "contacts/groups/" + groupId + "/permissions/" + username; + } - private string username; - public string Username { get { return username; } private set { username = value; } } - } + protected override void Validate() + { + if (string.IsNullOrEmpty(username)) + { + throw new ArgumentException("Username cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/Contacts/ListContactGroups.cs b/smsapi/Api/Action/Contacts/ListContactGroups.cs index 3dddeaa..1232906 100644 --- a/smsapi/Api/Action/Contacts/ListContactGroups.cs +++ b/smsapi/Api/Action/Contacts/ListContactGroups.cs @@ -1,21 +1,21 @@ -using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListContactGroups : Rest - { - public ListContactGroups(string contactId) - : base() - { - ContactId = contactId; - } + public class ListContactGroups : Action + { + private readonly string contactId; - protected override string Resource { get { return "contacts/" + ContactId + "/groups"; } } + public ListContactGroups(string contactId) + { + this.contactId = contactId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } - } + protected override string Uri() + { + return "contacts/" + contactId + "/groups"; + } + } } diff --git a/smsapi/Api/Action/Contacts/ListContacts.cs b/smsapi/Api/Action/Contacts/ListContacts.cs index a729b88..64e1fa8 100644 --- a/smsapi/Api/Action/Contacts/ListContacts.cs +++ b/smsapi/Api/Action/Contacts/ListContacts.cs @@ -1,106 +1,143 @@ using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListContacts : Rest - { - public ListContacts () - : base() - { - } - - protected override string Resource { get { return "contacts"; } } - - protected override RequestMethod Method { get { return RequestMethod.GET; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - if (Search != null) parameters.Add("q", Search); - if (Offset != null) parameters.Add("offset", Offset.Value.ToString()); - if (Limit != null) parameters.Add("limit", Limit.Value.ToString()); - if (PhoneNumber != null) parameters.Add("phone_number", PhoneNumber); - if (Email != null) parameters.Add("email", Email); - if (FirstName != null) parameters.Add("first_name", FirstName); - if (LastName != null) parameters.Add("last_name", LastName); - if (GroupId != null) parameters.Add("group_id", GroupId.Value.ToString()); - if (Gender != null) parameters.Add("gender", Gender); - if (BirthdayDate != null) parameters.Add("birthday_date", BirthdayDate.Value.ToString("Y-m-d")); - return parameters; - } - } - - public string Search; - public ListContacts SetSearch(string search) - { - Search = search; - return this; - } - - public int? Offset; - public ListContacts SetOffset(int? offset) - { - Offset = offset; - return this; - } - - public int? Limit; - public ListContacts SetLimit(int? limit) - { - Limit = limit; - return this; - } - - public string PhoneNumber; - public ListContacts SetPhoneNumber(string phoneNumber) - { - PhoneNumber = phoneNumber; - return this; - } - - public string Email; - public ListContacts SetEmail(string email) - { - Email = email; - return this; - } - - public string FirstName; - public ListContacts SetFirstName(string firstName) - { - FirstName = firstName; - return this; - } - - public string LastName; - public ListContacts SetLastName(string lastName) - { - LastName = lastName; - return this; - } - - public int? GroupId; - public ListContacts SetGroupId(int? groupId) - { - GroupId = groupId; - return this; - } - - public string Gender; - public ListContacts SetGender(string gender) - { - Gender = gender; - return this; - } - - public DateTime? BirthdayDate; - public ListContacts SetBirthdayDate(DateTime? birthdayDate) - { - BirthdayDate = birthdayDate; - return this; - } - } + public class ListContacts : Action + { + private DateTime? birthdayDate; + private string email; + private string firstName; + private string gender; + private int? groupId; + private string lastName; + private int? limit; + private int? offset; + private string phoneNumber; + private string search; + + protected override RequestMethod Method => RequestMethod.GET; + + public ListContacts SetBirthdayDate(DateTime? birthdayDate) + { + this.birthdayDate = birthdayDate; + return this; + } + + public ListContacts SetEmail(string email) + { + this.email = email; + return this; + } + + public ListContacts SetFirstName(string firstName) + { + this.firstName = firstName; + return this; + } + + public ListContacts SetGender(string gender) + { + this.gender = gender; + return this; + } + + public ListContacts SetGroupId(int? groupId) + { + this.groupId = groupId; + return this; + } + + public ListContacts SetLastName(string lastName) + { + this.lastName = lastName; + return this; + } + + public ListContacts SetLimit(int? limit) + { + this.limit = limit; + return this; + } + + public ListContacts SetOffset(int? offset) + { + this.offset = offset; + return this; + } + + public ListContacts SetPhoneNumber(string phoneNumber) + { + this.phoneNumber = phoneNumber; + return this; + } + + public ListContacts SetSearch(string search) + { + this.search = search; + return this; + } + + protected override string Uri() + { + return "contacts"; + } + + protected override NameValueCollection Values() + { + var parameters = new NameValueCollection(); + if (search != null) + { + parameters.Add("q", search); + } + + if (offset != null) + { + parameters.Add("offset", offset.Value.ToString()); + } + + if (limit != null) + { + parameters.Add("limit", limit.Value.ToString()); + } + + if (phoneNumber != null) + { + parameters.Add("phone_number", phoneNumber); + } + + if (email != null) + { + parameters.Add("email", email); + } + + if (firstName != null) + { + parameters.Add("first_name", firstName); + } + + if (lastName != null) + { + parameters.Add("last_name", lastName); + } + + if (groupId != null) + { + parameters.Add("group_id", groupId.Value.ToString()); + } + + if (gender != null) + { + parameters.Add("gender", gender); + } + + if (birthdayDate != null) + { + parameters.Add("birthday_date", birthdayDate.Value.ToString("yyyy-MM-dd")); + } + + return parameters; + } + } } diff --git a/smsapi/Api/Action/Contacts/ListFieldOptions.cs b/smsapi/Api/Action/Contacts/ListFieldOptions.cs index b637819..282fd46 100644 --- a/smsapi/Api/Action/Contacts/ListFieldOptions.cs +++ b/smsapi/Api/Action/Contacts/ListFieldOptions.cs @@ -1,21 +1,21 @@ -using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListFieldOptions : Rest - { - public ListFieldOptions(string fieldId) - : base() - { - FieldId = fieldId; - } + public class ListFieldOptions : Action + { + private readonly string fieldId; - protected override string Resource { get { return "contacts/fields/" + FieldId + "/options"; } } + public ListFieldOptions(string fieldId) + { + this.fieldId = fieldId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string fieldId; - public string FieldId { get { return fieldId; } private set { fieldId = value; } } - } + protected override string Uri() + { + return "contacts/fields/" + fieldId + "/options"; + } + } } diff --git a/smsapi/Api/Action/Contacts/ListFields.cs b/smsapi/Api/Action/Contacts/ListFields.cs index 61f3b67..6e27dd0 100644 --- a/smsapi/Api/Action/Contacts/ListFields.cs +++ b/smsapi/Api/Action/Contacts/ListFields.cs @@ -1,17 +1,14 @@ -using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListFields : Rest - { - public ListFields () - : base() - { - } + public class ListFields : Action + { + protected override RequestMethod Method => RequestMethod.GET; - protected override string Resource { get { return "contacts/fields"; } } - - protected override RequestMethod Method { get { return RequestMethod.GET; } } - } + protected override string Uri() + { + return "contacts/fields"; + } + } } diff --git a/smsapi/Api/Action/Contacts/ListGroupPermissions.cs b/smsapi/Api/Action/Contacts/ListGroupPermissions.cs index 1857022..de5e109 100644 --- a/smsapi/Api/Action/Contacts/ListGroupPermissions.cs +++ b/smsapi/Api/Action/Contacts/ListGroupPermissions.cs @@ -1,21 +1,21 @@ -using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListGroupPermissions : Rest - { - public ListGroupPermissions(string groupId) - : base() - { - GroupId = groupId; - } + public class ListGroupPermissions : Action + { + private string groupId; - protected override string Resource { get { return "contacts/groups/" + GroupId + "/permissions"; } } + public ListGroupPermissions(string groupId) + { + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.GET; } } + protected override RequestMethod Method => RequestMethod.GET; - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override string Uri() + { + return "contacts/groups/" + groupId + "/permissions"; + } + } } diff --git a/smsapi/Api/Action/Contacts/ListGroups.cs b/smsapi/Api/Action/Contacts/ListGroups.cs index c1c8544..6c36a87 100644 --- a/smsapi/Api/Action/Contacts/ListGroups.cs +++ b/smsapi/Api/Action/Contacts/ListGroups.cs @@ -1,43 +1,50 @@ -using System; using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class ListGroups : Rest - { - public ListGroups () - : base() - { - } - - protected override string Resource { get { return "contacts/groups"; } } - - protected override RequestMethod Method { get { return RequestMethod.GET; } } - - protected override NameValueCollection Parameters - { - get - { - NameValueCollection parameters = base.Parameters; - parameters.Add("with", "contacts_count"); - if (Id != null) parameters.Add("id", Id); - if (Name != null) parameters.Add("name", Name); - return parameters; - } - } - - public string Id; - public ListGroups SetId(string id) - { - Id = id; - return this; - } - - public string Name; - public ListGroups SetName(string name) - { - Name = name; - return this; - } - } + public class ListGroups : Action + { + private string id; + private string name; + + protected override RequestMethod Method => RequestMethod.GET; + + public ListGroups SetId(string id) + { + this.id = id; + return this; + } + + public ListGroups SetName(string name) + { + this.name = name; + return this; + } + + protected override string Uri() + { + return "contacts/groups"; + } + + protected override NameValueCollection Values() + { + var parameters = new NameValueCollection + { + { "with", "contacts_count" } + }; + + if (id != null) + { + parameters.Add("id", id); + } + + if (name != null) + { + parameters.Add("name", name); + } + + return parameters; + } + } } diff --git a/smsapi/Api/Action/Contacts/UnbindContactFromGroup.cs b/smsapi/Api/Action/Contacts/UnbindContactFromGroup.cs index a6da74d..4385041 100644 --- a/smsapi/Api/Action/Contacts/UnbindContactFromGroup.cs +++ b/smsapi/Api/Action/Contacts/UnbindContactFromGroup.cs @@ -1,25 +1,38 @@ using System; -using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class UnbindContactFromGroup : Rest - { - public UnbindContactFromGroup(string contactId, string groupId) - : base() - { - ContactId = contactId; - GroupId = groupId; - } + public class UnbindContactFromGroup : Action + { + private readonly string contactId; + private readonly string groupId; - protected override string Resource { get { return "contacts/" + contactId + "/groups/" + groupId; } } + public UnbindContactFromGroup(string contactId, string groupId) + { + this.contactId = contactId; + this.groupId = groupId; + } - protected override RequestMethod Method { get { return RequestMethod.DELETE; } } + protected override RequestMethod Method => RequestMethod.DELETE; - private string contactId; - public string ContactId { get { return contactId; } private set { contactId = value; } } + protected override string Uri() + { + return "contacts/" + contactId + "/groups/" + groupId; + } - private string groupId; - public string GroupId { get { return groupId; } private set { groupId = value; } } - } + protected override void Validate() + { + if (string.IsNullOrEmpty(contactId)) + { + throw new ArgumentException("ContactId cannot be empty"); + } + + if (string.IsNullOrEmpty(groupId)) + { + throw new ArgumentException("GroupId cannot be empty"); + } + } + } } diff --git a/smsapi/Api/Action/HLR/CheckNumber.cs b/smsapi/Api/Action/HLR/CheckNumber.cs index 032cf79..305cee9 100644 --- a/smsapi/Api/Action/HLR/CheckNumber.cs +++ b/smsapi/Api/Action/HLR/CheckNumber.cs @@ -1,37 +1,31 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class HLRCheckNumber : BaseSimple + public class HLRCheckNumber : Action { - public HLRCheckNumber() : base() { } + private string number; - protected override string Uri() { return "hlrsync.do"; } - - protected string[] numbers; + protected override RequestMethod Method => RequestMethod.POST; public HLRCheckNumber SetNumber(string number) { - this.numbers = new string[] { number }; + this.number = number; return this; } -/* - public HLRCheckNumber SetNumber(string[] numbers) + protected override string Uri() { - this.numbers = numbers; - return this; + return "hlrsync.do"; } -*/ protected override NameValueCollection Values() { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("number", string.Join(",", numbers)); - - return collection; + return new NameValueCollection + { + { "number", this.number } + }; } - } + } } diff --git a/smsapi/Api/Action/MFA/CreateMFACode.cs b/smsapi/Api/Action/MFA/CreateMFACode.cs new file mode 100644 index 0000000..e9c8bf4 --- /dev/null +++ b/smsapi/Api/Action/MFA/CreateMFACode.cs @@ -0,0 +1,66 @@ +using System.Collections.Specialized; +using SMSApi.Api.Response.MFA; + +namespace SMSApi.Api.Action.MFA; + +public class CreateMFACode : Action +{ + private readonly string phoneNumber; + private string content; + private bool fast; + private string from; + + public CreateMFACode(string phoneNumber) + { + this.phoneNumber = phoneNumber; + } + + protected override RequestMethod Method => RequestMethod.POST; + + public CreateMFACode AsFast() + { + fast = true; + + return this; + } + + public CreateMFACode FromSendername(string sendername) + { + from = sendername; + + return this; + } + + public CreateMFACode WithContent(string content) + { + this.content = content; + + return this; + } + + protected override ApiType ApiType() + { + return Action.ApiType.Rest; + } + + protected override string Uri() + { + return "mfa/codes"; + } + + protected override NameValueCollection Values() + { + var parameters = new NameValueCollection { { "phone_number", phoneNumber } }; + + if (content != null) + parameters.Add("content", content); + + if (fast) + parameters.Add("fast", "1"); + + if (from != null) + parameters.Add("from", from); + + return parameters; + } +} diff --git a/smsapi/Api/Action/MFA/VerifyMFACode.cs b/smsapi/Api/Action/MFA/VerifyMFACode.cs new file mode 100644 index 0000000..30ec8c8 --- /dev/null +++ b/smsapi/Api/Action/MFA/VerifyMFACode.cs @@ -0,0 +1,33 @@ +using System.Collections.Specialized; +using SMSApi.Api.Response.MFA; + +namespace SMSApi.Api.Action.MFA; + +public class VerifyMFACode : Action +{ + private readonly string code; + private readonly string phoneNumber; + + public VerifyMFACode(string phoneNumber, string code) + { + this.phoneNumber = phoneNumber; + this.code = code; + } + + protected override RequestMethod Method => RequestMethod.POST; + + protected override ApiType ApiType() + { + return Action.ApiType.Rest; + } + + protected override string Uri() + { + return "mfa/codes/verifications"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection { { "phone_number", phoneNumber }, { "code", code } }; + } +} diff --git a/smsapi/Api/Action/MMS/Delete.cs b/smsapi/Api/Action/MMS/Delete.cs index c0ca5f5..94e23d7 100644 --- a/smsapi/Api/Action/MMS/Delete.cs +++ b/smsapi/Api/Action/MMS/Delete.cs @@ -1,28 +1,17 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class MMSDelete : BaseSimple + public class MMSDelete : Action { - public MMSDelete() : base() { } + private string[] ids; - protected override string Uri() { return "mms.do"; } - - protected string[] ids; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("sch_del", string.Join("|", ids)); - - return collection; - } + protected override RequestMethod Method => RequestMethod.POST; public MMSDelete Id(string id) { - this.ids = new string[] { id }; + ids = new[] { id }; return this; } @@ -31,5 +20,18 @@ public MMSDelete Ids(string[] ids) this.ids = ids; return this; } + + protected override string Uri() + { + return "mms.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "sch_del", string.Join("|", ids) } + }; + } } } diff --git a/smsapi/Api/Action/MMS/Get.cs b/smsapi/Api/Action/MMS/Get.cs index d76a055..85fced2 100644 --- a/smsapi/Api/Action/MMS/Get.cs +++ b/smsapi/Api/Action/MMS/Get.cs @@ -1,28 +1,17 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class MMSGet : BaseSimple + public class MMSGet : Action { - public MMSGet() : base() { } + private string[] ids; - protected override string Uri() { return "mms.do"; } - - protected string[] ids; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("status", string.Join("|", ids)); - - return collection; - } + protected override RequestMethod Method => RequestMethod.POST; public MMSGet Id(string id) { - this.ids = new string[] { id }; + ids = new[] { id }; return this; } @@ -31,5 +20,18 @@ public MMSGet Ids(string[] ids) this.ids = ids; return this; } + + protected override string Uri() + { + return "mms.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "status", string.Join("|", ids) } + }; + } } } diff --git a/smsapi/Api/Action/MMS/Send.cs b/smsapi/Api/Action/MMS/Send.cs index a11a401..6793145 100644 --- a/smsapi/Api/Action/MMS/Send.cs +++ b/smsapi/Api/Action/MMS/Send.cs @@ -5,131 +5,145 @@ namespace SMSApi.Api.Action { public class MMSSend : Send { - public MMSSend() : base() { } - - protected override string Uri() { return "mms.do"; } - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - - if (To != null) - collection.Add("to", string.Join(",", To)); - - if (Group != null) - collection.Add("group", Group); - - if (Subject != null) - collection.Add("subject", Subject); - - collection.Add("smil", Smil); - - if (DateSent != null) - collection.Add("date", DateSent); - - if (Partner != null) - collection.Add("partner_id", Partner); + private string Smil; - if (Test == true) - collection.Add("test", "1"); + private string Subject; - if (Idx != null && Idx.Length > 0) - { - collection.Add("check_idx", (IdxCheck ? "1" : "0")); - collection.Add("idx", string.Join("|", Idx)); - } + protected override RequestMethod Method => RequestMethod.POST; - return collection; - } - - protected override void Validate() + public MMSSend SetCheckIDx(bool check = true) { - if( To != null && Group != null ) - { - throw new ArgumentException("Cannot use 'to' and 'group' at the same time!"); - } - - if (Smil == null || Smil.Length < 1) - { - throw new ArgumentException("Cannot send message without smil!"); - } + IdxCheck = check; + return this; } - private string Subject; - private string Smil; - - public MMSSend SetTo(string to) + public MMSSend SetDateSent(string data) { - this.To = new string[] { to }; + DateSent = data; return this; } - public MMSSend SetTo(string[] to) + public MMSSend SetDateSent(DateTime data) { - this.To = to; + DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); return this; } public MMSSend SetGroup(string group) { - this.Group = group; + Group = group; return this; } - public MMSSend SetDateSent(string data) + public MMSSend SetIDx(string idx) { - this.DateSent = data; + Idx = new[] { idx }; return this; } - public MMSSend SetDateSent(DateTime data) + public MMSSend SetIDx(string[] idx) { - this.DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); + Idx = idx; return this; } - public MMSSend SetIDx(string idx) + public MMSSend SetPartner(string partner) { - this.Idx = new string[] { idx }; + Partner = partner; return this; } - public MMSSend SetIDx(string[] idx) + public MMSSend SetSmil(string smil) { - this.Idx = idx; + Smil = smil; return this; } - public MMSSend SetCheckIDx(bool check = true) + public MMSSend SetSubject(string subject) { - this.IdxCheck = check; + Subject = subject; return this; } - public MMSSend SetSubject(string subject) + public MMSSend SetTest(bool test = true) { - this.Subject = subject; + Test = test; return this; } - public MMSSend SetSmil(string smil) + public MMSSend SetTo(string to) { - this.Smil = smil; + To = new[] { to }; return this; } - public MMSSend SetPartner(string partner) + public MMSSend SetTo(string[] to) { - this.Partner = partner; + To = to; return this; } - public MMSSend SetTest(bool test = true) + protected override string Uri() { - this.Test = test; - return this; + return "mms.do"; + } + + protected override void Validate() + { + if (To != null && Group != null) + { + throw new ArgumentException("Cannot use 'to' and 'group' at the same time!"); + } + + if (Smil == null || Smil.Length < 1) + { + throw new ArgumentException("Cannot send message without smil!"); + } + } + + protected override NameValueCollection Values() + { + var collection = new NameValueCollection(); + + if (To != null) + { + collection.Add("to", string.Join(",", To)); + } + + if (Group != null) + { + collection.Add("group", Group); + } + + if (Subject != null) + { + collection.Add("subject", Subject); + } + + collection.Add("smil", Smil); + + if (DateSent != null) + { + collection.Add("date", DateSent); + } + + if (Partner != null) + { + collection.Add("partner_id", Partner); + } + + if (Test) + { + collection.Add("test", "1"); + } + + if (Idx != null && Idx.Length > 0) + { + collection.Add("check_idx", IdxCheck ? "1" : "0"); + collection.Add("idx", string.Join("|", Idx)); + } + + return collection; } } } diff --git a/smsapi/Api/Action/Phonebook/ContactAdd.cs b/smsapi/Api/Action/Phonebook/ContactAdd.cs deleted file mode 100644 index 34aa350..0000000 --- a/smsapi/Api/Action/Phonebook/ContactAdd.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookContactAdd : BaseSimple - { - public PhonebookContactAdd() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string number; - protected string firstName; - protected string lastName; - protected string info; - protected int birthday; - protected string city; - protected string gender; - protected string[] groups; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("add_contact", number); - - if (firstName != null) collection.Add("first_name", firstName); - if (lastName != null) collection.Add("last_name", lastName); - if (info != null) collection.Add("info", info); - if (birthday != 0) collection.Add("birthday", birthday.ToString()); - if (city != null) collection.Add("city", city); - if (gender != null) collection.Add("gender", gender); - if (groups != null) collection.Add("groups", string.Join(",", groups)); - - return collection; - } - - public PhonebookContactAdd SetNumber(string number) - { - this.number = number; - return this; - } - - public PhonebookContactAdd SetFirstName(string firstName) - { - this.firstName = firstName; - return this; - } - - public PhonebookContactAdd SetLastName(string lastName) - { - this.lastName = lastName; - return this; - } - - public PhonebookContactAdd SetInfo(string info) - { - this.info = info; - return this; - } - - public PhonebookContactAdd SetBirthday(int birthday) - { - this.birthday = birthday; - return this; - } - - public PhonebookContactAdd SetCity(string city) - { - this.city = city; - return this; - } - - public PhonebookContactAdd SetGender(string gender) - { - this.gender = gender; - return this; - } - - public PhonebookContactAdd SetGroup(string group) - { - this.groups = new string[] {group}; - return this; - } - - public PhonebookContactAdd SetGroups(string[] groups) - { - this.groups = groups; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/ContactDelete.cs b/smsapi/Api/Action/Phonebook/ContactDelete.cs deleted file mode 100644 index cdb50b6..0000000 --- a/smsapi/Api/Action/Phonebook/ContactDelete.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookContactDelete : BaseSimple - { - public PhonebookContactDelete() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string number; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("delete_contact", number); - - return collection; - } - - public PhonebookContactDelete Number(string number) - { - this.number = number; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/ContactEdit.cs b/smsapi/Api/Action/Phonebook/ContactEdit.cs deleted file mode 100644 index da77213..0000000 --- a/smsapi/Api/Action/Phonebook/ContactEdit.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookContactEdit : BaseSimple - { - public PhonebookContactEdit() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string oldNumber; - protected string newNumber; - protected string firstName; - protected string lastName; - protected string info; - protected int birthday; - protected string city; - protected string gender; - protected string[] groups; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("edit_contact", oldNumber); - - if (newNumber != null) collection.Add("new_number", newNumber); - if (firstName != null) collection.Add("first_name", firstName); - if (lastName != null) collection.Add("last_name", lastName); - if (info != null) collection.Add("info", info); - if (birthday != 0) collection.Add("birthday", birthday.ToString()); - if (city != null) collection.Add("city", city); - if (gender != null) collection.Add("gender", gender); - if (groups != null) collection.Add("groups", string.Join(",", groups)); - - return collection; - } - - public PhonebookContactEdit Number(string number) - { - this.oldNumber = number; - return this; - } - - public PhonebookContactEdit SetNumber(string number) - { - this.newNumber = number; - return this; - } - - public PhonebookContactEdit SetFirstName(string firstName) - { - this.firstName = firstName; - return this; - } - - public PhonebookContactEdit SetLastName(string lastName) - { - this.lastName = lastName; - return this; - } - - public PhonebookContactEdit SetInfo(string info) - { - this.info = info; - return this; - } - - public PhonebookContactEdit SetBirthday(int birthday) - { - this.birthday = birthday; - return this; - } - - public PhonebookContactEdit SetCity(string city) - { - this.city = city; - return this; - } - - public PhonebookContactEdit SetGender(string gender) - { - this.gender = gender; - return this; - } - - public PhonebookContactEdit SetGroup(string group) - { - this.groups = new string[] {group}; - return this; - } - - public PhonebookContactEdit SetGroups(string[] groups) - { - this.groups = groups; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/ContactGet.cs b/smsapi/Api/Action/Phonebook/ContactGet.cs deleted file mode 100644 index 24c3849..0000000 --- a/smsapi/Api/Action/Phonebook/ContactGet.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookContactGet : BaseSimple - { - public PhonebookContactGet() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string number; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("get_contact", number); - - return collection; - } - - public PhonebookContactGet Number(string number) - { - this.number = number; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/ContactList.cs b/smsapi/Api/Action/Phonebook/ContactList.cs deleted file mode 100644 index 76a91d9..0000000 --- a/smsapi/Api/Action/Phonebook/ContactList.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookContactList : BaseSimple - { - public PhonebookContactList() - : base() - { - offset = 0; - limit = 0; - } - - protected override string Uri() { return "phonebook.do"; } - - protected string number; - protected string[] groups; - protected string searchText; - protected string gender; - protected string orderBy; - protected string orderDir; - protected uint limit; - protected uint offset; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("list_contacts", ""); - - if (number != null && number.Length > 0) collection.Add("number", number); - if (groups != null && groups.Length > 0) collection.Add("groups", string.Join(";", groups)); - if (searchText != null && searchText.Length > 0) collection.Add("text_search", searchText); - if (gender != null && gender.Length > 0) collection.Add("gender", gender); - if (orderBy != null && orderBy.Length > 0) collection.Add("order_by", orderBy); - if (orderDir != null && orderDir.Length > 0) collection.Add("order_dir", orderDir); - if (limit > 0) collection.Add("limit", limit.ToString()); - if (offset > 0) collection.Add("offset", offset.ToString()); - - return collection; - } - - public PhonebookContactList Number(string number) - { - this.number = number; - return this; - } - - public PhonebookContactList Group(string group) - { - this.groups = new string[] { group }; - return this; - } - - public PhonebookContactList Groups(string[] groups) - { - this.groups = groups; - return this; - } - - public PhonebookContactList Text(string text) - { - this.searchText = text; - return this; - } - - public PhonebookContactList Gender(string gender) - { - this.gender = gender; - return this; - } - - public PhonebookContactList OrderBy(string orderBy) - { - this.orderBy = orderBy; - return this; - } - - public PhonebookContactList OrderDir(string orderDir) - { - this.orderDir = orderDir; - return this; - } - - public PhonebookContactList Limit(uint limit) - { - this.limit = limit; - return this; - } - - public PhonebookContactList Offset(uint offset) - { - this.offset = offset; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/GroupAdd.cs b/smsapi/Api/Action/Phonebook/GroupAdd.cs deleted file mode 100644 index b9135d4..0000000 --- a/smsapi/Api/Action/Phonebook/GroupAdd.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookGroupAdd : BaseSimple - { - public PhonebookGroupAdd() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string name; - protected string info; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("add_group", name); - if (info != null) collection.Add("info", info); - - return collection; - } - - public PhonebookGroupAdd SetName(string name) - { - this.name = name; - return this; - } - - public PhonebookGroupAdd SetInfo(string info) - { - this.info = info; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/GroupDelete.cs b/smsapi/Api/Action/Phonebook/GroupDelete.cs deleted file mode 100644 index 66e41c6..0000000 --- a/smsapi/Api/Action/Phonebook/GroupDelete.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookGroupDelete : BaseSimple - { - public PhonebookGroupDelete() : base() { - removeContacts = false; - } - - protected override string Uri() { return "phonebook.do"; } - - protected string name; - protected bool removeContacts; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("delete_group", name); - - if (removeContacts == true) - { - collection.Add("remove_contacts", "1"); - } - - return collection; - } - - public PhonebookGroupDelete Name(string name) - { - this.name = name; - return this; - } - - public PhonebookGroupDelete Contacts(bool flag) - { - this.removeContacts = flag; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/GroupEdit.cs b/smsapi/Api/Action/Phonebook/GroupEdit.cs deleted file mode 100644 index 095e8f2..0000000 --- a/smsapi/Api/Action/Phonebook/GroupEdit.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookGroupEdit : BaseSimple - { - public PhonebookGroupEdit() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string oldName; - protected string newName; - protected string info; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("edit_group", oldName); - collection.Add("name", newName); - collection.Add("info", info); - - return collection; - } - - public PhonebookGroupEdit Name(string name) - { - this.oldName = name; - return this; - } - - public PhonebookGroupEdit SetName(string name) - { - this.newName = name; - return this; - } - - public PhonebookGroupEdit SetInfo(string info) - { - this.info = info; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/GroupGet.cs b/smsapi/Api/Action/Phonebook/GroupGet.cs deleted file mode 100644 index 3557537..0000000 --- a/smsapi/Api/Action/Phonebook/GroupGet.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookGroupGet : BaseSimple - { - public PhonebookGroupGet() : base() { } - - protected override string Uri() { return "phonebook.do"; } - - protected string name; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("get_group", name); - - return collection; - } - - public PhonebookGroupGet Name(string name) - { - this.name = name; - return this; - } - } -} diff --git a/smsapi/Api/Action/Phonebook/GroupList.cs b/smsapi/Api/Action/Phonebook/GroupList.cs deleted file mode 100644 index 3841511..0000000 --- a/smsapi/Api/Action/Phonebook/GroupList.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class PhonebookGroupList : BaseSimple - { - public PhonebookGroupList() - : base() - { - } - - protected override string Uri() { return "phonebook.do"; } - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("list_groups", ""); - - return collection; - } - } -} diff --git a/smsapi/Api/Action/Ping/PingService.cs b/smsapi/Api/Action/Ping/PingService.cs new file mode 100644 index 0000000..11b691b --- /dev/null +++ b/smsapi/Api/Action/Ping/PingService.cs @@ -0,0 +1,12 @@ +using SMSApi.Api.Response.Ping; + +namespace SMSApi.Api.Action.Ping; + +public class PingService : Action +{ + protected override RequestMethod Method => RequestMethod.GET; + + protected override string Uri() => "ping"; + + protected override ApiType ApiType() => Action.ApiType.Rest; +} diff --git a/smsapi/Api/Action/Profile/Prices/GetPrices.cs b/smsapi/Api/Action/Profile/Prices/GetPrices.cs new file mode 100644 index 0000000..14c3daf --- /dev/null +++ b/smsapi/Api/Action/Profile/Prices/GetPrices.cs @@ -0,0 +1,13 @@ +using SMSApi.Api.Response; +using SMSApi.Api.Response.Profile.Prices; + +namespace SMSApi.Api.Action.Profile.Prices; + +public class GetPrices : Action> +{ + protected override RequestMethod Method => RequestMethod.GET; + + protected override string Uri() => "profile/prices"; + + protected override ApiType ApiType() => Action.ApiType.Rest; +} diff --git a/smsapi/Api/Action/Rest.cs b/smsapi/Api/Action/Rest.cs deleted file mode 100644 index c70206f..0000000 --- a/smsapi/Api/Action/Rest.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.Linq; -using System.Web; - -namespace SMSApi.Api.Action -{ - public abstract class Rest : BaseSimple - { - public Rest() - : base() - { - } - - protected override string Uri() - { - string uri = Resource; - if (RequestMethod.GET.Equals(Method)) - { - if (Parameters.Count > 0) uri += "?" + Parameters.ToString(); - } - return uri; - } - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - if (RequestMethod.POST.Equals(Method) || RequestMethod.PUT.Equals(Method)) - { - collection = Parameters; - } - return collection; - } - - protected abstract string Resource { get; } - - protected virtual NameValueCollection Parameters { get { return HttpUtility.ParseQueryString(string.Empty); } } - } -} diff --git a/smsapi/Api/Action/SMS/Delete.cs b/smsapi/Api/Action/SMS/Delete.cs index 6ff1321..32c97df 100644 --- a/smsapi/Api/Action/SMS/Delete.cs +++ b/smsapi/Api/Action/SMS/Delete.cs @@ -1,29 +1,31 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class SMSDelete : BaseSimple + public class SMSDelete : Action { - public SMSDelete() : base() { } + private string id; - protected override string Uri() { return "sms.do"; } + protected override RequestMethod Method => RequestMethod.POST; - protected string id; - - protected override NameValueCollection Values() + public SMSDelete Id(string id) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("sch_del", id); + this.id = id; + return this; + } - return collection; + protected override string Uri() + { + return "sms.do"; } - public SMSDelete Id(string id) + protected override NameValueCollection Values() { - this.id = id; - return this; + return new NameValueCollection + { + { "sch_del", id } + }; } } } diff --git a/smsapi/Api/Action/SMS/Get.cs b/smsapi/Api/Action/SMS/Get.cs index b99b885..1f44bce 100644 --- a/smsapi/Api/Action/SMS/Get.cs +++ b/smsapi/Api/Action/SMS/Get.cs @@ -1,35 +1,37 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class SMSGet : BaseSimple + public class SMSGet : Action { - public SMSGet() : base() { } + private string[] id; - protected override string Uri() { return "sms.do"; } - - protected string[] id; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("status", string.Join("|", id)); - - return collection; - } + protected override RequestMethod Method => RequestMethod.POST; public SMSGet Id(string id) { - this.id = new string[] { id }; + this.id = new[] { id }; return this; } public SMSGet Ids(string[] ids) { - this.id = ids; + id = ids; return this; } + + protected override string Uri() + { + return "sms.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "status", string.Join("|", id) } + }; + } } } diff --git a/smsapi/Api/Action/SMS/Send.cs b/smsapi/Api/Action/SMS/Send.cs index 2b309b4..84814c8 100644 --- a/smsapi/Api/Action/SMS/Send.cs +++ b/smsapi/Api/Action/SMS/Send.cs @@ -5,262 +5,280 @@ namespace SMSApi.Api.Action { public class SMSSend : Send { - public SMSSend() : base() { } + private const string Encoding = "UTF-8"; + + private string dataCoding; + private string dateExpire; + private bool fast; + private bool flash; + private int maxParts; + private bool normalize; + private bool noUnicode; + private string[] @params; + private string sender; + private bool single; + private string text; + private string? template; + + protected override RequestMethod Method => RequestMethod.POST; - protected override string Uri() { return "sms.do"; } - - protected override NameValueCollection Values() + public SMSSend SetCheckIDx(bool check = true) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - - if (Sender != null) - collection.Add("from", Sender); - - if (To != null) - collection.Add("to", string.Join(",", To)); - - if (Group != null) - collection.Add("group", Group); - - collection.Add("message", Text); - - collection.Add("single", (Single ? "1" : "0") ); - collection.Add("nounicode", (NoUnicode ? "1" : "0") ); - collection.Add("flash", (Flash ? "1" : "0") ); - collection.Add("fast", (Fast ? "1" : "0") ); - - if (DataCoding != null) - collection.Add("datacoding", DataCoding); - - if (MaxParts > 0) - collection.Add("max_parts", MaxParts.ToString()); - - if (DateSent != null) - collection.Add("date", DateSent); - - if (DateExpire != null) - collection.Add("expiration_date", DateExpire); - - if (Partner != null) - collection.Add("partner_id", Partner); - - collection.Add("encoding", Encoding); - - if (Normalize == true) - collection.Add("normalize", "1"); - - if (Test == true) - collection.Add("test", "1"); - - if (Idx != null && Idx.Length > 0) - { - collection.Add("check_idx", (IdxCheck ? "1" : "0")); - collection.Add("idx", string.Join("|", Idx)); - } - - if (Details == true) - { - collection.Add("details", "1"); - } - - if (this.Params != null) - { - for (int i = 0; i < this.Params.Length; i++) - { - if (this.Params[i] != null) - { - collection.Add("param" + ((i + 1).ToString()), this.Params[i]); - } - } - } - - return collection; + IdxCheck = check; + return this; } - protected override void Validate() + public SMSSend SetDataCoding(string dataCoding) { - if( To != null && Group != null ) - { - throw new ArgumentException("Cannot use 'to' and 'group' at the same time!"); - } + this.dataCoding = dataCoding; + return this; + } - if (Text == null) - { - throw new ArgumentException("Cannot send message without text!"); - } + public SMSSend SetDateExpire(string data) + { + dateExpire = data; + return this; } - private string Text; - private string DateExpire; - private string Sender; - private bool Single = false; - private bool NoUnicode = false; - private string DataCoding; - private string udh; - private bool Flash = false; - private string Encoding = "UTF-8"; - private bool Fast = false; - private bool Normalize = false; - private int MaxParts = 0; - private string[] Params = null; - private bool Details = true; + public SMSSend SetDateExpire(DateTime data) + { + dateExpire = data.ToString("yyyy-MM-ddTHH:mm:ssK"); + return this; + } - public SMSSend SetTo(string to) + public SMSSend SetDateSent(string data) { - this.To = new string[] { to }; + DateSent = data; return this; } - public SMSSend SetTo(string[] to) + public SMSSend SetDateSent(DateTime data) { - this.To = to; + DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); return this; } - public SMSSend SetGroup(string group) + /* + public SMSSend SetEncoding(string encoding) + { + this.encoding = encoding; + return this; + } + */ + + public SMSSend SetFast(bool fast = true) { - this.Group = group; + this.fast = fast; return this; } - public SMSSend SetDateSent(string data) + public SMSSend SetFlash(bool flash = true) { - this.DateSent = data; + this.flash = flash; return this; } - public SMSSend SetDateSent(DateTime data) + public SMSSend SetGroup(string group) { - this.DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); + Group = group; return this; } public SMSSend SetIDx(string idx) { - this.Idx = new string[] { idx }; + Idx = new[] { idx }; return this; } public SMSSend SetIDx(string[] idx) { - this.Idx = idx; + Idx = idx; return this; } - public SMSSend SetCheckIDx(bool check = true) + public SMSSend SetNormalize(bool flag = true) { - this.IdxCheck = check; + normalize = flag; return this; } - public SMSSend SetPartner(string partner) + public SMSSend SetNoUnicode(bool noUnicode = true) { - this.Partner = partner; + this.noUnicode = noUnicode; return this; } - public SMSSend SetText(string text) + public SMSSend SetParam(int i, string[] text) { - this.Text = text; - return this; + return SetParam(i, string.Join("|", text)); } - public SMSSend SetDateExpire(string data) + public SMSSend SetParam(int i, string text) { - this.DateExpire = data; + if (i > 3 || i < 0) + { + throw new IndexOutOfRangeException(); + } + + if (@params == null) + { + @params = new string[4]; + } + + @params[i] = text; + return this; } - public SMSSend SetDateExpire(DateTime data) + public SMSSend SetPartner(string partner) { - this.DateExpire = data.ToString("yyyy-MM-ddTHH:mm:ssK"); + Partner = partner; return this; } public SMSSend SetSender(string sender) { - this.Sender = sender; + this.sender = sender; return this; } public SMSSend SetSingle(bool single = true) { - this.Single = single; + this.single = single; return this; } - public SMSSend SetNoUnicode(bool noUnicode = true) + public SMSSend SetTest(bool test = true) { - this.NoUnicode = noUnicode; + Test = test; return this; } - public SMSSend SetDataCoding(string dataCoding) + public SMSSend SetText(string text) { - this.DataCoding = dataCoding; + this.text = text; return this; } - public SMSSend SetUdh(string udh) + public SMSSend SetTo(string to) { - this.udh = udh; + To = new[] { to }; return this; } - public SMSSend SetFlash(bool flash = true) + public SMSSend SetTo(string[] to) { - this.Flash = flash; + To = to; return this; } - -/* - public SMSSend SetEncoding(string encoding) + + public SMSSend SetTemplate(string templateName) { - this.encoding = encoding; + template = templateName; + return this; } -*/ - public SMSSend SetFast(bool fast = true) + protected override string Uri() { - this.Fast = fast; - return this; + return "sms.do"; } - public SMSSend SetTest(bool test = true) + protected override void Validate() { - this.Test = test; - return this; + if (text == null) + { + throw new ArgumentException("Cannot send message without text!"); + } } - public SMSSend SetParam(int i, string[] text) + protected override NameValueCollection Values() { - return this.SetParam(i, string.Join("|", text)); - } + var collection = new NameValueCollection(); - public SMSSend SetParam(int i, string text) - { - if (i > 3 || i < 0) + if (sender != null) { - throw new IndexOutOfRangeException(); + collection.Add("from", sender); } - if (this.Params == null) + if (To != null) { - this.Params = new string[4]; + collection.Add("to", string.Join(",", To)); } - this.Params[i] = text; + if (Group != null) + { + collection.Add("group", Group); + } - return this; - } + collection.Add("message", text); + + collection.Add("single", single ? "1" : "0"); + collection.Add("nounicode", noUnicode ? "1" : "0"); + collection.Add("flash", flash ? "1" : "0"); + collection.Add("fast", fast ? "1" : "0"); + collection.Add("details", "1"); + + if (dataCoding != null) + { + collection.Add("datacoding", dataCoding); + } - public SMSSend SetNormalize(bool flag = true) - { - this.Normalize = flag; - return this; - } + if (maxParts > 0) + { + collection.Add("max_parts", maxParts.ToString()); + } + + if (DateSent != null) + { + collection.Add("date", DateSent); + } + + if (dateExpire != null) + { + collection.Add("expiration_date", dateExpire); + } + + if (Partner != null) + { + collection.Add("partner_id", Partner); + } + + collection.Add("encoding", Encoding); + + if (normalize) + { + collection.Add("normalize", "1"); + } + + if (Test) + { + collection.Add("test", "1"); + } + + if (Idx != null && Idx.Length > 0) + { + collection.Add("check_idx", IdxCheck ? "1" : "0"); + collection.Add("idx", string.Join("|", Idx)); + } + + if (@params != null) + { + for (int i = 0; i < @params.Length; i++) + { + if (@params[i] != null) + { + collection.Add("param" + (i + 1), @params[i]); + } + } + } + + if (template != null) + { + collection.Add("template", template); + } + + return collection; + } } } diff --git a/smsapi/Api/Action/Send.cs b/smsapi/Api/Action/Send.cs index 012934b..aad0c1b 100644 --- a/smsapi/Api/Action/Send.cs +++ b/smsapi/Api/Action/Send.cs @@ -1,17 +1,16 @@ -using System.IO; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public abstract class Send : BaseSimple + public abstract class Send : Action { - protected Send() : base() {} - - protected string[] To; - protected string Group; protected string DateSent; + protected string Group; protected string[] Idx; protected bool IdxCheck = false; protected string Partner; protected bool Test = false; + + protected string[] To; } } diff --git a/smsapi/Api/Action/Sender/Add.cs b/smsapi/Api/Action/Sender/Add.cs index 25bcf5b..09c1b53 100644 --- a/smsapi/Api/Action/Sender/Add.cs +++ b/smsapi/Api/Action/Sender/Add.cs @@ -1,12 +1,14 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class SenderAdd : BaseSimple + public class SenderAdd : Action { private string name; - protected override string Uri() { return "sender.do"; } + protected override RequestMethod Method => RequestMethod.POST; public SenderAdd SetName(string name) { @@ -14,14 +16,17 @@ public SenderAdd SetName(string name) return this; } - protected override NameValueCollection Values() + protected override string Uri() { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("add", name); + return "sender.do"; + } - return collection; + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "add", name } + }; } } } diff --git a/smsapi/Api/Action/Sender/Delete.cs b/smsapi/Api/Action/Sender/Delete.cs index 5de5fa6..eb22e4c 100644 --- a/smsapi/Api/Action/Sender/Delete.cs +++ b/smsapi/Api/Action/Sender/Delete.cs @@ -1,27 +1,32 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class SenderDelete : BaseSimple + public class SenderDelete : Action { - protected override string Uri() { return "sender.do"; } - private string name; + protected override RequestMethod Method => RequestMethod.POST; + public SenderDelete Name(string name) { this.name = name; return this; } - protected override NameValueCollection Values() + protected override string Uri() { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("delete", this.name); + return "sender.do"; + } - return collection; + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "delete", name } + }; } } } diff --git a/smsapi/Api/Action/Sender/List.cs b/smsapi/Api/Action/Sender/List.cs index cf888bb..d3bdf15 100644 --- a/smsapi/Api/Action/Sender/List.cs +++ b/smsapi/Api/Action/Sender/List.cs @@ -1,20 +1,34 @@ using System.Collections.Generic; using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.Deserialization; +using smsapi.Api.Response.Deserialization.Exception; namespace SMSApi.Api.Action { - public class SenderList : BaseArray + public class SenderList : Action> { - protected override string Uri() { return "sender.do"; } + protected override RequestMethod Method => RequestMethod.POST; - protected override NameValueCollection Values() + protected override Array ResponseToObject(HttpResponseEntity data) { - NameValueCollection collection = new NameValueCollection(); + var result = BaseJsonDeserializer.Deserialize>(data); + result.ThrowErrors(); + + return new Array(result.Result); + } - collection.Add("format", "json"); - collection.Add("list", "1"); + protected override string Uri() + { + return "sender.do"; + } - return collection; + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "list", "1" } + }; } } } diff --git a/smsapi/Api/Action/Sender/SetDefault.cs b/smsapi/Api/Action/Sender/SetDefault.cs index d259d62..7fb9db5 100644 --- a/smsapi/Api/Action/Sender/SetDefault.cs +++ b/smsapi/Api/Action/Sender/SetDefault.cs @@ -1,27 +1,32 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Action { - public class SenderSetDefault : BaseSimple + public class SenderSetDefault : Action { - protected override string Uri() { return "sender.do"; } - private string name; + protected override RequestMethod Method => RequestMethod.POST; + public SenderSetDefault Name(string name) { this.name = name; return this; } - protected override NameValueCollection Values() + protected override string Uri() { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("default", this.name); + return "sender.do"; + } - return collection; + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "default", name } + }; } } } diff --git a/smsapi/Api/Action/User/Add.cs b/smsapi/Api/Action/User/Add.cs index c04191a..13d22cd 100644 --- a/smsapi/Api/Action/User/Add.cs +++ b/smsapi/Api/Action/User/Add.cs @@ -1,22 +1,25 @@ using System.Collections.Specialized; +using System.Globalization; +using SMSApi.Api.Response; -/** - * add_user * Nazwa dodawanego podużytkownika bez prefiksu użytkownika głównego - * pass * Hasło do panelu klienta SMSAPI dodawanego podużytkownika zakodowane w md5 - * pass_api Hasło do interfejsu API dla podużytkownika zakodowane w md5 - * limit Limit punktów przydzielony podużytkownikowi - * month_limit Ilość punktów która będzie przypisana do konta podużytkownika każdego pierwszego dnia - * senders Udostępnienie pól nadawców konta głównego (dostępne wartości: 1 – udostępniaj, 0 – nie udostępniaj, domyślnie wartość równa 0) - * phonebook Udostępnienie grup książki telefonicznej konta głównego (dostępne wartości: 1 – udostępniaj, 0 – nie udostępniaj, domyślnie wartość równa 0). Po udostępnieniu - * książki podużytkownik będzie mógł wysyłać do grup wiadomości nie będzie jednak widział poszczególnych kontaktów w książce telefonicznej. - * active Aktywowanie konta podużytkownika (dostępne wartości: 1 – aktywne, 0 – nieaktywne, domyślnie wartość równa 0) - * info Dodatkowy opis podużytkownika - */ namespace SMSApi.Api.Action { - public class UserAdd : BaseSimple + public class UserAdd : Action { - public UserAdd() : base() + private bool active; + private string info; + private double limit; + private double monthLimit; + private string newUsername; + private string password; + private string passwordApi; + private int phonebook; + private int senders; + private bool withoutPrefix; + + protected override RequestMethod Method => RequestMethod.POST; + + public UserAdd() { limit = -1; monthLimit = -1; @@ -25,102 +28,120 @@ public UserAdd() : base() senders = -1; } - protected override string Uri() { return "user.do"; } - - const int SENDERS_NOSHARE = 0; - const int SENDERS_SHARE = 1; - - const int PHONEBOOK_NOSHARE = 0; - const int PHONEBOOK_SHARE = 1; - - protected string newUsername; - protected string password; - protected string passwordApi; - protected double limit; - protected double monthLimit; - protected int senders; - protected int phonebook; - protected bool active; - protected string info; - protected bool withoutPrefix = false; - - protected override NameValueCollection Values() + public UserAdd SetActive(bool flag) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("add_user", newUsername); - if (password != null) collection.Add("pass", password); - if (passwordApi != null) collection.Add("pass_api", passwordApi); - if (limit >= 0) collection.Add("limit", limit.ToString()); - if (monthLimit >= 0) collection.Add("month_limit", monthLimit.ToString()); - if (senders >= 0) collection.Add("senders", senders.ToString()); - if (phonebook >= 0) collection.Add("phonebook", phonebook.ToString()); - collection.Add("active", (active == true ? "1" : "0") ); - if (info != null) collection.Add("info", info); - if (withoutPrefix) collection.Add("without_prefix", "1"); + active = flag; + return this; + } - return collection; + public UserAdd SetInfo(string text) + { + info = text; + return this; } - public UserAdd SetUsername(string username) + public UserAdd SetLimit(double limit) { - this.newUsername = username; + this.limit = limit; return this; } - public UserAdd SetPassword(string password) + public UserAdd SetMonthLimit(double limit) { - this.password = password; + monthLimit = limit; return this; } - public UserAdd SetPasswordApi(string password) + public UserAdd SetPassword(string password) { - this.passwordApi = password; + this.password = password; return this; } - public UserAdd SetLimit(double limit) + public UserAdd SetPasswordApi(string password) { - this.limit = limit; + passwordApi = password; return this; } - public UserAdd SetMonthLimit(double limit) + public UserAdd SetPhonebook(int flag) { - this.monthLimit = limit; + phonebook = flag; return this; } public UserAdd SetSenders(int flag) { - this.senders = flag; + senders = flag; return this; } - public UserAdd SetPhonebook(int flag) + public UserAdd SetUsername(string username) { - this.phonebook = flag; + newUsername = username; return this; } - public UserAdd SetActive(bool flag) + public UserAdd SetWithoutPrefix(bool flag) { - this.active = flag; + withoutPrefix = flag; return this; } - public UserAdd SetInfo(string text) + protected override string Uri() { - this.info = text; - return this; + return "user.do"; } - public UserAdd SetWithoutPrefix(bool flag) + protected override NameValueCollection Values() { - this.withoutPrefix = flag; - return this; + var collection = new NameValueCollection + { + { "add_user", newUsername } + }; + + if (password != null) + { + collection.Add("pass", password); + } + + if (passwordApi != null) + { + collection.Add("pass_api", passwordApi); + } + + if (limit >= 0) + { + collection.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + + if (monthLimit >= 0) + { + collection.Add("month_limit", monthLimit.ToString(CultureInfo.InvariantCulture)); + } + + if (senders >= 0) + { + collection.Add("senders", senders.ToString()); + } + + if (phonebook >= 0) + { + collection.Add("phonebook", phonebook.ToString()); + } + + collection.Add("active", active ? "1" : "0"); + if (info != null) + { + collection.Add("info", info); + } + + if (withoutPrefix) + { + collection.Add("without_prefix", "1"); + } + + return collection; } } } diff --git a/smsapi/Api/Action/User/Edit.cs b/smsapi/Api/Action/User/Edit.cs index 622767f..90cb2c5 100644 --- a/smsapi/Api/Action/User/Edit.cs +++ b/smsapi/Api/Action/User/Edit.cs @@ -1,23 +1,25 @@ using System.Collections.Specialized; +using System.Globalization; +using SMSApi.Api.Response; -/** - * add_user * Nazwa dodawanego podużytkownika bez prefiksu użytkownika głównego - * pass * Hasło do panelu klienta SMSAPI dodawanego podużytkownika zakodowane w md5 - * pass_api Hasło do interfejsu API dla podużytkownika zakodowane w md5 - * limit Limit punktów przydzielony podużytkownikowi - * month_limit Ilość punktów która będzie przypisana do konta podużytkownika każdego pierwszego dnia - * senders Udostępnienie pól nadawców konta głównego (dostępne wartości: 1 – udostępniaj, 0 – nie udostępniaj, domyślnie wartość równa 0) - * phonebook Udostępnienie grup książki telefonicznej konta głównego (dostępne wartości: 1 – udostępniaj, 0 – nie udostępniaj, domyślnie wartość równa 0). Po udostępnieniu - * książki podużytkownik będzie mógł wysyłać do grup wiadomości nie będzie jednak widział poszczególnych kontaktów w książce telefonicznej. - * active Aktywowanie konta podużytkownika (dostępne wartości: 1 – aktywne, 0 – nieaktywne, domyślnie wartość równa 0) - * info Dodatkowy opis podużytkownika - */ namespace SMSApi.Api.Action { - public class UserEdit : BaseSimple + public class UserEdit : Action { + private int active; + private string info; + private double limit; + private double monthLimit; + private string password; + private string passwordApi; + private int phonebook; + private int senders; + private string username; + private bool withoutPrefix; + + protected override RequestMethod Method => RequestMethod.POST; + public UserEdit() - : base() { limit = -1; monthLimit = -1; @@ -26,102 +28,124 @@ public UserEdit() senders = -1; } - protected override string Uri() { return "user.do"; } - - const int SENDERS_NOSHARE = 0; - const int SENDERS_SHARE = 1; - - const int PHONEBOOK_NOSHARE = 0; - const int PHONEBOOK_SHARE = 1; - - protected string username; - protected string password; - protected string passwordApi; - protected double limit; - protected double monthLimit; - protected int senders; - protected int phonebook; - protected int active; - protected string info; - protected bool withoutPrefix = false; - - protected override NameValueCollection Values() + public UserEdit SetActive(bool flag) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("set_user", username); - if (password != null) collection.Add("pass", password); - if (passwordApi != null) collection.Add("pass_api", passwordApi); - if (limit >= 0) collection.Add("limit", limit.ToString()); - if (monthLimit >= 0) collection.Add("month_limit", monthLimit.ToString()); - if (senders >= 0) collection.Add("senders", senders.ToString()); - if (phonebook >= 0) collection.Add("phonebook", phonebook.ToString()); - if (active >= 0) collection.Add("active", (active > 0 ? "1" : "0")); - if (info != null) collection.Add("info", info); - if (withoutPrefix) collection.Add("without_prefix", "1"); + active = flag ? 1 : 0; + return this; + } - return collection; + public UserEdit SetInfo(string text) + { + info = text; + return this; } - public UserEdit Username(string username) + public UserEdit SetLimit(double limit) { - this.username = username; + this.limit = limit; return this; } - public UserEdit SetPassword(string password) + public UserEdit SetMonthLimit(double limit) { - this.password = password; + monthLimit = limit; return this; } - public UserEdit SetPasswordApi(string password) + public UserEdit SetPassword(string password) { - this.passwordApi = password; + this.password = password; return this; } - public UserEdit SetLimit(double limit) + public UserEdit SetPasswordApi(string password) { - this.limit = limit; + passwordApi = password; return this; } - public UserEdit SetMonthLimit(double limit) + public UserEdit SetPhonebook(int flag) { - this.monthLimit = limit; + phonebook = flag; return this; } public UserEdit SetSenders(int flag) { - this.senders = flag; + senders = flag; return this; } - public UserEdit SetPhonebook(int flag) + public UserEdit SetWithoutPrefix(bool flag) { - this.phonebook = flag; + withoutPrefix = flag; return this; } - public UserEdit SetActive(bool flag) + public UserEdit Username(string username) { - this.active = (flag ? 1 : 0); + this.username = username; return this; } - public UserEdit SetInfo(string text) + protected override string Uri() { - this.info = text; - return this; + return "user.do"; } - public UserEdit SetWithoutPrefix(bool flag) + protected override NameValueCollection Values() { - this.withoutPrefix = flag; - return this; + var collection = new NameValueCollection + { + { "set_user", username } + }; + + if (password != null) + { + collection.Add("pass", password); + } + + if (passwordApi != null) + { + collection.Add("pass_api", passwordApi); + } + + if (limit >= 0) + { + collection.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + + if (monthLimit >= 0) + { + collection.Add("month_limit", monthLimit.ToString(CultureInfo.InvariantCulture)); + } + + if (senders >= 0) + { + collection.Add("senders", senders.ToString()); + } + + if (phonebook >= 0) + { + collection.Add("phonebook", phonebook.ToString()); + } + + if (active >= 0) + { + collection.Add("active", active > 0 ? "1" : "0"); + } + + if (info != null) + { + collection.Add("info", info); + } + + if (withoutPrefix) + { + collection.Add("without_prefix", "1"); + } + + return collection; } } } diff --git a/smsapi/Api/Action/User/Get.cs b/smsapi/Api/Action/User/Get.cs index 681ee56..8e9c747 100644 --- a/smsapi/Api/Action/User/Get.cs +++ b/smsapi/Api/Action/User/Get.cs @@ -1,29 +1,31 @@ using System.Collections.Specialized; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class UserGet : BaseSimple + public class UserGet : Action { - public UserGet() : base() { } + private string username; - protected override string Uri() { return "user.do"; } + protected override RequestMethod Method => RequestMethod.POST; - protected override NameValueCollection Values() + public UserGet Username(string username) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("get_user", username); - - return collection; + this.username = username; + return this; } - protected string username; + protected override string Uri() + { + return "user.do"; + } - public UserGet Username(string username) + protected override NameValueCollection Values() { - this.username = username; - return this; + return new NameValueCollection + { + { "get_user", username } + }; } } } diff --git a/smsapi/Api/Action/User/GetPoints.cs b/smsapi/Api/Action/User/GetPoints.cs index d74a870..7d652e6 100644 --- a/smsapi/Api/Action/User/GetPoints.cs +++ b/smsapi/Api/Action/User/GetPoints.cs @@ -1,22 +1,24 @@ -using System.Collections.Specialized; - -namespace SMSApi.Api.Action -{ - public class UserGetCredits : BaseSimple - { - public UserGetCredits() : base() { } - - protected override string Uri() { return "user.do"; } - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("credits", "1"); - collection.Add("details", "1"); - - return collection; - } - } -} +using System.Collections.Specialized; +using SMSApi.Api.Response; + +namespace SMSApi.Api.Action +{ + public class UserGetCredits : Action + { + protected override RequestMethod Method => RequestMethod.POST; + + protected override string Uri() + { + return "user.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "credits", "1" }, + { "details", "1" } + }; + } + } +} diff --git a/smsapi/Api/Action/User/List.cs b/smsapi/Api/Action/User/List.cs index 7dc6c74..7344b91 100644 --- a/smsapi/Api/Action/User/List.cs +++ b/smsapi/Api/Action/User/List.cs @@ -1,30 +1,34 @@ -using System.Collections.Specialized; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Collections.Specialized; +using SMSApi.Api.Response; +using SMSApi.Api.Response.Deserialization; +using smsapi.Api.Response.Deserialization.Exception; namespace SMSApi.Api.Action { - public class UserList : BaseArray + public class UserList : Action> { - public UserList() : base() { } + protected override RequestMethod Method => RequestMethod.POST; - protected override string Uri() { return "user.do"; } - - protected override NameValueCollection Values() + protected override Array ResponseToObject(HttpResponseEntity data) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("list", "1"); - - return collection; + var result = BaseJsonDeserializer.Deserialize>(data); + result.ThrowErrors(); + + return new Array(result.Result); } - protected string username; + protected override string Uri() + { + return "user.do"; + } - public UserList Username(string username) + protected override NameValueCollection Values() { - this.username = username; - return this; + return new NameValueCollection + { + { "list", "1" } + }; } } } diff --git a/smsapi/Api/Action/VMS/Delete.cs b/smsapi/Api/Action/VMS/Delete.cs index 3d69888..d29b2d0 100644 --- a/smsapi/Api/Action/VMS/Delete.cs +++ b/smsapi/Api/Action/VMS/Delete.cs @@ -1,30 +1,17 @@ using System.Collections.Specialized; -using System.IO; -using System.Runtime.Serialization.Json; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class VMSDelete : BaseSimple + public class VMSDelete : Action { - public VMSDelete() : base() { } + private string[] ids; - protected override string Uri() { return "vms.do"; } - - protected string[] ids; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("sch_del", string.Join("|", ids)); - - return collection; - } + protected override RequestMethod Method => RequestMethod.POST; public VMSDelete Id(string id) { - this.ids = new string[] { id }; + ids = new[] { id }; return this; } @@ -33,5 +20,18 @@ public VMSDelete Ids(string[] ids) this.ids = ids; return this; } + + protected override string Uri() + { + return "vms.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "sch_del", string.Join("|", ids) } + }; + } } } diff --git a/smsapi/Api/Action/VMS/Get.cs b/smsapi/Api/Action/VMS/Get.cs index 33273c8..3f12d77 100644 --- a/smsapi/Api/Action/VMS/Get.cs +++ b/smsapi/Api/Action/VMS/Get.cs @@ -1,38 +1,37 @@ using System.Collections.Specialized; -using System.IO; -using System.Runtime.Serialization.Json; +using SMSApi.Api.Response; namespace SMSApi.Api.Action { - public class VMSGet : BaseSimple + public class VMSGet : Action { - public VMSGet() : base() { } + private string[] ids; - protected override string Uri() { return "vms.do"; } - - protected string[] ids; - - protected override NameValueCollection Values() - { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - collection.Add("status", string.Join("|", ids)); - - return collection; - } + protected override RequestMethod Method => RequestMethod.POST; public VMSGet Id(string id) { - this.ids = new string[] { id }; + ids = new[] { id }; return this; } - public VMSGet Ids(string[] ids) { this.ids = ids; return this; } + + protected override string Uri() + { + return "vms.do"; + } + + protected override NameValueCollection Values() + { + return new NameValueCollection + { + { "status", string.Join("|", ids) } + }; + } } } diff --git a/smsapi/Api/Action/VMS/Send.cs b/smsapi/Api/Action/VMS/Send.cs index 340902b..befbe58 100644 --- a/smsapi/Api/Action/VMS/Send.cs +++ b/smsapi/Api/Action/VMS/Send.cs @@ -7,196 +7,214 @@ namespace SMSApi.Api.Action { public class VMSSend : Send { - public VMSSend() : base() { } - - protected override string Uri() { return "vms.do"; } - - protected override Dictionary Files() - { - Dictionary files = null; - - if (File != null && File.Length > 0) - { - files = new Dictionary(); - files.Add("file", File); - } + private Stream File; + private string From; + private int Interval; + private bool SkipGSM; + private int Try; + private string TTS; + private string TTSLector; - return files; - } + protected override RequestMethod Method => RequestMethod.POST; - protected override NameValueCollection Values() + public VMSSend SetCheckIDx(bool check = true) { - NameValueCollection collection = new NameValueCollection(); - - collection.Add("format", "json"); - - if (To != null) - collection.Add("to", string.Join(",", To)); - - if (From != null) - collection.Add("from", From); - - if (TTS != null) - collection.Add("tts", TTS); - - if (DateSent != null) - collection.Add("date", DateSent); - - if (Try > 0) - collection.Add("try", Try.ToString()); - - if (Interval > 0) - collection.Add("interval", Interval.ToString()); - - if (Partner != null) - collection.Add("partner_id", Partner); - - if (SkipGSM == true) - collection.Add("skip_gsm", "1"); - - if (TTSLector != null) - collection.Add("tts_lector", TTSLector); - - if (Test == true) - collection.Add("test", "1"); - - if (Idx != null && Idx.Length > 0) - { - collection.Add("check_idx", (IdxCheck ? "1" : "0")); - collection.Add("idx", string.Join("|", Idx)); - } - - return collection; + IdxCheck = check; + return this; } - protected override void Validate() + public VMSSend SetDateSent(string data) { - if( To != null && Group != null ) - { - throw new ArgumentException("Cannot use 'to' and 'group' at the same time!"); - } - - if ( (TTS == null || TTS.Length < 1) && (File == null || File.Length == 0) ) - { - throw new ArgumentException("Cannot send message without content!"); - } - - if (TTS != null && File != null) - { - throw new ArgumentException("Cannot send TTS and file at the same time"); - } + DateSent = data; + return this; } - private string From; - private Stream File; - private string TTS; - private string TTSLector; - private int Try = 0; - private int Interval = 0; - private bool SkipGSM = false; - - public VMSSend SetTo(string to) + public VMSSend SetDateSent(DateTime data) { - this.To = new string[] { to }; + DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); return this; } - public VMSSend SetTo(string[] to) + public VMSSend SetFile(Stream file) { - this.To = to; + File = file; return this; } public VMSSend SetFrom(string from) { - this.From = from; + From = from; return this; } public VMSSend SetGroup(string group) { - this.Group = group; + Group = group; return this; } - public VMSSend SetDateSent(string data) + public VMSSend SetIDx(string idx) { - this.DateSent = data; + Idx = new[] { idx }; return this; } - public VMSSend SetDateSent(DateTime data) + public VMSSend SetIDx(string[] idx) { - this.DateSent = data.ToString("yyyy-MM-ddTHH:mm:ssK"); + Idx = idx; return this; } - public VMSSend SetIDx(string idx) + public VMSSend SetPartner(string partner) { - this.Idx = new string[] { idx }; + Partner = partner; return this; } - public VMSSend SetIDx(string[] idx) + public VMSSend SetSkipGSM(bool flag) { - this.Idx = idx; + SkipGSM = flag; return this; } - public VMSSend SetCheckIDx(bool check = true) + public VMSSend SetTest(bool test = true) { - this.IdxCheck = check; + Test = test; return this; } - public VMSSend SetFile(Stream file) + public VMSSend SetTo(string to) { - this.File = file; + To = new[] { to }; return this; } - public VMSSend SetTTS(string tts) + public VMSSend SetTo(string[] to) { - this.TTS = tts; + To = to; return this; } - public VMSSend SetTTSLector(string lector) + public VMSSend SetTry(int retry) { - this.TTSLector = lector; + Try = retry; return this; } - public VMSSend SetPartner(string partner) + public VMSSend SetTryInterval(int sec) { - this.Partner = partner; + Interval = sec; return this; } - public VMSSend SetTest(bool test = true) + public VMSSend SetTTS(string tts) { - this.Test = test; + TTS = tts; return this; } - public VMSSend SetTry(int retry) + public VMSSend SetTTSLector(string lector) { - this.Try = retry; + TTSLector = lector; return this; } - public VMSSend SetTryInterval(int sec) + protected override Dictionary Files() { - this.Interval = sec; - return this; + Dictionary files = new Dictionary(); + + if (File != null && File.Length > 0) + { + files.Add("file", File); + } + + return files; } - public VMSSend SetSkipGSM(bool flag) + protected override string Uri() { - this.SkipGSM = flag; - return this; + return "vms.do"; + } + + protected override void Validate() + { + if (To != null && Group != null) + { + throw new ArgumentException("Cannot use 'to' and 'group' at the same time!"); + } + + if ((TTS == null || TTS.Length < 1) && (File == null || File.Length == 0)) + { + throw new ArgumentException("Cannot send message without content!"); + } + + if (TTS != null && File != null) + { + throw new ArgumentException("Cannot send TTS and file at the same time"); + } } - + protected override NameValueCollection Values() + { + var collection = new NameValueCollection(); + + if (To != null) + { + collection.Add("to", string.Join(",", To)); + } + + if (From != null) + { + collection.Add("from", From); + } + + if (TTS != null) + { + collection.Add("tts", TTS); + } + + if (DateSent != null) + { + collection.Add("date", DateSent); + } + + if (Try > 0) + { + collection.Add("try", Try.ToString()); + } + + if (Interval > 0) + { + collection.Add("interval", Interval.ToString()); + } + + if (Partner != null) + { + collection.Add("partner_id", Partner); + } + + if (SkipGSM) + { + collection.Add("skip_gsm", "1"); + } + + if (TTSLector != null) + { + collection.Add("tts_lector", TTSLector); + } + + if (Test) + { + collection.Add("test", "1"); + } + + if (Idx != null && Idx.Length > 0) + { + collection.Add("check_idx", IdxCheck ? "1" : "0"); + collection.Add("idx", string.Join("|", Idx)); + } + + return collection; + } } } diff --git a/smsapi/Api/ContactsFactory.cs b/smsapi/Api/ContactsFactory.cs index 78905d3..da1095c 100644 --- a/smsapi/Api/ContactsFactory.cs +++ b/smsapi/Api/ContactsFactory.cs @@ -1,214 +1,196 @@ -using System; - -namespace SMSApi.Api -{ - public class ContactsFactory : Factory - { - public ContactsFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } - - public ContactsFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } - - public ContactsFactory(IClient client, Proxy proxy) : base(client, proxy) - { - } - - public SMSApi.Api.Action.ListContacts ListContacts() - { - SMSApi.Api.Action.ListContacts action = new SMSApi.Api.Action.ListContacts(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.CreateContact CreateContact() - { - SMSApi.Api.Action.CreateContact action = new SMSApi.Api.Action.CreateContact(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.DeleteContact DeleteContact(string contactId) - { - SMSApi.Api.Action.DeleteContact action = new SMSApi.Api.Action.DeleteContact(contactId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.GetContact GetContact(string contactId) - { - SMSApi.Api.Action.GetContact action = new SMSApi.Api.Action.GetContact(contactId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.EditContact EditContact(string contactId) - { - SMSApi.Api.Action.EditContact action = new SMSApi.Api.Action.EditContact(contactId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.ListGroups ListGroups() - { - SMSApi.Api.Action.ListGroups action = new SMSApi.Api.Action.ListGroups(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.CreateGroup CreateGroup() - { - SMSApi.Api.Action.CreateGroup action = new SMSApi.Api.Action.CreateGroup(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.DeleteGroup DeleteGroup(string groupId) - { - SMSApi.Api.Action.DeleteGroup action = new SMSApi.Api.Action.DeleteGroup(groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.GetGroup GetGroup(string groupId) - { - SMSApi.Api.Action.GetGroup action = new SMSApi.Api.Action.GetGroup(groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.EditGroup EditGroup(string groupId) - { - SMSApi.Api.Action.EditGroup action = new SMSApi.Api.Action.EditGroup(groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.ListGroupPermissions ListGroupPermissions(string groupId) - { - SMSApi.Api.Action.ListGroupPermissions action = new SMSApi.Api.Action.ListGroupPermissions(groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.ListFields ListFields() - { - SMSApi.Api.Action.ListFields action = new SMSApi.Api.Action.ListFields(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.CreateField CreateField() - { - SMSApi.Api.Action.CreateField action = new SMSApi.Api.Action.CreateField(); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.DeleteField DeleteField(string fieldId) - { - SMSApi.Api.Action.DeleteField action = new SMSApi.Api.Action.DeleteField(fieldId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.EditField EditField(string fieldId) - { - SMSApi.Api.Action.EditField action = new SMSApi.Api.Action.EditField(fieldId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.ListFieldOptions ListFieldOptions(string fieldId) - { - SMSApi.Api.Action.ListFieldOptions action = new SMSApi.Api.Action.ListFieldOptions(fieldId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.BindContactToGroup BindContactToGroup(string contactId, string groupId) - { - SMSApi.Api.Action.BindContactToGroup action = new SMSApi.Api.Action.BindContactToGroup(contactId, groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.UnbindContactFromGroup UnbindContactFromGroup(string contactId, string groupId) - { - SMSApi.Api.Action.UnbindContactFromGroup action = new SMSApi.Api.Action.UnbindContactFromGroup(contactId, groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.ListContactGroups ListContactGroups(string contactId) - { - SMSApi.Api.Action.ListContactGroups action = new SMSApi.Api.Action.ListContactGroups(contactId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.GetContactGroup GetContactGroup(string contactId, string groupId) - { - SMSApi.Api.Action.GetContactGroup action = new SMSApi.Api.Action.GetContactGroup(contactId, groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.CreateGroupPermission CreateGroupPermission(string groupId) - { - SMSApi.Api.Action.CreateGroupPermission action = new SMSApi.Api.Action.CreateGroupPermission(groupId); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.DeleteGroupPermission DeleteGroupPermission(string groupId, string username) - { - SMSApi.Api.Action.DeleteGroupPermission action = new SMSApi.Api.Action.DeleteGroupPermission(groupId, username); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.GetGroupPermission GetGroupPermission(string groupId, string username) - { - SMSApi.Api.Action.GetGroupPermission action = new SMSApi.Api.Action.GetGroupPermission(groupId, username); - action.Client(client); - action.Proxy(proxy); - return action; - } - - public SMSApi.Api.Action.EditGroupPermission EditGroupPermission(string groupId, string username) - { - SMSApi.Api.Action.EditGroupPermission action = new SMSApi.Api.Action.EditGroupPermission(groupId, username); - action.Client(client); - action.Proxy(proxy); - return action; - } - } -} - +using SMSApi.Api; +using SMSApi.Api.Action; + +namespace SMSApi.Api +{ + public class ContactsFactory : Factory + { + public ContactsFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } + + public ContactsFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } + + public ContactsFactory(IClient client, Proxy proxy) + : base(client, proxy) + { } + + public BindContactToGroup BindContactToGroup(string contactId, string groupId) + { + var action = new BindContactToGroup(contactId, groupId); + action.Proxy(proxy); + return action; + } + + public CreateContact CreateContact() + { + var action = new CreateContact(); + action.Proxy(proxy); + return action; + } + + public CreateField CreateField() + { + var action = new CreateField(); + action.Proxy(proxy); + return action; + } + + public CreateGroup CreateGroup() + { + var action = new CreateGroup(); + action.Proxy(proxy); + return action; + } + + public CreateGroupPermission CreateGroupPermission(string groupId) + { + var action = new CreateGroupPermission(groupId); + action.Proxy(proxy); + return action; + } + + public DeleteContact DeleteContact(string contactId) + { + var action = new DeleteContact(contactId); + action.Proxy(proxy); + return action; + } + + public DeleteField DeleteField(string fieldId) + { + var action = new DeleteField(fieldId); + action.Proxy(proxy); + return action; + } + + public DeleteGroup DeleteGroup(string groupId) + { + var action = new DeleteGroup(groupId); + action.Proxy(proxy); + return action; + } + + public DeleteGroupPermission DeleteGroupPermission(string groupId, string username) + { + var action = new DeleteGroupPermission(groupId, username); + action.Proxy(proxy); + return action; + } + + public EditContact EditContact(string contactId) + { + var action = new EditContact(contactId); + action.Proxy(proxy); + return action; + } + + public EditField EditField(string fieldId) + { + var action = new EditField(fieldId); + action.Proxy(proxy); + return action; + } + + public EditGroup EditGroup(string groupId) + { + var action = new EditGroup(groupId); + action.Proxy(proxy); + return action; + } + + public EditGroupPermission EditGroupPermission(string groupId, string username) + { + var action = new EditGroupPermission(groupId, username); + action.Proxy(proxy); + return action; + } + + public GetContact GetContact(string contactId) + { + var action = new GetContact(contactId); + action.Proxy(proxy); + return action; + } + + public GetContactGroup GetContactGroup(string contactId, string groupId) + { + var action = new GetContactGroup(contactId, groupId); + action.Proxy(proxy); + return action; + } + + public GetGroup GetGroup(string groupId) + { + var action = new GetGroup(groupId); + action.Proxy(proxy); + return action; + } + + public GetGroupPermission GetGroupPermission(string groupId, string username) + { + var action = new GetGroupPermission(groupId, username); + action.Proxy(proxy); + return action; + } + + public ListContactGroups ListContactGroups(string contactId) + { + var action = new ListContactGroups(contactId); + action.Proxy(proxy); + return action; + } + + public ListContacts ListContacts() + { + var action = new ListContacts(); + action.Proxy(proxy); + return action; + } + + public ListFieldOptions ListFieldOptions(string fieldId) + { + var action = new ListFieldOptions(fieldId); + action.Proxy(proxy); + return action; + } + + public ListFields ListFields() + { + var action = new ListFields(); + action.Proxy(proxy); + return action; + } + + public ListGroupPermissions ListGroupPermissions(string groupId) + { + var action = new ListGroupPermissions(groupId); + action.Proxy(proxy); + return action; + } + + public ListGroups ListGroups() + { + var action = new ListGroups(); + action.Proxy(proxy); + return action; + } + + public UnbindContactFromGroup UnbindContactFromGroup(string contactId, string groupId) + { + var action = new UnbindContactFromGroup(contactId, groupId); + action.Proxy(proxy); + return action; + } + } +} + +public static class ContactsFeatureRegister +{ + public static ContactsFactory Contacts(this Features features) + { + return new ContactsFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/Factory.cs b/smsapi/Api/Factory.cs index f8703c6..865af4a 100644 --- a/smsapi/Api/Factory.cs +++ b/smsapi/Api/Factory.cs @@ -1,60 +1,43 @@ - -using System.Collections.Generic; +namespace SMSApi.Api +{ + public abstract class Factory + { + protected Proxy proxy; -namespace SMSApi.Api -{ - public abstract class Factory - { - private static Dictionary _addresses = - new Dictionary - { - { ProxyAddress.SmsApiPl, "https://api.smsapi.pl/" }, - { ProxyAddress.BackupSmsApiPl, "https://api2.smsapi.pl/" }, - { ProxyAddress.SmsApiCom, "https://api.smsapi.com/" }, - { ProxyAddress.BackupSmsApiCom, "https://api2.smsapi.com/" } - }; - - protected IClient client; - protected Proxy proxy; - - public Factory(ProxyAddress address = ProxyAddress.SmsApiPl) - { - Proxy(address); - } - - public Factory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : this(address) - { - Client(client); + private IClient client; + + protected Factory(ProxyAddress address = ProxyAddress.SmsApiIo) + { + Proxy(address); } - public Factory(IClient client, Proxy proxy) + protected Factory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : this(address) + { + Client(client); + } + + protected Factory(IClient client, Proxy proxy) { Client(client); Proxy(proxy); } - public void Client(IClient client) - { - this.client = client; - if (proxy != null) - { - proxy.Authentication(client); - } - } - - public void Proxy(Proxy proxy) - { - this.proxy = proxy; - if (proxy != null) - { - proxy.Authentication(client); - } - } - - public void Proxy(ProxyAddress address) + private void Client(IClient client) { - Proxy(new ProxyHTTP(_addresses[address])); - } - } -} + this.client = client; + proxy?.Authentication(client); + } + + private void Proxy(Proxy proxy) + { + this.proxy = proxy; + proxy?.Authentication(client); + } + + private void Proxy(ProxyAddress address) + { + Proxy(new ProxyHTTP(address.GetUrl())); + } + } +} diff --git a/smsapi/Api/Features.cs b/smsapi/Api/Features.cs new file mode 100644 index 0000000..502093d --- /dev/null +++ b/smsapi/Api/Features.cs @@ -0,0 +1,19 @@ +namespace SMSApi.Api; + +public class Features +{ + internal readonly IClient Client; + internal readonly Proxy Proxy; + + public Features(IClient client, ProxyAddress proxy = ProxyAddress.SmsApiIo) + { + Proxy = new ProxyHTTP(proxy.GetUrl()); + Client = client; + } + + public Features(IClient client, Proxy proxy) + { + Proxy = proxy; + Client = client; + } +} diff --git a/smsapi/Api/HLRFactory.cs b/smsapi/Api/HLRFactory.cs index 75a3493..f25fd3d 100644 --- a/smsapi/Api/HLRFactory.cs +++ b/smsapi/Api/HLRFactory.cs @@ -1,37 +1,36 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace SMSApi.Api -{ - public class HLRFactory : Factory - { - public HLRFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } - - public HLRFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } +using SMSApi.Api; +using SMSApi.Api.Action; + +namespace SMSApi.Api +{ + public class HLRFactory : Factory + { + public HLRFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } - public HLRFactory(IClient client, Proxy proxy) + public HLRFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } + + public HLRFactory(IClient client, Proxy proxy) : base(client, proxy) + { } + + public HLRCheckNumber ActionCheckNumber(string number = null) { + var action = new HLRCheckNumber(); + action.Proxy(proxy); + action.SetNumber(number); + return action; } + } +} - public SMSApi.Api.Action.HLRCheckNumber ActionCheckNumber(string number = null) - { - var action = new SMSApi.Api.Action.HLRCheckNumber(); - - action.Client(client); - action.Proxy(proxy); - - action.SetNumber(number); - - return action; - } - } -} +public static class HlrFeatureRegister +{ + public static HLRFactory HLR(this Features features) + { + return new HLRFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/MFAFactory.cs b/smsapi/Api/MFAFactory.cs new file mode 100644 index 0000000..6ed7439 --- /dev/null +++ b/smsapi/Api/MFAFactory.cs @@ -0,0 +1,45 @@ +using SMSApi.Api.Action.MFA; + +namespace SMSApi.Api; + +public class MFAFactory : Factory +{ + public MFAFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { + } + + public MFAFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { + } + + public MFAFactory(IClient client, Proxy proxy) + : base(client, proxy) + { + } + + public CreateMFACode CreateMfaCode(string phoneNumber) + { + var action = new CreateMFACode(phoneNumber); + action.Proxy(proxy); + + return action; + } + + public VerifyMFACode VerifyMfaCode(string phoneNumber, string code) + { + var action = new VerifyMFACode(phoneNumber, code); + action.Proxy(proxy); + + return action; + } +} + +public static class MFAFeatureRegister +{ + public static MFAFactory MFA(this Features features) + { + return new MFAFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/MMSFactory.cs b/smsapi/Api/MMSFactory.cs index 6d274f3..e64b858 100644 --- a/smsapi/Api/MMSFactory.cs +++ b/smsapi/Api/MMSFactory.cs @@ -1,70 +1,66 @@ - +using SMSApi.Api; +using SMSApi.Api.Action; + namespace SMSApi.Api { public class MMSFactory : Factory { - public MMSFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } + public MMSFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } - public MMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } + public MMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } - public MMSFactory(IClient client, Proxy proxy) - : base(client, proxy) - { - } + public MMSFactory(IClient client, Proxy proxy) + : base(client, proxy) + { } - public SMSApi.Api.Action.MMSDelete ActionDelete(string id = null) + public MMSDelete ActionDelete(string id = null) { - SMSApi.Api.Action.MMSDelete action = new SMSApi.Api.Action.MMSDelete(); - - action.Client(client); + var action = new MMSDelete(); action.Proxy(proxy); action.Id(id); - return action; } - public SMSApi.Api.Action.MMSGet ActionGet(string id = null) + public MMSGet ActionGet(string id = null) { - SMSApi.Api.Action.MMSGet action = new SMSApi.Api.Action.MMSGet(); - - action.Client(client); + var action = new MMSGet(); action.Proxy(proxy); action.Id(id); - return action; } - public SMSApi.Api.Action.MMSGet ActionGet(string[] id) + public MMSGet ActionGet(string[] id) { - SMSApi.Api.Action.MMSGet action = new SMSApi.Api.Action.MMSGet(); - - action.Client(client); + var action = new MMSGet(); action.Proxy(proxy); action.Ids(id); - return action; } - public SMSApi.Api.Action.MMSSend ActionSend(string to = null) + public MMSSend ActionSend(string to = null) { - string[] tos = ( to == null ? null : new string[] { to } ); + string[] tos = to == null ? null : new[] { to }; return ActionSend(tos); } - public SMSApi.Api.Action.MMSSend ActionSend(string[] to) + public MMSSend ActionSend(string[] to) { - SMSApi.Api.Action.MMSSend action = new SMSApi.Api.Action.MMSSend(); - action.Client(client); + var action = new MMSSend(); action.Proxy(proxy); action.SetTo(to); - return action; } } } + +public static class MMSFeatureRegister +{ + public static MMSFactory MMS(this Features features) + { + return new MMSFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/PhonebookFactory.cs b/smsapi/Api/PhonebookFactory.cs deleted file mode 100644 index 4f95eb2..0000000 --- a/smsapi/Api/PhonebookFactory.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace SMSApi.Api -{ - [Obsolete("use ContactsFactory instead")] - public class PhonebookFactory : Factory - { - public PhonebookFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } - - public PhonebookFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } - - public PhonebookFactory(IClient client, Proxy proxy) - : base(client, proxy) - { - } - - public SMSApi.Api.Action.PhonebookContactAdd ActionContactAdd(string number = null) - { - var action = new SMSApi.Api.Action.PhonebookContactAdd(); - - action.Client(client); - action.Proxy(proxy); - - action.SetNumber(number); - - return action; - } - - public SMSApi.Api.Action.PhonebookContactGet ActionContactGet(string number = null) - { - var action = new SMSApi.Api.Action.PhonebookContactGet(); - - action.Client(client); - action.Proxy(proxy); - - action.Number(number); - - return action; - } - - public SMSApi.Api.Action.PhonebookContactEdit ActionContactEdit(string number = null) - { - var action = new SMSApi.Api.Action.PhonebookContactEdit(); - - action.Client(client); - action.Proxy(proxy); - - action.Number(number); - - return action; - } - - public SMSApi.Api.Action.PhonebookContactDelete ActionContactDelete(string number = null) - { - var action = new SMSApi.Api.Action.PhonebookContactDelete(); - - action.Client(client); - action.Proxy(proxy); - - action.Number(number); - - return action; - } - - public SMSApi.Api.Action.PhonebookContactList ActionContactList() - { - var action = new SMSApi.Api.Action.PhonebookContactList(); - - action.Client(client); - action.Proxy(proxy); - - return action; - } - - public SMSApi.Api.Action.PhonebookGroupAdd ActionGroupAdd(string name = null) - { - var action = new SMSApi.Api.Action.PhonebookGroupAdd(); - - action.Client(client); - action.Proxy(proxy); - - action.SetName(name); - - return action; - } - - public SMSApi.Api.Action.PhonebookGroupEdit ActionGroupEdit(string name = null) - { - var action = new SMSApi.Api.Action.PhonebookGroupEdit(); - - action.Client(client); - action.Proxy(proxy); - - action.Name(name); - - return action; - } - - public SMSApi.Api.Action.PhonebookGroupGet ActionGroupGet(string name = null) - { - var action = new SMSApi.Api.Action.PhonebookGroupGet(); - - action.Client(client); - action.Proxy(proxy); - - action.Name(name); - - return action; - } - - public SMSApi.Api.Action.PhonebookGroupDelete ActionGroupDelete(string name = null) - { - var action = new SMSApi.Api.Action.PhonebookGroupDelete(); - - action.Client(client); - action.Proxy(proxy); - - action.Name(name); - - return action; - } - - public SMSApi.Api.Action.PhonebookGroupList ActionGroupList() - { - var action = new SMSApi.Api.Action.PhonebookGroupList(); - - action.Client(client); - action.Proxy(proxy); - - return action; - } - } -} diff --git a/smsapi/Api/PingFactory.cs b/smsapi/Api/PingFactory.cs new file mode 100644 index 0000000..103d575 --- /dev/null +++ b/smsapi/Api/PingFactory.cs @@ -0,0 +1,30 @@ +using SMSApi.Api.Action.Ping; + +namespace SMSApi.Api; + +public class PingFactory : Factory +{ + public PingFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) : base(client, address) + { + } + + public PingFactory(IClient client, Proxy proxy) : base(client, proxy) + { + } + + public PingService PingService() + { + var service = new PingService(); + service.Proxy(proxy); + + return service; + } +} + +public static class PingFeatureRegister +{ + public static PingFactory Ping(this Features features) + { + return new PingFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/PricesFactory.cs b/smsapi/Api/PricesFactory.cs new file mode 100644 index 0000000..27f710e --- /dev/null +++ b/smsapi/Api/PricesFactory.cs @@ -0,0 +1,37 @@ +using SMSApi.Api.Action.Profile.Prices; + +namespace SMSApi.Api; + +public class PricesFactory : Factory +{ + public PricesFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { + } + + public PricesFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { + } + + public PricesFactory(IClient client, Proxy proxy) + : base(client, proxy) + { + } + + public GetPrices GetPrices() + { + var action = new GetPrices(); + action.Proxy(proxy); + + return action; + } +} + +public static class PricesFeatureRegister +{ + public static PricesFactory Prices(this Features features) + { + return new PricesFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/Response/Array.cs b/smsapi/Api/Response/Array.cs index 371cf6c..4d3385f 100644 --- a/smsapi/Api/Response/Array.cs +++ b/smsapi/Api/Response/Array.cs @@ -1,19 +1,21 @@ -using System.Runtime.Serialization; +using System.Collections.Generic; +using System.Runtime.Serialization; namespace SMSApi.Api.Response { [DataContract] public class Array : Countable { - protected Array() : base() { } + [DataMember(Name = "list", IsRequired = true)] + public readonly List List; - public Array(System.Collections.Generic.List list) + public Array(List list) : base(list.Count) { - this.List = list; + List = list; } - [DataMember(Name = "list", IsRequired = true)] - public readonly System.Collections.Generic.List List; + protected Array() + { } } } diff --git a/smsapi/Api/Response/BasicCollection.cs b/smsapi/Api/Response/BasicCollection.cs index 5a96f29..b4da875 100644 --- a/smsapi/Api/Response/BasicCollection.cs +++ b/smsapi/Api/Response/BasicCollection.cs @@ -1,38 +1,60 @@ using System; +using System.Collections.Generic; using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Response { - [DataContract] - public class BasicCollection : Countable - { - protected BasicCollection() : base() { } - - [DataMember(Name = "size", IsRequired = false)] - protected int size; - - public int Size { get { if (size == 0) return base.Count; return size; } } - - [DataMember(Name = "collection", IsRequired = false)] - protected System.Collections.Generic.List collection; - - [Obsolete("use Size instead")] - public override int Count { get { return Size; } } - - public System.Collections.Generic.List Collection - { - get - { - if (collection == null) - collection = new System.Collections.Generic.List(); - return collection; - } - - set { } - } - - [Obsolete("use Collection instead")] - [DataMember(Name = "list", IsRequired = false)] - public System.Collections.Generic.List List { get { return Collection; } protected set { collection = value; } } - } + [DataContract] + public class BasicCollection : Countable, IResponseCodeAwareResolver + { + [DataMember(Name = "collection", IsRequired = false)] + protected List collection; + + [DataMember(Name = "size", IsRequired = false)] + protected int size; + + protected BasicCollection() + { } + + public List Collection + { + get + { + if (collection == null) + { + collection = new List(); + } + + return collection; + } + + set + { } + } + + [Obsolete("use Size instead")] + public override int Count => Size; + + [Obsolete("use Collection instead")] + [DataMember(Name = "list", IsRequired = false)] + public List List + { + get => Collection; + protected set => collection = value; + } + + public int Size + { + get + { + if (size == 0) + { + return base.Count; + } + + return size; + } + } + } } diff --git a/smsapi/Api/Response/CheckNumber.cs b/smsapi/Api/Response/CheckNumber.cs index 23223da..c9765cd 100644 --- a/smsapi/Api/Response/CheckNumber.cs +++ b/smsapi/Api/Response/CheckNumber.cs @@ -6,22 +6,26 @@ namespace SMSApi.Api.Response [DataContract] public class CheckNumber : Countable { - protected CheckNumber() : base() { } - [DataMember(Name = "list", IsRequired = true)] private List list; + protected CheckNumber() + { } + public List List { get { if (list == null) + { list = new List(); + } return list; } - set { } + set + { } } } } diff --git a/smsapi/Api/Response/Contact.cs b/smsapi/Api/Response/Contact.cs index 212aa06..4c36644 100644 --- a/smsapi/Api/Response/Contact.cs +++ b/smsapi/Api/Response/Contact.cs @@ -1,86 +1,135 @@ using System; using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Response { - [DataContract] - public class Contact : Base - { - public const string MaleGender = "male"; - public const string FemaleGender = "female"; - public const string UndefinedGender = "undefined"; - - public Contact() : base() { } - - [DataMember(Name = "id", IsRequired = false)] - public readonly string Id; - - [DataMember(Name = "idx", IsRequired = false)] - public readonly string Idx; - - [DataMember(Name = "first_name", IsRequired = false)] - public readonly string FirstName; - - [DataMember(Name = "last_name", IsRequired = false)] - public readonly string LastName; - - private DateTime? birthdayDate; - - [DataMember(Name = "birthday_date", IsRequired = false)] - private string BirthdayDateSerializationHelper { set { if (value != null) birthdayDate = DateTime.Parse(value); } get { return ""; } } - - public DateTime? BirthdayDate { get { return birthdayDate; } } - - [DataMember(Name = "phone_number", IsRequired = false)] - public readonly string PhoneNumber; - - [DataMember(Name = "email", IsRequired = false)] - public readonly string Email; - - [DataMember(Name = "gender", IsRequired = false)] - public readonly string Gender; - - [DataMember(Name = "city", IsRequired = false)] - public readonly string City; - - [DataMember(Name = "source", IsRequired = false)] - public readonly string Source; - - private DateTime? dateCreated; - [DataMember(Name = "date_created", IsRequired = false)] - private string DateCreatedSerializationHelper { set { dateCreated = DateTime.Parse(value); } get { return ""; } } - public DateTime? DateCreated { get { return dateCreated; } } - - private DateTime? dateUpdated; - [DataMember(Name = "date_updated", IsRequired = false)] - private string DateUpdatedSerializationHelper { set { dateUpdated = DateTime.Parse(value); } get { return ""; } } - public DateTime? DateUpdated { get { return dateUpdated; } } - - [DataMember(Name = "description", IsRequired = false)] - public readonly string Description; - - [Obsolete("use Id instead")] - [DataMember(Name = "number", IsRequired = false)] - public readonly string Number; - - [Obsolete("use Description instead")] - [DataMember(Name = "info", IsRequired = false)] - public readonly string info; - - [Obsolete("use BirthdayDate instead")] - [DataMember(Name = "birthday", IsRequired = false)] - public readonly string Birthday; - - [DataMember(Name = "date_add", IsRequired = false)] - private uint DateAddSerializationHelper { set { DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); dateCreated = origin.AddSeconds(value); } get { return 0; } } - - [Obsolete("use DateCreated instead")] - public uint DateAdd { get { DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return dateCreated != null ? (uint)(dateCreated.Value.ToUniversalTime() - origin).TotalSeconds : 0; } } - - [DataMember(Name = "date_mod", IsRequired = false)] - private uint DateModSerializationHelper { set { DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); dateUpdated = origin.AddSeconds(value); } get { return 0; } } - - [Obsolete("use DateUpdated instead")] - public uint DateMod { get { DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return dateUpdated != null? (uint)(dateUpdated.Value.ToUniversalTime() - origin).TotalSeconds : 0; } } - } + [DataContract] + public class Contact : ErrorAwareResponse + { + public const string FemaleGender = "female"; + public const string MaleGender = "male"; + public const string UndefinedGender = "undefined"; + + [Obsolete("use BirthdayDate instead")] + [DataMember(Name = "birthday", IsRequired = false)] + public readonly string Birthday; + + [DataMember(Name = "city", IsRequired = false)] + public readonly string City; + + [DataMember(Name = "description", IsRequired = false)] + public readonly string Description; + + [DataMember(Name = "email", IsRequired = false)] + public readonly string Email; + + [DataMember(Name = "first_name", IsRequired = false)] + public readonly string FirstName; + + [DataMember(Name = "gender", IsRequired = false)] + public readonly string Gender; + + [DataMember(Name = "id", IsRequired = false)] + public readonly string Id; + + [DataMember(Name = "idx", IsRequired = false)] + public readonly string Idx; + + [Obsolete("use Description instead")] + [DataMember(Name = "info", IsRequired = false)] + public readonly string info; + + [DataMember(Name = "last_name", IsRequired = false)] + public readonly string LastName; + + [Obsolete("use Id instead")] + [DataMember(Name = "number", IsRequired = false)] + public readonly string Number; + + [DataMember(Name = "phone_number", IsRequired = false)] + public readonly string PhoneNumber; + + [DataMember(Name = "source", IsRequired = false)] + public readonly string Source; + + private DateTime? dateCreated; + + private DateTime? dateUpdated; + + public DateTime? BirthdayDate { get; private set; } + + [Obsolete("use DateCreated instead")] + public uint DateAdd + { + get + { + var origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + return dateCreated != null ? (uint)(dateCreated.Value.ToUniversalTime() - origin).TotalSeconds : 0; + } + } + + public DateTime? DateCreated => dateCreated; + + [Obsolete("use DateUpdated instead")] + public uint DateMod + { + get + { + var origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + return dateUpdated != null ? (uint)(dateUpdated.Value.ToUniversalTime() - origin).TotalSeconds : 0; + } + } + + public DateTime? DateUpdated => dateUpdated; + + [DataMember(Name = "birthday_date", IsRequired = false)] + private string BirthdayDateSerializationHelper + { + set + { + if (value != null) + { + BirthdayDate = DateTime.Parse(value); + } + } + get => ""; + } + + [DataMember(Name = "date_add", IsRequired = false)] + private uint DateAddSerializationHelper + { + set + { + var origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + dateCreated = origin.AddSeconds(value); + } + get => 0; + } + + [DataMember(Name = "date_created", IsRequired = false)] + private string DateCreatedSerializationHelper + { + set => dateCreated = DateTime.Parse(value); + get => ""; + } + + [DataMember(Name = "date_mod", IsRequired = false)] + private uint DateModSerializationHelper + { + set + { + var origin = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + dateUpdated = origin.AddSeconds(value); + } + get => 0; + } + + [DataMember(Name = "date_updated", IsRequired = false)] + private string DateUpdatedSerializationHelper + { + set => dateUpdated = DateTime.Parse(value); + get => ""; + } + } } diff --git a/smsapi/Api/Response/Contacts.cs b/smsapi/Api/Response/Contacts.cs index 708d2f3..9816c3a 100644 --- a/smsapi/Api/Response/Contacts.cs +++ b/smsapi/Api/Response/Contacts.cs @@ -3,11 +3,11 @@ namespace SMSApi.Api.Response { - [DataContract] - public class Contacts : BasicCollection - { - [Obsolete("")] - [DataMember(Name = "total", IsRequired = false)] - public readonly int Total; - } + [DataContract] + public class Contacts : BasicCollection + { + [Obsolete("")] + [DataMember(Name = "total", IsRequired = false)] + public readonly int Total; + } } diff --git a/smsapi/Api/Response/Countable.cs b/smsapi/Api/Response/Countable.cs index 2c19b80..d352b29 100644 --- a/smsapi/Api/Response/Countable.cs +++ b/smsapi/Api/Response/Countable.cs @@ -2,17 +2,21 @@ namespace SMSApi.Api.Response { - [DataContract] - public class Countable /*: Base*/ - { - protected Countable(int count = 0) : base() - { - this.count = count; - } + [DataContract] + public class Countable + { + private int count; - private int count; + protected Countable(int count = 0) + { + this.count = count; + } - [DataMember(Name = "count", IsRequired = false)] - public virtual int Count { get { return count; } private set { count = value; } } - } + [DataMember(Name = "count", IsRequired = false)] + public virtual int Count + { + get => count; + private set => count = value; + } + } } diff --git a/smsapi/Api/Response/Deserialization/AccessErrorResolver.cs b/smsapi/Api/Response/Deserialization/AccessErrorResolver.cs new file mode 100644 index 0000000..35abb75 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/AccessErrorResolver.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.IO; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; + +namespace SMSApi.Api.Response.Deserialization; + +public class AccessErrorResolver : IResponseCodeAwareResolver +{ + public Dictionary> HandleExceptionActions() + { + return new Dictionary> + { + { 401, _ => throw new UnauthorizedException() }, + { 403, _ => throw new AccessForbiddenException() } + }; + } +} diff --git a/smsapi/Api/Response/Deserialization/BaseJsonDeserializer.cs b/smsapi/Api/Response/Deserialization/BaseJsonDeserializer.cs new file mode 100644 index 0000000..aa75717 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/BaseJsonDeserializer.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization.Json; + +namespace SMSApi.Api.Response.Deserialization +{ + public class BaseJsonDeserializer : IDeserializer + { + public DeserializationResult Deserialize(HttpResponseEntity responseEntity) + { + T result; + var data = responseEntity.Content.Result; + + if (data.Length > 0) + { + data.Position = 0; + var serializer = new DataContractJsonSerializer(typeof(T)); + result = (T)serializer.ReadObject(data); + data.Position = 0; + } + else + { + result = Activator.CreateInstance(); + } + + return new DeserializationResult + { + Result = result + }; + } + } +} diff --git a/smsapi/Api/Response/Deserialization/DeserializationResult.cs b/smsapi/Api/Response/Deserialization/DeserializationResult.cs new file mode 100644 index 0000000..1d6f555 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/DeserializationResult.cs @@ -0,0 +1,23 @@ +#nullable enable +namespace SMSApi.Api.Response.Deserialization +{ + public class DeserializationResult + { + public T? Result; + public ResponseError? ClientError; + public ResponseError? HostError; + public ResponseError? ActionError; + } + + public readonly struct ResponseError + { + public readonly string Message; + public readonly int Code; + + public ResponseError(string message, int code) + { + Message = message; + Code = code; + } + } +} diff --git a/smsapi/Api/Response/Deserialization/Exception/DeserializationExceptionManager.cs b/smsapi/Api/Response/Deserialization/Exception/DeserializationExceptionManager.cs new file mode 100644 index 0000000..d362b35 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/Exception/DeserializationExceptionManager.cs @@ -0,0 +1,21 @@ +using System; +using SMSApi.Api; +using SMSApi.Api.Response.Deserialization; + +namespace smsapi.Api.Response.Deserialization.Exception +{ + public static class DeserializationExceptionManager + { + public static void ThrowErrors(this DeserializationResult dr) + { + if (dr.ClientError != null) + throw new ClientException(dr.ClientError.Value.Message, dr.ClientError.Value.Code); + + if (dr.HostError != null) + throw new HostException(dr.HostError.Value.Message, Convert.ToString(dr.HostError.Value.Code)); + + if (dr.ActionError != null) + throw new ActionException(dr.ActionError.Value.Message, dr.ActionError.Value.Code); + } + } +} diff --git a/smsapi/Api/Response/Deserialization/IDeserializer.cs b/smsapi/Api/Response/Deserialization/IDeserializer.cs new file mode 100644 index 0000000..ba3416f --- /dev/null +++ b/smsapi/Api/Response/Deserialization/IDeserializer.cs @@ -0,0 +1,7 @@ +namespace SMSApi.Api.Response.Deserialization +{ + public interface IDeserializer + { + public DeserializationResult Deserialize(HttpResponseEntity responseEntity); + } +} diff --git a/smsapi/Api/Response/Deserialization/LegacyJsonResponseDeserializer.cs b/smsapi/Api/Response/Deserialization/LegacyJsonResponseDeserializer.cs new file mode 100644 index 0000000..ea08844 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/LegacyJsonResponseDeserializer.cs @@ -0,0 +1,121 @@ +#nullable enable +using System.IO; +using System.Runtime.Serialization; +using smsapi.Api.Response.Deserialization.Exception; +using SMSApi.Api.Response.ResponseResolver; + +namespace SMSApi.Api.Response.Deserialization +{ + public class LegacyJsonResponseDeserializer : IDeserializer + { + private readonly BaseJsonDeserializer _baseJsonDeserializer = new(); + + public DeserializationResult Deserialize(HttpResponseEntity responseEntity) + { + DeserializationResult response; + Stream? data = null; + + try + { + var errorDeserializationResult = new DeserializationResult(); + HandleError(responseEntity, errorDeserializationResult); + errorDeserializationResult.ThrowErrors(); + + data = responseEntity.Content.Result; + response = _baseJsonDeserializer.Deserialize(responseEntity); + } + catch (SerializationException e) + { + throw new HostException(e.Message, HostException.E_JSON_DECODE); + } + catch (Exception e) + { + throw e; + } + finally + { + data?.Close(); + } + + return response; + } + + private void HandleError(HttpResponseEntity responseEntity, DeserializationResult deserializationResult) + { + try + { + var error = _baseJsonDeserializer.Deserialize(responseEntity).Result; + + if (!error.IsError()) return; + + if (IsHostError(error.ErrorCode)) + { + deserializationResult.HostError = + new ResponseError(error.GetErrorMessage(), error.ErrorCode); + return; + } + + if (IsClientError(error.ErrorCode)) + { + deserializationResult.ClientError = + new ResponseError(error.GetErrorMessage(), error.ErrorCode); + return; + } + + deserializationResult.ActionError = + new ResponseError(error.GetErrorMessage(), error.ErrorCode); + } + catch (SerializationException) + { + } + } + + /** + * 101 Niepoprawne lub brak danych autoryzacji. + * 102 Nieprawidłowy login lub hasło + * 103 Brak punków dla tego użytkownika + * 105 Błędny adres IP + * 110 Usługa nie jest dostępna na danym koncie + * 1000 Akcja dostępna tylko dla użytkownika głównego + * 1001 Nieprawidłowa akcja + */ + private static bool IsClientError(int code) + { + switch (code) + { + case 101: + case 102: + case 103: + case 105: + case 110: + case 1000: + case 1001: + return true; + + default: + return false; + } + } + + /** + * 8 Błąd w odwołaniu + * 666 Wewnętrzny błąd systemu + * 999 Wewnętrzny błąd systemu + * 201 Wewnętrzny błąd systemu + */ + private static bool IsHostError(int code) + { + switch (code) + { + case 8: + case 201: + case 666: + case 999: + return true; + + default: + return false; + } + } + } +} diff --git a/smsapi/Api/Response/Deserialization/RestJsonResponseDeserializer.cs b/smsapi/Api/Response/Deserialization/RestJsonResponseDeserializer.cs new file mode 100644 index 0000000..ebfa8c7 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/RestJsonResponseDeserializer.cs @@ -0,0 +1,53 @@ +using System; +using System.Linq; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; + +namespace SMSApi.Api.Response.Deserialization; + +public class RestJsonResponseDeserializer : IDeserializer +{ + private readonly LegacyJsonResponseDeserializer legacyJsonResponseDeserializer; + private readonly IResponseCodeAwareResolver[] responseCodesResolvers; + + public RestJsonResponseDeserializer( + LegacyJsonResponseDeserializer legacyJsonResponseDeserializer, + params IResponseCodeAwareResolver[] responseCodesResolvers + ) + { + this.legacyJsonResponseDeserializer = legacyJsonResponseDeserializer; + this.responseCodesResolvers = responseCodesResolvers; + } + + public DeserializationResult Deserialize(HttpResponseEntity responseEntity) + { + if (!typeof(IResponseCodeAwareResolver).IsAssignableFrom(typeof(T))) + throw new Exception("Deserialization from non-rest response"); + + if (responseEntity.StatusCode.IsSuccessful()) + return legacyJsonResponseDeserializer.Deserialize(responseEntity); + + var responseObject = (IResponseCodeAwareResolver)Activator.CreateInstance(); + var exceptionsMatchers = responseObject.HandleExceptionActions() + .Concat(responseCodesResolvers.SelectMany(resolver => resolver.HandleExceptionActions())); + + var responseStatusCode = (int)responseEntity.StatusCode; + var matchedExceptions = exceptionsMatchers + .Where(pair => pair.Key.Equals(responseStatusCode)) + .ToHashSet(); + + if (matchedExceptions.Count > 0) matchedExceptions.First().Value.Invoke(responseEntity.Content.Result); + + HandleUnknownError(responseEntity); + + return default; + } + + private static void HandleUnknownError(HttpResponseEntity responseEntity) + { + throw new UnhandledRestException( + $"Unknown http status code: {(int)responseEntity.StatusCode}", + responseEntity.StatusCode.ToString() + ); + } +} diff --git a/smsapi/Api/Response/Deserialization/TooManyRequestsErrorResolver.cs b/smsapi/Api/Response/Deserialization/TooManyRequestsErrorResolver.cs new file mode 100644 index 0000000..23f0494 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/TooManyRequestsErrorResolver.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.IO; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; + +namespace SMSApi.Api.Response.Deserialization; + +public class TooManyRequestsErrorResolver : IResponseCodeAwareResolver +{ + public Dictionary> HandleExceptionActions() + { + return new Dictionary> + { + { 429, _ => throw new TooManyRequestsException() } + }; + } +} diff --git a/smsapi/Api/Response/Deserialization/ValidationErrorsResolver.cs b/smsapi/Api/Response/Deserialization/ValidationErrorsResolver.cs new file mode 100644 index 0000000..46fce90 --- /dev/null +++ b/smsapi/Api/Response/Deserialization/ValidationErrorsResolver.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Runtime.Serialization; +using System.Threading.Tasks; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; + +namespace SMSApi.Api.Response.Deserialization; + +public class ValidationErrorsResolver : IResponseCodeAwareResolver +{ + private readonly BaseJsonDeserializer baseJsonDeserializer; + + public ValidationErrorsResolver(BaseJsonDeserializer baseJsonDeserializer) + { + this.baseJsonDeserializer = baseJsonDeserializer; + } + + public Dictionary> HandleExceptionActions() + { + return new Dictionary> + { + { 400, ResolveErrors } + }; + } + + private void ResolveErrors(Stream stream) + { + var validationErrors = baseJsonDeserializer.Deserialize( + new HttpResponseEntity(Task.FromResult(stream), HttpStatusCode.BadRequest) + ).Result; + + throw ValidationException.Create(validationErrors); + } + + [DataContract] + public readonly struct ValidationErrors + { + [DataMember(Name = "errors")] public readonly IEnumerable Errors; + } + + [DataContract] + public readonly struct ValidationError + { + [DataMember(Name = "message")] public readonly string Message; + + [DataMember(Name = "error")] public readonly string Error; + } +} diff --git a/smsapi/Api/Response/Error.cs b/smsapi/Api/Response/Error.cs deleted file mode 100644 index c4374ef..0000000 --- a/smsapi/Api/Response/Error.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Runtime.Serialization; - -namespace SMSApi.Api.Response -{ - [DataContract] - public class Error - { - public Error() - { - Code = 0; - Message = ""; - } - - [DataMember(Name = "error", IsRequired = true)] - public readonly int Code; - - [DataMember(Name = "message", IsRequired = true)] - public readonly string Message; - - public bool isError() - { - return (Code != 0); - } - } -} diff --git a/smsapi/Api/Response/Field.cs b/smsapi/Api/Response/Field.cs index ed4d3d2..bfa9824 100644 --- a/smsapi/Api/Response/Field.cs +++ b/smsapi/Api/Response/Field.cs @@ -2,22 +2,22 @@ namespace SMSApi.Api.Response { - [DataContract] - public class Field - { - public const string TextType = "TEXT"; - public const string DateType = "DATE"; - public const string EmailType = "EMAIL"; - public const string PhoneNumberType = "PHONE_NUMBER"; - public const string NumberType = "NUMBER"; + [DataContract] + public class Field + { + public const string DateType = "DATE"; + public const string EmailType = "EMAIL"; + public const string NumberType = "NUMBER"; + public const string PhoneNumberType = "PHONE_NUMBER"; + public const string TextType = "TEXT"; - [DataMember(Name = "id", IsRequired = false)] - public readonly string Id; + [DataMember(Name = "id", IsRequired = false)] + public readonly string Id; - [DataMember(Name = "name", IsRequired = false)] - public readonly string Name; + [DataMember(Name = "name", IsRequired = false)] + public readonly string Name; - [DataMember(Name = "type", IsRequired = false)] - public readonly string Type; - } + [DataMember(Name = "type", IsRequired = false)] + public readonly string Type; + } } diff --git a/smsapi/Api/Response/FieldOption.cs b/smsapi/Api/Response/FieldOption.cs index 29ea42d..0c26c13 100644 --- a/smsapi/Api/Response/FieldOption.cs +++ b/smsapi/Api/Response/FieldOption.cs @@ -2,13 +2,13 @@ namespace SMSApi.Api.Response { - [DataContract] - public class FieldOption - { - [DataMember(Name = "name", IsRequired = false)] - public readonly string Name; + [DataContract] + public class FieldOption + { + [DataMember(Name = "name", IsRequired = false)] + public readonly string Name; - [DataMember(Name = "value", IsRequired = false)] - public readonly string Value; - } + [DataMember(Name = "value", IsRequired = false)] + public readonly string Value; + } } diff --git a/smsapi/Api/Response/FieldOptions.cs b/smsapi/Api/Response/FieldOptions.cs index 0bf0aaa..f59f20e 100644 --- a/smsapi/Api/Response/FieldOptions.cs +++ b/smsapi/Api/Response/FieldOptions.cs @@ -2,9 +2,10 @@ namespace SMSApi.Api.Response { - [DataContract] - public class FieldOptions : BasicCollection - { - private FieldOptions() : base() { } - } + [DataContract] + public class FieldOptions : BasicCollection + { + private FieldOptions() + { } + } } diff --git a/smsapi/Api/Response/Fields.cs b/smsapi/Api/Response/Fields.cs index df7f10b..a4bc83a 100644 --- a/smsapi/Api/Response/Fields.cs +++ b/smsapi/Api/Response/Fields.cs @@ -2,9 +2,10 @@ namespace SMSApi.Api.Response { - [DataContract] - public class Fields : BasicCollection - { - private Fields() : base() { } - } + [DataContract] + public class Fields : BasicCollection + { + private Fields() + { } + } } diff --git a/smsapi/Api/Response/Group.cs b/smsapi/Api/Response/Group.cs index 624e45a..ec6a3a2 100644 --- a/smsapi/Api/Response/Group.cs +++ b/smsapi/Api/Response/Group.cs @@ -1,64 +1,82 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Response { - [DataContract] - public class Group : Base - { - private Group() : base() { } - - [DataMember(Name = "id", IsRequired = false)] - public readonly string Id; - - [DataMember(Name = "name", IsRequired = true)] - public readonly string Name; - - private int contactsCount; - [DataMember(Name = "contacts_count", IsRequired = false)] - public int ContactsCount { get { return contactsCount; } private set { contactsCount = value; } } - - private DateTime? dateCreated; - [DataMember(Name = "date_created", IsRequired = false)] - private string DateCreatedSerializationHelper { set { dateCreated = DateTime.Parse(value); } get { return ""; } } - public DateTime? DateCreated { get { return dateCreated; } } - - private DateTime? dateUpdated; - [DataMember(Name = "date_updated", IsRequired = false)] - private string DateUpdatedSerializationHelper { set { dateUpdated = DateTime.Parse(value); } get { return ""; } } - public DateTime? DateUpdated { get { return dateUpdated; } } - - private string description; - [DataMember(Name = "description", IsRequired = false)] - public string Description { get { return description; } private set { description = value; } } - - [DataMember(Name = "created_by", IsRequired = false)] - public readonly string CreatedBy; - - [DataMember(Name = "idx", IsRequired = false)] - public readonly string Idx; - - [DataMember(Name = "permissions", IsRequired = false)] - private System.Collections.Generic.List permissions; - public System.Collections.Generic.List Permissions - { - get - { - if (permissions == null) - permissions = new System.Collections.Generic.List(); - return permissions; - } - } - - [Obsolete("use Description instead")] - [DataMember(Name = "info", IsRequired = false)] - public string Info { get { return Description; } private set { Description = value; } } - - [Obsolete("use ContactsCount instead")] - [DataMember(Name = "numbers_count", IsRequired = false)] - public uint NumbersCount { get { return (uint)ContactsCount; } private set { ContactsCount = (int)value; } } - } + [DataContract] + public class Group : ErrorAwareResponse + { + [DataMember(Name = "created_by", IsRequired = false)] + public readonly string CreatedBy; + + [DataMember(Name = "id", IsRequired = false)] + public readonly string Id; + + [DataMember(Name = "idx", IsRequired = false)] + public readonly string Idx; + + [DataMember(Name = "name", IsRequired = true)] + public readonly string Name; + + [DataMember(Name = "permissions", IsRequired = false)] + private List permissions; + + private Group() + { } + + [DataMember(Name = "contacts_count", IsRequired = false)] + public int ContactsCount { get; private set; } + + public DateTime? DateCreated { get; private set; } + + public DateTime? DateUpdated { get; private set; } + + [DataMember(Name = "description", IsRequired = false)] + public string Description { get; private set; } + + [Obsolete("use Description instead")] + [DataMember(Name = "info", IsRequired = false)] + public string Info + { + get => Description; + private set => Description = value; + } + + [Obsolete("use ContactsCount instead")] + [DataMember(Name = "numbers_count", IsRequired = false)] + public uint NumbersCount + { + get => (uint)ContactsCount; + private set => ContactsCount = (int)value; + } + + public List Permissions + { + get + { + if (permissions == null) + { + permissions = new List(); + } + + return permissions; + } + } + + [DataMember(Name = "date_created", IsRequired = false)] + private string DateCreatedSerializationHelper + { + set => DateCreated = DateTime.Parse(value); + get => ""; + } + + [DataMember(Name = "date_updated", IsRequired = false)] + private string DateUpdatedSerializationHelper + { + set => DateUpdated = DateTime.Parse(value); + get => ""; + } + } } diff --git a/smsapi/Api/Response/GroupPermission.cs b/smsapi/Api/Response/GroupPermission.cs index f6f4860..dd333cb 100644 --- a/smsapi/Api/Response/GroupPermission.cs +++ b/smsapi/Api/Response/GroupPermission.cs @@ -1,26 +1,24 @@ -using System; using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Response { - [DataContract] - public class GroupPermission : Base - { - public GroupPermission() : base() { } + [DataContract] + public class GroupPermission : ErrorAwareResponse + { + [DataMember(Name = "group_id", IsRequired = false)] + public readonly string GroupId; - [DataMember(Name = "group_id", IsRequired = false)] - public readonly string GroupId; - - [DataMember(Name = "username", IsRequired = false)] - public readonly string Username; + [DataMember(Name = "read", IsRequired = false)] + public readonly bool Read; - [DataMember(Name = "write", IsRequired = false)] - public readonly bool Write; + [DataMember(Name = "send", IsRequired = false)] + public readonly bool Send; - [DataMember(Name = "read", IsRequired = false)] - public readonly bool Read; + [DataMember(Name = "username", IsRequired = false)] + public readonly string Username; - [DataMember(Name = "send", IsRequired = false)] - public readonly bool Send; - } + [DataMember(Name = "write", IsRequired = false)] + public readonly bool Write; + } } diff --git a/smsapi/Api/Response/GroupPermissions.cs b/smsapi/Api/Response/GroupPermissions.cs index 79298b1..ce6bab7 100644 --- a/smsapi/Api/Response/GroupPermissions.cs +++ b/smsapi/Api/Response/GroupPermissions.cs @@ -1,11 +1,11 @@ -using System; using System.Runtime.Serialization; namespace SMSApi.Api.Response { - [DataContract] - public class GroupPermissions : BasicCollection - { - private GroupPermissions() : base() { } - } + [DataContract] + public class GroupPermissions : BasicCollection + { + private GroupPermissions() + { } + } } diff --git a/smsapi/Api/Response/Groups.cs b/smsapi/Api/Response/Groups.cs index 715551d..45a0b55 100644 --- a/smsapi/Api/Response/Groups.cs +++ b/smsapi/Api/Response/Groups.cs @@ -5,6 +5,7 @@ namespace SMSApi.Api.Response [DataContract] public class Groups : BasicCollection { - private Groups() : base() { } + private Groups() + { } } } diff --git a/smsapi/Api/Response/HttpCodesGroupHelper.cs b/smsapi/Api/Response/HttpCodesGroupHelper.cs new file mode 100644 index 0000000..1cde094 --- /dev/null +++ b/smsapi/Api/Response/HttpCodesGroupHelper.cs @@ -0,0 +1,13 @@ +using System.Net; + +namespace SMSApi.Api.Response; + +public static class HttpCodesGroupHelper +{ + public static bool IsSuccessful(this HttpStatusCode statusCode) + { + var intRepresentation = (int)statusCode; + + return intRepresentation is >= 200 and <= 299; + } +} diff --git a/smsapi/Api/Response/MFA/Exception/ExpiredVerificationCodeException.cs b/smsapi/Api/Response/MFA/Exception/ExpiredVerificationCodeException.cs new file mode 100644 index 0000000..2757f32 --- /dev/null +++ b/smsapi/Api/Response/MFA/Exception/ExpiredVerificationCodeException.cs @@ -0,0 +1,8 @@ +namespace SMSApi.Api.Response.MFA.Exception; + +public class ExpiredVerificationCodeException : ClientException +{ + public ExpiredVerificationCodeException() : base("Verification code has expired", 408) + { + } +} diff --git a/smsapi/Api/Response/MFA/Exception/InvalidVerificationCodeException.cs b/smsapi/Api/Response/MFA/Exception/InvalidVerificationCodeException.cs new file mode 100644 index 0000000..b6f48aa --- /dev/null +++ b/smsapi/Api/Response/MFA/Exception/InvalidVerificationCodeException.cs @@ -0,0 +1,8 @@ +namespace SMSApi.Api.Response.MFA.Exception; + +public class InvalidVerificationCodeException : ClientException +{ + public InvalidVerificationCodeException() : base("Invalid verification code", 404) + { + } +} diff --git a/smsapi/Api/Response/MFA/MFACreationResponse.cs b/smsapi/Api/Response/MFA/MFACreationResponse.cs new file mode 100644 index 0000000..efdd356 --- /dev/null +++ b/smsapi/Api/Response/MFA/MFACreationResponse.cs @@ -0,0 +1,16 @@ +using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; + +namespace SMSApi.Api.Response.MFA; + +[DataContract] +public class MFACreationResponse : IResponseCodeAwareResolver +{ + [DataMember(Name = "code")] public readonly string Code; + + [DataMember(Name = "from")] public readonly string From; + + [DataMember(Name = "id")] public readonly string Id; + + [DataMember(Name = "phone_number")] public readonly string PhoneNumber; +} diff --git a/smsapi/Api/Response/MFA/MFAVerificationResponse.cs b/smsapi/Api/Response/MFA/MFAVerificationResponse.cs new file mode 100644 index 0000000..ddd90e3 --- /dev/null +++ b/smsapi/Api/Response/MFA/MFAVerificationResponse.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.IO; +using SMSApi.Api.Response.MFA.Exception; +using SMSApi.Api.Response.ResponseResolver; + +namespace SMSApi.Api.Response.MFA; + +public class MFAVerificationResponse : IResponseCodeAwareResolver +{ + public Dictionary> HandleExceptionActions() + { + return new Dictionary> + { + { 404, _ => throw new InvalidVerificationCodeException() }, + { 408, _ => throw new ExpiredVerificationCodeException() }, + }; + } +} diff --git a/smsapi/Api/Response/MessageStatus.cs b/smsapi/Api/Response/MessageStatus.cs index 3eb9bd0..7c64400 100644 --- a/smsapi/Api/Response/MessageStatus.cs +++ b/smsapi/Api/Response/MessageStatus.cs @@ -5,7 +5,25 @@ namespace SMSApi.Api.Response [DataContract] public class MessageStatus { - private MessageStatus() + [DataMember(Name = "error", IsRequired = false)] + public readonly string Error; + + [DataMember(Name = "id", IsRequired = true)] + public readonly string ID; + + [DataMember(Name = "idx", IsRequired = false)] + public readonly string IDx; + + [DataMember(Name = "number", IsRequired = true)] + public readonly string Number; + + [DataMember(Name = "points", IsRequired = true)] + public readonly double Points; + + [DataMember(Name = "status", IsRequired = true)] + public readonly string Status; + + private MessageStatus() { ID = ""; Points = 0; @@ -17,38 +35,37 @@ private MessageStatus() public bool isError() { - if (ID == null || ID.Length == 0) return true; - if (Error != null) return true; - + if (ID == null || ID.Length == 0) + { + return true; + } + + if (Error != null) + { + return true; + } + return false; } public bool isFinal() { - if (isError()) return true; + if (isError()) + { + return true; + } - if (Status.Equals("QUEUE")) return false; - if (Status.Equals("SENT")) return false; + if (Status.Equals("QUEUE")) + { + return false; + } + + if (Status.Equals("SENT")) + { + return false; + } return true; } - - [DataMember(Name = "id", IsRequired = true)] - public readonly string ID; - - [DataMember(Name = "points", IsRequired = true)] - public readonly double Points; - - [DataMember(Name = "number", IsRequired = true)] - public readonly string Number; - - [DataMember(Name = "status", IsRequired = true)] - public readonly string Status; - - [DataMember(Name = "error", IsRequired = false)] - public readonly string Error; - - [DataMember(Name = "idx", IsRequired = false)] - public readonly string IDx; } } diff --git a/smsapi/Api/Response/NumberStatus.cs b/smsapi/Api/Response/NumberStatus.cs index 88e27dc..8a32df8 100644 --- a/smsapi/Api/Response/NumberStatus.cs +++ b/smsapi/Api/Response/NumberStatus.cs @@ -5,40 +5,26 @@ namespace SMSApi.Api.Response [DataContract] public class NumberStatus { - private NumberStatus() - { - ID = ""; - Number = ""; - MCC = 0; - MNC = 0; - Info = null; - Status = null; - Date = 0; - Ported = 0; - PortedFrom = 0; - Points = 0; - } + [DataMember(Name = "date", IsRequired = false)] + public readonly int Date; [DataMember(Name = "id", IsRequired = false)] public readonly string ID; - [DataMember(Name = "number", IsRequired = true)] - public readonly string Number; - + [DataMember(Name = "info", IsRequired = false)] + public readonly string Info; + [DataMember(Name = "mcc", IsRequired = false)] public readonly int MCC; [DataMember(Name = "mnc", IsRequired = false)] public readonly int MNC; - - [DataMember(Name = "info", IsRequired = false)] - public readonly string Info; - [DataMember(Name = "status", IsRequired = false)] - public readonly string Status; - - [DataMember(Name = "date", IsRequired = false)] - public readonly int Date; + [DataMember(Name = "number", IsRequired = true)] + public readonly string Number; + + [DataMember(Name = "price", IsRequired = false)] + public readonly double Points; [DataMember(Name = "ported", IsRequired = false)] public readonly int Ported; @@ -46,7 +32,21 @@ private NumberStatus() [DataMember(Name = "ported_from", IsRequired = false)] public readonly int PortedFrom; - [DataMember(Name = "price", IsRequired = false)] - public readonly double Points; + [DataMember(Name = "status", IsRequired = false)] + public readonly string Status; + + private NumberStatus() + { + ID = ""; + Number = ""; + MCC = 0; + MNC = 0; + Info = null; + Status = null; + Date = 0; + Ported = 0; + PortedFrom = 0; + Points = 0; + } } } diff --git a/smsapi/Api/Response/Ping/PingServiceResponse.cs b/smsapi/Api/Response/Ping/PingServiceResponse.cs new file mode 100644 index 0000000..038951a --- /dev/null +++ b/smsapi/Api/Response/Ping/PingServiceResponse.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; + +namespace SMSApi.Api.Response.Ping; + +[DataContract] +public readonly record struct PingServiceResponse : IResponseCodeAwareResolver +{ + [DataMember(Name = "authorized")] public readonly bool Authorized; + + [DataMember(Name = "unavailable")] public readonly IEnumerable UnavailableServices; +} diff --git a/smsapi/Api/Response/Points.cs b/smsapi/Api/Response/Points.cs index 6691a1e..3cfb807 100644 --- a/smsapi/Api/Response/Points.cs +++ b/smsapi/Api/Response/Points.cs @@ -1,24 +1,30 @@ -using System.Runtime.Serialization; - -namespace SMSApi.Api.Response -{ - [DataContract] - public class Credits : Base - { - private Credits() : base() { } - - [DataMember(Name = "points", IsRequired = true)] - public readonly double Points; +using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; - [DataMember(Name = "proCount", IsRequired = false)] - public readonly int ProCount; - [DataMember(Name = "ecoCount", IsRequired = false)] +namespace SMSApi.Api.Response +{ + [DataContract] + public class Credits : ErrorAwareResponse + { + [DataMember(Name = "ecoCount", IsRequired = false)] public readonly int EcoCount; - [DataMember(Name = "mmsCount", IsRequired = false)] + + [DataMember(Name = "mmsCount", IsRequired = false)] public readonly int MmsCount; - [DataMember(Name = "vmsGsmCount", IsRequired = false)] + + [DataMember(Name = "points", IsRequired = true)] + public readonly double Points; + + [DataMember(Name = "proCount", IsRequired = false)] + public readonly int ProCount; + + [DataMember(Name = "vmsGsmCount", IsRequired = false)] public readonly int VmsGsmCount; + [DataMember(Name = "vmsLandCount", IsRequired = false)] - public readonly int VmsLandCount; - } -} + public readonly int VmsLandCount; + + private Credits() + { } + } +} diff --git a/smsapi/Api/Response/Profile/Prices/PriceResponse.cs b/smsapi/Api/Response/Profile/Prices/PriceResponse.cs new file mode 100644 index 0000000..b0bfe42 --- /dev/null +++ b/smsapi/Api/Response/Profile/Prices/PriceResponse.cs @@ -0,0 +1,34 @@ +using System.Runtime.Serialization; + +namespace SMSApi.Api.Response.Profile.Prices; + +[DataContract] +public readonly struct PriceResponse +{ + [DataMember(Name = "price")] public readonly Price Price; + + [DataMember(Name = "country")] public readonly Country Country; + + [DataMember(Name = "network")] public readonly Network Network; +} + +[DataContract] +public readonly struct Price +{ + [DataMember(Name = "amount")] public readonly float Amount; + [DataMember(Name = "currency")] public readonly string Currency; +} + +[DataContract] +public readonly struct Country +{ + [DataMember(Name = "name")] public readonly string Name; + [DataMember(Name = "mcc")] public readonly int MCC; +} + +[DataContract] +public readonly struct Network +{ + [DataMember(Name = "name")] public readonly string Name; + [DataMember(Name = "mnc")] public readonly int MNC; +} diff --git a/smsapi/Api/Response/REST/Exception/AccessForbiddenException.cs b/smsapi/Api/Response/REST/Exception/AccessForbiddenException.cs new file mode 100644 index 0000000..242cd5c --- /dev/null +++ b/smsapi/Api/Response/REST/Exception/AccessForbiddenException.cs @@ -0,0 +1,10 @@ +using SMSApi.Api; + +namespace smsapi.Api.Response.REST.Exception; + +public class AccessForbiddenException : ClientException +{ + public AccessForbiddenException() : base("Access forbidden", 403) + { + } +} diff --git a/smsapi/Api/Response/REST/Exception/TooManyRequestsException.cs b/smsapi/Api/Response/REST/Exception/TooManyRequestsException.cs new file mode 100644 index 0000000..abc82ad --- /dev/null +++ b/smsapi/Api/Response/REST/Exception/TooManyRequestsException.cs @@ -0,0 +1,10 @@ +using SMSApi.Api; + +namespace smsapi.Api.Response.REST.Exception; + +public class TooManyRequestsException : ClientException +{ + public TooManyRequestsException() : base("Too many requests", 429) + { + } +} diff --git a/smsapi/Api/Response/REST/Exception/UnauthorizedException.cs b/smsapi/Api/Response/REST/Exception/UnauthorizedException.cs new file mode 100644 index 0000000..0a45467 --- /dev/null +++ b/smsapi/Api/Response/REST/Exception/UnauthorizedException.cs @@ -0,0 +1,10 @@ +using SMSApi.Api; + +namespace smsapi.Api.Response.REST.Exception; + +public class UnauthorizedException : ClientException +{ + public UnauthorizedException() : base("Invalid credentials", 401) + { + } +} diff --git a/smsapi/Api/Response/REST/Exception/UnhandledRestException.cs b/smsapi/Api/Response/REST/Exception/UnhandledRestException.cs new file mode 100644 index 0000000..337d249 --- /dev/null +++ b/smsapi/Api/Response/REST/Exception/UnhandledRestException.cs @@ -0,0 +1,10 @@ +using SMSApi.Api; + +namespace smsapi.Api.Response.REST.Exception; + +public class UnhandledRestException : HostException +{ + public UnhandledRestException(string message, string code) : base(message, code) + { + } +} diff --git a/smsapi/Api/Response/REST/Exception/ValidationException.cs b/smsapi/Api/Response/REST/Exception/ValidationException.cs new file mode 100644 index 0000000..36564c9 --- /dev/null +++ b/smsapi/Api/Response/REST/Exception/ValidationException.cs @@ -0,0 +1,26 @@ +using System.Linq; +using SMSApi.Api; +using SMSApi.Api.Response.Deserialization; + +namespace smsapi.Api.Response.REST.Exception; + +public class ValidationException : ClientException +{ + public readonly ValidationErrorsResolver.ValidationErrors ValidationErrors; + + private ValidationException(ValidationErrorsResolver.ValidationErrors validationErrors, string message) : base(message, 400) + { + ValidationErrors = validationErrors; + } + + public static ValidationException Create(ValidationErrorsResolver.ValidationErrors validationErrors) + { + var errorMessages = validationErrors.Errors + .Select(error => $"{error.Error}: {error.Message}") + .ToList(); + + var errorMessage = string.Join(", ", errorMessages); + + return new ValidationException(validationErrors, errorMessage); + } +} diff --git a/smsapi/Api/Response/Base.cs b/smsapi/Api/Response/ResponseResolver/ErrorAwareResponse.cs similarity index 53% rename from smsapi/Api/Response/Base.cs rename to smsapi/Api/Response/ResponseResolver/ErrorAwareResponse.cs index b6bc364..e007bc7 100644 --- a/smsapi/Api/Response/Base.cs +++ b/smsapi/Api/Response/ResponseResolver/ErrorAwareResponse.cs @@ -1,25 +1,17 @@ using System.Runtime.Serialization; -namespace SMSApi.Api.Response +namespace SMSApi.Api.Response.ResponseResolver { [DataContract] - public class Base + public class ErrorAwareResponse: IErrorResponse { - public Base() - { - ErrorCode = 0; - ErrorMessage = ""; - } - [DataMember(Name = "error", IsRequired = false)] public readonly int ErrorCode; [DataMember(Name = "message", IsRequired = false)] public readonly string ErrorMessage; - - public bool isError() - { - return (ErrorCode != 0); - } + + public bool IsError() => ErrorCode != 0; + public string GetErrorMessage() => ErrorMessage; } } diff --git a/smsapi/Api/Response/ResponseResolver/IErrorResponse.cs b/smsapi/Api/Response/ResponseResolver/IErrorResponse.cs new file mode 100644 index 0000000..ee75f66 --- /dev/null +++ b/smsapi/Api/Response/ResponseResolver/IErrorResponse.cs @@ -0,0 +1,6 @@ +namespace SMSApi.Api.Response.ResponseResolver +{ + public interface IErrorResponse + { + } +} diff --git a/smsapi/Api/Response/ResponseResolver/ResponseCodeAwareResolver.cs b/smsapi/Api/Response/ResponseResolver/ResponseCodeAwareResolver.cs new file mode 100644 index 0000000..6bacbd3 --- /dev/null +++ b/smsapi/Api/Response/ResponseResolver/ResponseCodeAwareResolver.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace SMSApi.Api.Response.ResponseResolver; + +public interface IResponseCodeAwareResolver : IErrorResponse +{ + public Dictionary> HandleExceptionActions() => new(); +} diff --git a/smsapi/Api/Response/Sender.cs b/smsapi/Api/Response/Sender.cs index 91e1e73..39e5a91 100644 --- a/smsapi/Api/Response/Sender.cs +++ b/smsapi/Api/Response/Sender.cs @@ -5,13 +5,13 @@ namespace SMSApi.Api.Response [DataContract] public class Sender { + [DataMember(Name = "default", IsRequired = true)] + public readonly bool Default; + [DataMember(Name = "sender", IsRequired = true)] public readonly string Name; [DataMember(Name = "status", IsRequired = true)] public readonly string Status; - - [DataMember(Name = "default", IsRequired = true)] - public readonly bool Default; } } diff --git a/smsapi/Api/Response/Senders.cs b/smsapi/Api/Response/Senders.cs index 58fcb0a..dc74d4b 100644 --- a/smsapi/Api/Response/Senders.cs +++ b/smsapi/Api/Response/Senders.cs @@ -6,22 +6,26 @@ namespace SMSApi.Api.Response [DataContract] public class Senders : Countable { - private Senders() : base() { } - [DataMember(Name = "list", IsRequired = false)] private List list; + private Senders() + { } + public List List { get { if (list == null) + { list = new List(); + } return list; } - set { } + set + { } } } } diff --git a/smsapi/Api/Response/Status.cs b/smsapi/Api/Response/Status.cs index b33fcf8..0f3e74a 100644 --- a/smsapi/Api/Response/Status.cs +++ b/smsapi/Api/Response/Status.cs @@ -6,31 +6,35 @@ namespace SMSApi.Api.Response [DataContract] public class Status : Countable { - private Status() : base() { } + [DataMember(Name = "length", IsRequired = false)] + public readonly int? Length; + + [DataMember(Name = "message", IsRequired = false)] + public readonly string Message; + + [DataMember(Name = "parts", IsRequired = false)] + public readonly int? Parts; [DataMember(Name = "list", IsRequired = false)] private List list; + private Status() + { } + public List List { get { if (list == null) + { list = new List(); + } return list; } - set { } + set + { } } - - [DataMember(Name = "message", IsRequired = false)] - public readonly string Message; - - [DataMember(Name = "length", IsRequired = false)] - public readonly int? Length; - - [DataMember(Name = "parts", IsRequired = false)] - public readonly int? Parts; } } diff --git a/smsapi/Api/Response/User.cs b/smsapi/Api/Response/User.cs index 119cbae..8919437 100644 --- a/smsapi/Api/Response/User.cs +++ b/smsapi/Api/Response/User.cs @@ -1,18 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Runtime.Serialization; +using System.Runtime.Serialization; +using SMSApi.Api.Response.ResponseResolver; namespace SMSApi.Api.Response { [DataContract] - public class User : Base + public class User : ErrorAwareResponse { - private User() : base() { } + [DataMember(Name = "active", IsRequired = true)] + public readonly bool Active; - [DataMember(Name = "username", IsRequired = true)] - public readonly string Username; + [DataMember(Name = "info", IsRequired = true)] + public readonly string Info; [DataMember(Name = "limit", IsRequired = true)] public readonly double Limit; @@ -20,16 +18,16 @@ private User() : base() { } [DataMember(Name = "month_limit", IsRequired = true)] public readonly double MonthLimit; - [DataMember(Name = "senders", IsRequired = true)] - public readonly uint Senders; - [DataMember(Name = "phonebook", IsRequired = true)] public readonly uint Phonebook; - [DataMember(Name = "active", IsRequired = true)] - public readonly bool Active; + [DataMember(Name = "senders", IsRequired = true)] + public readonly uint Senders; - [DataMember(Name = "info", IsRequired = true)] - public readonly string Info; + [DataMember(Name = "username", IsRequired = true)] + public readonly string Username; + + private User() + { } } } diff --git a/smsapi/Api/SMSFactory.cs b/smsapi/Api/SMSFactory.cs index c365089..0dfbba3 100644 --- a/smsapi/Api/SMSFactory.cs +++ b/smsapi/Api/SMSFactory.cs @@ -1,71 +1,67 @@ - -namespace SMSApi.Api -{ - public class SMSFactory : Factory - { - public SMSFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } - - public SMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { +using SMSApi.Api; +using SMSApi.Api.Action; + +namespace SMSApi.Api +{ + public class SMSFactory : Factory + { + public SMSFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } + + public SMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } + + public SMSFactory(IClient client, Proxy proxy) + : base(client, proxy) + { } + + public SMSDelete ActionDelete(string id = null) + { + var action = new SMSDelete(); + action.Proxy(proxy); + action.Id(id); + return action; + } + + public SMSGet ActionGet(string id = null) + { + var action = new SMSGet(); + action.Proxy(proxy); + action.Id(id); + return action; + } + + public SMSGet ActionGet(string[] id) + { + var action = new SMSGet(); + action.Proxy(proxy); + action.Ids(id); + return action; + } + + public SMSSend ActionSend(string to = null, string text = null) + { + string[] tos = to == null ? null : new[] { to }; + return ActionSend(tos, text); } - public SMSFactory(IClient client, Proxy proxy) - : base(client, proxy) - { + public SMSSend ActionSend(string[] to, string text = null) + { + var action = new SMSSend(); + action.Proxy(proxy); + action.SetTo(to); + action.SetText(text); + return action; } + } +} - public SMSApi.Api.Action.SMSDelete ActionDelete(string id = null) - { - SMSApi.Api.Action.SMSDelete action = new SMSApi.Api.Action.SMSDelete(); - - action.Client(client); - action.Proxy(proxy); - action.Id(id); - - return action; - } - - public SMSApi.Api.Action.SMSGet ActionGet(string id = null) - { - SMSApi.Api.Action.SMSGet action = new SMSApi.Api.Action.SMSGet(); - - action.Client(client); - action.Proxy(proxy); - action.Id(id); - - return action; - } - - public SMSApi.Api.Action.SMSGet ActionGet(string[] id) - { - SMSApi.Api.Action.SMSGet action = new SMSApi.Api.Action.SMSGet(); - - action.Client(client); - action.Proxy(proxy); - action.Ids(id); - - return action; - } - - public SMSApi.Api.Action.SMSSend ActionSend(string to = null, string text = null) - { - string[] tos = ( to == null ? null : new string[] { to } ); - return ActionSend(tos, text); - } - - public SMSApi.Api.Action.SMSSend ActionSend(string[] to, string text = null) - { - SMSApi.Api.Action.SMSSend action = new SMSApi.Api.Action.SMSSend(); - action.Client(client); - action.Proxy(proxy); - action.SetTo(to); - action.SetText(text); - - return action; - } - } -} +public static class SMSFeatureRegister +{ + public static SMSFactory SMS(this Features features) + { + return new SMSFactory(features.Client, features.Proxy); + } +} \ No newline at end of file diff --git a/smsapi/Api/SenderFactory.cs b/smsapi/Api/SenderFactory.cs index 7a85e5d..f649135 100644 --- a/smsapi/Api/SenderFactory.cs +++ b/smsapi/Api/SenderFactory.cs @@ -1,71 +1,59 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using SMSApi.Api; +using SMSApi.Api.Action; namespace SMSApi.Api { public class SenderFactory : Factory { - public SenderFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } + public SenderFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } - public SenderFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } + public SenderFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } - public SenderFactory(IClient client, Proxy proxy) - : base(client, proxy) - { - } + public SenderFactory(IClient client, Proxy proxy) + : base(client, proxy) + { } - public SMSApi.Api.Action.SenderAdd ActionAdd(string name = null) + public SenderAdd ActionAdd(string name = null) { - var action = new SMSApi.Api.Action.SenderAdd(); - - action.Client(client); + var action = new SenderAdd(); action.Proxy(proxy); - action.SetName(name); - return action; } - public SMSApi.Api.Action.SenderDelete ActionDelete(string name = null) + public SenderDelete ActionDelete(string name = null) { - var action = new SMSApi.Api.Action.SenderDelete(); - - action.Client(client); + var action = new SenderDelete(); action.Proxy(proxy); - action.Name(name); - return action; } - public SMSApi.Api.Action.SenderSetDefault ActionSetDefault(string name = null) + public SenderList ActionList() { - var action = new SMSApi.Api.Action.SenderSetDefault(); - - action.Client(client); + var action = new SenderList(); action.Proxy(proxy); - - action.Name(name); - return action; } - public SMSApi.Api.Action.SenderList ActionList() + public SenderSetDefault ActionSetDefault(string name = null) { - var action = new SMSApi.Api.Action.SenderList(); - - action.Client(client); + var action = new SenderSetDefault(); action.Proxy(proxy); - + action.Name(name); return action; } } } + +public static class SenderFeatureRegister +{ + public static SenderFactory Sender(this Features features) + { + return new SenderFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/UserFactory.cs b/smsapi/Api/UserFactory.cs index 312fb27..77bfb1f 100644 --- a/smsapi/Api/UserFactory.cs +++ b/smsapi/Api/UserFactory.cs @@ -1,79 +1,65 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using SMSApi.Api; +using SMSApi.Api.Action; namespace SMSApi.Api { public class UserFactory : Factory { - public UserFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } + public UserFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } - public UserFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } + public UserFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } - public UserFactory(IClient client, Proxy proxy) - : base(client, proxy) - { - } + public UserFactory(IClient client, Proxy proxy) + : base(client, proxy) + { } - public SMSApi.Api.Action.UserGetCredits ActionGetCredits() + public UserAdd ActionAdd() { - var action = new SMSApi.Api.Action.UserGetCredits(); - - action.Client(client); + var action = new UserAdd(); action.Proxy(proxy); - return action; } - public SMSApi.Api.Action.UserAdd ActionAdd() + public UserEdit ActionEdit(string username = null) { - var action = new SMSApi.Api.Action.UserAdd(); - - action.Client(client); + var action = new UserEdit(); action.Proxy(proxy); - + action.Username(username); return action; } - public SMSApi.Api.Action.UserEdit ActionEdit(string username = null) + public UserGet ActionGet(string username = null) { - var action = new SMSApi.Api.Action.UserEdit(); - - action.Client(client); + var action = new UserGet(); action.Proxy(proxy); - action.Username(username); - return action; } - public SMSApi.Api.Action.UserGet ActionGet(string username = null) + public UserGetCredits ActionGetCredits() { - var action = new SMSApi.Api.Action.UserGet(); - - action.Client(client); + var action = new UserGetCredits(); action.Proxy(proxy); - - action.Username(username); - return action; } - public SMSApi.Api.Action.UserList ActionList() + public UserList ActionList() { - var action = new SMSApi.Api.Action.UserList(); - - action.Client(client); + var action = new UserList(); action.Proxy(proxy); - return action; } } } + +public static class UserFeatureRegister +{ + public static UserFactory User(this Features features) + { + return new UserFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Api/VMSFactory.cs b/smsapi/Api/VMSFactory.cs index f676dc3..295bc49 100644 --- a/smsapi/Api/VMSFactory.cs +++ b/smsapi/Api/VMSFactory.cs @@ -1,70 +1,66 @@ - -namespace SMSApi.Api -{ - public class VMSFactory : Factory - { - public VMSFactory(ProxyAddress address = ProxyAddress.SmsApiPl) - : base(address) - { - } - - public VMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiPl) - : base(client, address) - { - } +using SMSApi.Api; +using SMSApi.Api.Action; + +namespace SMSApi.Api +{ + public class VMSFactory : Factory + { + public VMSFactory(ProxyAddress address = ProxyAddress.SmsApiIo) + : base(address) + { } - public VMSFactory(IClient client, Proxy proxy) + public VMSFactory(IClient client, ProxyAddress address = ProxyAddress.SmsApiIo) + : base(client, address) + { } + + public VMSFactory(IClient client, Proxy proxy) : base(client, proxy) + { } + + public VMSDelete ActionDelete(string id = null) + { + var action = new VMSDelete(); + action.Proxy(proxy); + action.Id(id); + return action; + } + + public VMSGet ActionGet(string id = null) + { + var action = new VMSGet(); + action.Proxy(proxy); + action.Id(id); + return action; + } + + public VMSGet ActionGet(string[] id) + { + var action = new VMSGet(); + action.Proxy(proxy); + action.Ids(id); + return action; + } + + public VMSSend ActionSend(string to = null) + { + string[] tos = to == null ? null : new[] { to }; + return ActionSend(tos); + } + + public VMSSend ActionSend(string[] to) { + var action = new VMSSend(); + action.Proxy(proxy); + action.SetTo(to); + return action; } + } +} - public SMSApi.Api.Action.VMSDelete ActionDelete(string id = null) - { - SMSApi.Api.Action.VMSDelete action = new SMSApi.Api.Action.VMSDelete(); - - action.Client(client); - action.Proxy(proxy); - action.Id(id); - - return action; - } - - public SMSApi.Api.Action.VMSGet ActionGet(string id = null) - { - SMSApi.Api.Action.VMSGet action = new SMSApi.Api.Action.VMSGet(); - - action.Client(client); - action.Proxy(proxy); - action.Id(id); - - return action; - } - - public SMSApi.Api.Action.VMSGet ActionGet(string[] id) - { - SMSApi.Api.Action.VMSGet action = new SMSApi.Api.Action.VMSGet(); - - action.Client(client); - action.Proxy(proxy); - action.Ids(id); - - return action; - } - - public SMSApi.Api.Action.VMSSend ActionSend(string to = null) - { - string[] tos = ( to == null ? null : new string[] { to } ); - return ActionSend(tos); - } - - public SMSApi.Api.Action.VMSSend ActionSend(string[] to) - { - SMSApi.Api.Action.VMSSend action = new SMSApi.Api.Action.VMSSend(); - action.Client(client); - action.Proxy(proxy); - action.SetTo(to); - - return action; - } - } -} +public static class VmsFeatureRegister +{ + public static VMSFactory VMS(this Features features) + { + return new VMSFactory(features.Client, features.Proxy); + } +} diff --git a/smsapi/Client.cs b/smsapi/Client.cs deleted file mode 100644 index a702116..0000000 --- a/smsapi/Client.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Security.Cryptography; -using System.Text; - -namespace SMSApi.Api -{ - public class Client : IClient - { - protected string username; - protected string password; - - public Client(string username) - { - SetUsername(username); - } - - public void SetUsername(string username) - { - this.username = username; - } - - public void SetPasswordHash(string password) - { - this.password = password; - } - - public void SetPasswordRAW(string password) - { - StringBuilder hash = new StringBuilder(); - - MD5 md5 = MD5.Create(); - byte[] hashbin = md5.ComputeHash(Encoding.UTF8.GetBytes(password)); - - for (int i = 0; i < hashbin.Length; i++) - { - hash.Append(hashbin[i].ToString("x2")); - } - - SetPasswordHash(hash.ToString()); - } - - public string GetAuthenticationHeader() - { - return "Basic " + System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username + ":" + password)); - } - - public string GetUsername() - { - return username; - } - - public string GetPassword() - { - return password; - } - } -} diff --git a/smsapi/ClientBase.cs b/smsapi/ClientBase.cs new file mode 100644 index 0000000..7b048ea --- /dev/null +++ b/smsapi/ClientBase.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace SMSApi.Api +{ + public abstract class ClientBase : IClient + { + private readonly string _clientAgent = $"smsapi-csharp-client/{Assembly.GetExecutingAssembly().GetName().Version} {Environment.Version}"; + + public abstract KeyValuePair DefaultRequestHeaders { get; } + + public string GetClientAgent() + { + return _clientAgent; + } + } +} diff --git a/smsapi/ClientException.cs b/smsapi/ClientException.cs index bfd8be8..9962a76 100644 --- a/smsapi/ClientException.cs +++ b/smsapi/ClientException.cs @@ -1,11 +1,11 @@ - -namespace SMSApi.Api +using System; + +namespace SMSApi.Api { - public class ClientException : SMSApi.Api.SmsapiException - { + public class ClientException : SmsapiException + { public ClientException(string message, int code) - : base(message, code) - { - } - } -} + : base(message, Convert.ToString(code)) + { } + } +} diff --git a/smsapi/ClientOAuth.cs b/smsapi/ClientOAuth.cs index 280bfbc..b128ceb 100644 --- a/smsapi/ClientOAuth.cs +++ b/smsapi/ClientOAuth.cs @@ -1,25 +1,20 @@ using System; -using System.Text; +using System.Collections.Generic; namespace SMSApi.Api { - public class ClientOAuth : IClient + public class ClientOAuth : ClientBase { - public string Token { get; } + private readonly string _token; public ClientOAuth(string token) { - if (string.IsNullOrEmpty(token)) - { - throw new ArgumentNullException(nameof(token)); - } + if (string.IsNullOrEmpty(token)) throw new ArgumentNullException(nameof(token)); - Token = token; + _token = token; } - public string GetAuthenticationHeader() - { - return "Bearer " + Token; - } + public override KeyValuePair DefaultRequestHeaders => + KeyValuePair.Create("Authorization", $"Bearer {_token}"); } } diff --git a/smsapi/Exception.cs b/smsapi/Exception.cs index 58c8bc4..5078194 100644 --- a/smsapi/Exception.cs +++ b/smsapi/Exception.cs @@ -1,9 +1,13 @@ - -namespace SMSApi.Api +namespace SMSApi.Api { - public class Exception : System.Exception - { - public Exception(string message) : base(message) { } - public Exception(string message, System.Exception inner) : base(message, inner) { } + public class Exception : System.Exception + { + public Exception(string message) + : base(message) + { } + + public Exception(string message, System.Exception inner) + : base(message, inner) + { } } } diff --git a/smsapi/HostException.cs b/smsapi/HostException.cs index 41af65f..5ce05f9 100644 --- a/smsapi/HostException.cs +++ b/smsapi/HostException.cs @@ -1,13 +1,13 @@ - -namespace SMSApi.Api +using System; + +namespace SMSApi.Api { - public class HostException : SMSApi.Api.SmsapiException - { - public static readonly int E_JSON_DECODE = -1; - - public HostException(string message, int code) - : base(message, code) - { - } - } -} + public class HostException : SmsapiException + { + public static readonly string E_JSON_DECODE = "-1"; + + public HostException(string message, string code) + : base(message, Convert.ToString(code)) + { } + } +} diff --git a/smsapi/HttpResponseEntity.cs b/smsapi/HttpResponseEntity.cs new file mode 100644 index 0000000..1b1d020 --- /dev/null +++ b/smsapi/HttpResponseEntity.cs @@ -0,0 +1,18 @@ +using System.IO; +using System.Net; +using System.Threading.Tasks; + +namespace SMSApi.Api +{ + public readonly struct HttpResponseEntity + { + public readonly Task Content; + public readonly HttpStatusCode StatusCode; + + public HttpResponseEntity(Task content, HttpStatusCode statusCode) + { + Content = content; + StatusCode = statusCode; + } + } +} diff --git a/smsapi/IClient.cs b/smsapi/IClient.cs index 1a079b4..3d27be9 100644 --- a/smsapi/IClient.cs +++ b/smsapi/IClient.cs @@ -1,12 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace SMSApi.Api { public interface IClient { - string GetAuthenticationHeader(); + KeyValuePair DefaultRequestHeaders { get; } + + string GetClientAgent(); } } diff --git a/smsapi/NativeHttpClientHelper.cs b/smsapi/NativeHttpClientHelper.cs new file mode 100644 index 0000000..3ba0350 --- /dev/null +++ b/smsapi/NativeHttpClientHelper.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace SMSApi.Api +{ + public static class NativeHttpClientHelper + { + public static async Task SendRequest( + this HttpClient httpClient, + RequestMethod method, + string uri, + NameValueCollection body = null, + Dictionary files = null, + CancellationToken cancellationToken = default + ) + { + HttpContent httpContent; + + switch (method) + { + case RequestMethod.GET: + var getResponse = await httpClient.GetAsync(uri, cancellationToken); + + return new HttpResponseEntity(getResponse.Content.ReadAsStreamAsync(), getResponse.StatusCode); + case RequestMethod.POST: + httpContent = ConvertNameValueCollectionToHttpContent(body, files); + var postResponse = await httpClient.PostAsync(uri, httpContent, cancellationToken); + + return new HttpResponseEntity(postResponse.Content.ReadAsStreamAsync(), postResponse.StatusCode); + case RequestMethod.PUT: + httpContent = ConvertNameValueCollectionToHttpContent(body, files); + var putResponse = await httpClient.PutAsync(uri, httpContent, cancellationToken); + + return new HttpResponseEntity(putResponse.Content.ReadAsStreamAsync(), putResponse.StatusCode); + case RequestMethod.DELETE: + var deleteResult = await httpClient.DeleteAsync(uri, cancellationToken); + + return new HttpResponseEntity(deleteResult.Content.ReadAsStreamAsync(), deleteResult.StatusCode); + default: + throw new ArgumentOutOfRangeException(nameof(method), method, null); + } + } + + private static HttpContent ConvertNameValueCollectionToHttpContent( + NameValueCollection collection, + Dictionary files = null + ) + { + var contentCollectionKeys = collection.AllKeys; + + var contentCollection = contentCollectionKeys + .Select(key => new KeyValuePair(key, collection[key])) + .ToList(); + var formUrlEncodedContent = new FormUrlEncodedContent(contentCollection); + + if (files == null) return formUrlEncodedContent; + + var multipartContent = new MultipartFormDataContent(); + + foreach (var keyValuePair in contentCollection) + multipartContent.Add(new StringContent(keyValuePair.Value), keyValuePair.Key); + + files + .ToList() + .ForEach(pair => multipartContent.Add(new StreamContent(pair.Value), "file", pair.Key)); + + return multipartContent; + } + } +} diff --git a/smsapi/Properties/AssemblyInfo.cs b/smsapi/Properties/AssemblyInfo.cs index 721a9d9..0aec68e 100644 --- a/smsapi/Properties/AssemblyInfo.cs +++ b/smsapi/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -8,9 +7,9 @@ [assembly: AssemblyTitle("libsmsapi")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("comvision")] +[assembly: AssemblyCompany("LINK Mobility Poland")] [assembly: AssemblyProduct("libsmsapi")] -[assembly: AssemblyCopyright("Copyright © comvision 2013")] +[assembly: AssemblyCopyright("Copyright © LINK Mobility Poland 2023")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.*")] -[assembly: AssemblyFileVersion("2.0.0.0")] +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] diff --git a/smsapi/Properties/Resources.Designer.cs b/smsapi/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d5817d9 --- /dev/null +++ b/smsapi/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace smsapi.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("smsapi.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/smsapi/Properties/Resources.resx b/smsapi/Properties/Resources.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/smsapi/Properties/Resources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/smsapi/Proxy.cs b/smsapi/Proxy.cs index f332f43..693593b 100644 --- a/smsapi/Proxy.cs +++ b/smsapi/Proxy.cs @@ -1,17 +1,53 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; - -namespace SMSApi.Api -{ - public enum RequestMethod { GET, POST, PUT, DELETE }; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Threading; +using System.Threading.Tasks; - public interface Proxy - { - Stream Execute(string uri, NameValueCollection data, RequestMethod method = RequestMethod.POST); - Stream Execute(string uri, NameValueCollection data, Stream file, RequestMethod method = RequestMethod.POST); - Stream Execute(string uri, NameValueCollection data, Dictionary files, RequestMethod method = RequestMethod.POST); - - void Authentication(IClient client); - } -} +namespace SMSApi.Api +{ + public interface Proxy + { + void Authentication(IClient client); + + HttpResponseEntity Execute( + string uri, + NameValueCollection data, + RequestMethod method); + + HttpResponseEntity Execute( + string uri, + NameValueCollection data, + Stream file, + RequestMethod method); + + HttpResponseEntity Execute( + string uri, + NameValueCollection data, + Dictionary files, + RequestMethod method); + + Task ExecuteAsync( + string uri, + NameValueCollection data, + RequestMethod method, + CancellationToken cancellationToken = default + ); + + Task ExecuteAsync( + string uri, + NameValueCollection data, + Stream file, + RequestMethod method, + CancellationToken cancellationToken = default + ); + + Task ExecuteAsync( + string uri, + NameValueCollection data, + Dictionary files, + RequestMethod method, + CancellationToken cancellationToken = default + ); + } +} diff --git a/smsapi/ProxyAddress.cs b/smsapi/ProxyAddress.cs index b262b03..99d86a9 100644 --- a/smsapi/ProxyAddress.cs +++ b/smsapi/ProxyAddress.cs @@ -1,15 +1,37 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace SMSApi.Api +namespace SMSApi.Api { public enum ProxyAddress { + SmsApiIo, SmsApiPl, BackupSmsApiPl, SmsApiCom, BackupSmsApiCom } + + public static class ProxyAddressExtensions + { + public static string GetUrl(this ProxyAddress proxy) + { + switch (proxy) + { + case ProxyAddress.SmsApiIo: + return "https://smsapi.io/"; + + case ProxyAddress.SmsApiPl: + return "https://api.smsapi.pl/"; + + case ProxyAddress.BackupSmsApiPl: + return "https://api2.smsapi.pl/"; + + case ProxyAddress.SmsApiCom: + return "https://api.smsapi.com/"; + + case ProxyAddress.BackupSmsApiCom: + return "https://api2.smsapi.com/"; + } + + throw new ProxyException("Proxy address does not exist."); + } + } } diff --git a/smsapi/ProxyException.cs b/smsapi/ProxyException.cs index 153299d..144705e 100644 --- a/smsapi/ProxyException.cs +++ b/smsapi/ProxyException.cs @@ -1,9 +1,13 @@ - -namespace SMSApi.Api +namespace SMSApi.Api { - public class ProxyException : SMSApi.Api.Exception + public class ProxyException : Exception { - public ProxyException(string message) : base(message) { } - public ProxyException(string message, System.Exception inner) : base(message, inner) { } + public ProxyException(string message) + : base(message) + { } + + public ProxyException(string message, System.Exception inner) + : base(message, inner) + { } } } diff --git a/smsapi/ProxyHTTP.cs b/smsapi/ProxyHTTP.cs index 374d7af..b09decf 100644 --- a/smsapi/ProxyHTTP.cs +++ b/smsapi/ProxyHTTP.cs @@ -1,201 +1,119 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Net; -using System.Security.Authentication; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; namespace SMSApi.Api { public class ProxyHTTP : Proxy { - //private const SecurityProtocolType _Tls11 = (SecurityProtocolType)0x00000300; - private const SecurityProtocolType _Tls12 = (SecurityProtocolType)0x00000C00; + private readonly string baseUrl; + private IClient authentication; - protected string baseUrl; - IClient authentication; - - public ProxyHTTP(string baseUrl) + public ProxyHTTP(string baseUrl) { this.baseUrl = baseUrl; } - protected Stream PrepareContent(NameValueCollection data) + public void Authentication(IClient client) { - Stream stream = new MemoryStream(); - - IEnumerator enumerator = data.GetEnumerator(); - - enumerator.Reset(); - - int count = data.Keys.Count; - - foreach (string key in data.Keys) - { - String param = Uri.EscapeDataString(key) + "=" + Uri.EscapeDataString(data[key]) + "&"; - byte[] bytes = System.Text.Encoding.UTF8.GetBytes(param); - stream.Write(bytes, 0, bytes.Length); - } - - if (stream.Length > 0) - { - //remove the "&" at the end - stream.SetLength(stream.Length - 1); - } - - stream.Position = 0; - - return stream; + authentication = client; } - protected Stream PrepareMultipartContent(string boundary, NameValueCollection data, Dictionary files) + public HttpResponseEntity Execute(string uri, NameValueCollection data, RequestMethod method) { - Stream stream = new MemoryStream(); + return Execute(uri, data, new Dictionary(), method); + } - IEnumerator enumerator = data.GetEnumerator(); + public HttpResponseEntity Execute( + string uri, + NameValueCollection data, + Stream file, + RequestMethod method) + { + return Execute(uri, data, new Dictionary { { "file", file } }, method); + } - enumerator.Reset(); + public HttpResponseEntity Execute( + string uri, + NameValueCollection data, + Dictionary files, + RequestMethod method) + { + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - String template = Environment.NewLine + "--" + boundary + Environment.NewLine + "Content-Disposition: form-data; name=\"{0}\";" + Environment.NewLine + Environment.NewLine + "{1}"; + HttpClient client = CreateClient(); - foreach (string key in data.Keys) + try { - string param = string.Format(template, key, data[key]); - byte[] bytes = System.Text.Encoding.UTF8.GetBytes(param); - stream.Write(bytes, 0, bytes.Length); + return client.SendRequest(method, uri, data, files).Result; } - - template = - Environment.NewLine + "--" + boundary + Environment.NewLine + - "Content-Disposition: form-data; name=\"{0}\"; filename=\"{0}\"" + Environment.NewLine + - "Content-Type: application/octet-stream" + Environment.NewLine + Environment.NewLine; - - foreach( KeyValuePair file in files ) + catch (System.Exception e) { - string param = string.Format(template, file.Key); - byte[] bytes = System.Text.Encoding.UTF8.GetBytes(param); - stream.Write(bytes, 0, bytes.Length); - - Stream fileStream = file.Value; - fileStream.Position = 0; - byte[] buffer = new byte[1024]; - int bytesRead = 0; - - while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) - { - stream.Write(buffer, 0, bytesRead); - } + throw new ProxyException("Failed to get response from " + uri, e); } - - byte[] footBytes = System.Text.Encoding.UTF8.GetBytes(Environment.NewLine + "--" + boundary + "--"); - stream.Write(footBytes, 0, footBytes.Length); - - stream.Position = 0; - - return stream; } - public Stream Execute(string uri, NameValueCollection data, RequestMethod method = RequestMethod.POST) + public async Task ExecuteAsync( + string uri, + NameValueCollection data, + RequestMethod method, + CancellationToken cancellationToken = default + ) { - Dictionary files = new Dictionary(); - return Execute(uri, data, files, method); + return await ExecuteAsync(uri, data, new Dictionary(), method); } - public Stream Execute(string uri, NameValueCollection data, System.IO.Stream file, RequestMethod method = RequestMethod.POST) + public async Task ExecuteAsync( + string uri, + NameValueCollection data, + Stream file, + RequestMethod method, + CancellationToken cancellationToken = default + ) { - Dictionary files = new Dictionary(); - files.Add("file", file); - return Execute(uri, data, files, method); + return await ExecuteAsync(uri, data, new Dictionary { { "file", file } }, method); } - public Stream Execute(string uri, NameValueCollection data, Dictionary files, RequestMethod method = RequestMethod.POST) - { - String boundary = "SMSAPI-" + DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss") + (new Random()).Next(int.MinValue, int.MaxValue).ToString() + "-boundary"; - - ServicePointManager.SecurityProtocol = _Tls12; - WebRequest webRequest = WebRequest.Create(baseUrl + uri); - webRequest.Method = RequestMethodToString(method); - - if (authentication != null) - { - webRequest.Headers.Add("Authorization", authentication.GetAuthenticationHeader()); - } - - if (RequestMethod.POST.Equals(method) || RequestMethod.PUT.Equals(method)) - { - Stream stream; - - if (files != null && files.Count > 0) - { - webRequest.ContentType = "multipart/form-data; boundary=" + boundary; - stream = PrepareMultipartContent(boundary, data, files); - } - else - { - webRequest.ContentType = "application/x-www-form-urlencoded"; - stream = PrepareContent(data); - } - - webRequest.ContentLength = stream.Length; - - try - { - stream.Position = 0; - CopyStream(stream, webRequest.GetRequestStream()); - stream.Close(); - } - catch (System.Net.WebException e) - { - throw new ProxyException(e.Message, e); - } - } - - MemoryStream response = new MemoryStream(); - - try - { - CopyStream(webRequest.GetResponse().GetResponseStream(), response); - } - catch (System.Net.WebException e) - { - throw new ProxyException("Failed to get response from " + webRequest.RequestUri.ToString(), e); - } + public async Task ExecuteAsync( + string uri, + NameValueCollection data, + Dictionary files, + RequestMethod method, + CancellationToken cancellationToken = default + ) + { + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; - response.Position = 0; - return response; - } + HttpClient client = CreateClient(); - private void CopyStream(Stream input, Stream output) - { - byte[] buffer = new byte[2048]; - int read; - while ((read = input.Read(buffer, 0, buffer.Length)) > 0) + try { - output.Write(buffer, 0, read); + return await client.SendRequest(method, uri, data, files, cancellationToken); + } + catch (System.Exception e) + { + throw new ProxyException("Failed to get response from " + uri, e); } } + + private HttpClient CreateClient() + { + var client = new HttpClient(); + client.BaseAddress = new Uri(baseUrl); + client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", authentication.GetClientAgent()); - public void Authentication(IClient client) - { - authentication = client; - } + if (authentication == null) return client; + + var authHeader = authentication.DefaultRequestHeaders; + + client.DefaultRequestHeaders.Add(authHeader.Key, authHeader.Value); - public static string RequestMethodToString(RequestMethod method) - { - switch(method) - { - case RequestMethod.GET: - return "GET"; - case RequestMethod.PUT: - return "PUT"; - case RequestMethod.POST: - return "POST"; - case RequestMethod.DELETE: - return "DELETE"; - default: - throw new ProxyException("Invalid request method"); - } + return client; } } } diff --git a/smsapi/RequestMethod.cs b/smsapi/RequestMethod.cs new file mode 100644 index 0000000..22503b3 --- /dev/null +++ b/smsapi/RequestMethod.cs @@ -0,0 +1,10 @@ +namespace SMSApi.Api +{ + public enum RequestMethod + { + GET, + POST, + PUT, + DELETE, + } +} diff --git a/smsapi/SmsapiException.cs b/smsapi/SmsapiException.cs index c5ce93c..544d3fc 100644 --- a/smsapi/SmsapiException.cs +++ b/smsapi/SmsapiException.cs @@ -1,23 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace SMSApi.Api +namespace SMSApi.Api { - public class SmsapiException : SMSApi.Api.Exception + public class SmsapiException : Exception { - private int Code; - - public SmsapiException(string message, int code) - : base(message) - { - Code = code; - } - - public int GetCode() + protected SmsapiException(string message, string code) : base(message) { - return Code; + Code = code; } + + public string Code { get; private set; } } } diff --git a/smsapi/docs/LICENSE.md b/smsapi/docs/LICENSE.md new file mode 100644 index 0000000..c7d575e --- /dev/null +++ b/smsapi/docs/LICENSE.md @@ -0,0 +1,13 @@ +Copyright 2023 SMSAPI + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/smsapi/docs/README.md b/smsapi/docs/README.md new file mode 100644 index 0000000..2bd2fd8 --- /dev/null +++ b/smsapi/docs/README.md @@ -0,0 +1,107 @@ +csharp-client +=========== + +SMSAPI C# client may be used by SMSAPI clients. + +## How to pick a service? + +### *SMSAPI.IO* (default) + +```c# +var smsApi = new SMSApi.Api.SMSFactory(client); +//or +var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiIo); +``` + +### *SMSAPI.PL* + +```c# +var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiPl); +``` + +### *SMSAPI.COM* + +```c# +var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiCom); +``` + + +### Example + +```c# +try +{ + SMSApi.Api.IClient client = new SMSApi.Api.ClientOAuth("token"); + + var smsApi = new SMSApi.Api.SMSFactory(client); + // for SMSAPI.com clients: + // var smsApi = new SMSApi.Api.SMSFactory(client, ProxyAddress.SmsApiCom); + + var result = + smsApi.ActionSend() + .SetText("test message") + .SetTo("0000000000") + .SetSender("Test") //Sender name + .Execute(); + + System.Console.WriteLine("Send: " + result.Count); + + string[] ids = new string[result.Count]; + + for (int i = 0, l = 0; i < result.List.Count; i++) + { + if (!result.List[i].isError()) + { + if (!result.List[i].isFinal()) + { + ids[l] = result.List[i].ID; + l++; + } + } + } + + System.Console.WriteLine("Get:"); + result = + smsApi.ActionGet() + .Ids(ids) + .Execute(); + + foreach (var status in result.List) + { + System.Console.WriteLine("ID: " + status.ID + " Number: " + status.Number + " Points:" + status.Points + " Status:" + status.Status + " IDx: " + status.IDx); + } +} +catch (SMSApi.Api.ActionException e) +{ + /** + * Action error + */ + System.Console.WriteLine(e.Message); +} +catch (SMSApi.Api.ClientException e) +{ + /** + * Error codes (list available in smsapi docs). Example: + * 101 Invalid authorization info + * 102 Invalid username or password + * 103 Insufficient credits on Your account + * 104 No such template + * 105 Wrong IP address (for IP filter turned on) + * 110 Action not allowed for your account + */ + System.Console.WriteLine(e.Message); +} +catch (SMSApi.Api.HostException e) +{ + /* + * Server errors + * SMSApi.Api.HostException.E_JSON_DECODE - problem with parsing data + */ + System.Console.WriteLine(e.Message); +} +catch (SMSApi.Api.ProxyException e) +{ + // communication problem between client and sever + System.Console.WriteLine(e.Message); +} +``` diff --git a/smsapi/docs/icons/logo.jpg b/smsapi/docs/icons/logo.jpg new file mode 100644 index 0000000..4167b63 Binary files /dev/null and b/smsapi/docs/icons/logo.jpg differ diff --git a/smsapi/smsapi.csproj b/smsapi/smsapi.csproj index b99a7be..e26208e 100644 --- a/smsapi/smsapi.csproj +++ b/smsapi/smsapi.csproj @@ -1,33 +1,58 @@  - - 8.0.30703 - 2.0 - net35;netcoreapp2.0;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1;netstandard2.0;netstandard2.1 - false - false - - - SMSAPI.pl - 1.0.0 - false - https://github.com/smsapi/smsapi-php-client/blob/master/LICENSE - https://www.smsapi.pl - SMSAPI Client that allows to send SMS, MMS, VMS and manage your SMSAPI account. - SMSAPI Client that allows to send SMS, MMS, VMS and manage your SMSAPI account. - smsapi - - - - - - - - - - - - - - - \ No newline at end of file + + 8.0.30703 + 2.0 + netcoreapp3.1;net5.0;net6.0;net7.0 + false + false + 9.0 + SMSAPI + SMSAPI + SMSAPI + https://github.com/smsapi/smsapi-csharp-client + git + SMSAPI + SMSAPI + README.md + logo.jpg + + + SMSAPI.pl + 3.0.0 + false + MIT + https://www.smsapi.com + SMSAPI Client that allows to send SMS, MMS, VMS and manage your SMSAPI account. + SMSAPI Client that allows to send SMS, MMS, VMS and manage your SMSAPI account. + smsapi;sms;marketing;shipment;mms;vms;message + net6.0;net7.0;netcoreapp3.1 + True + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + diff --git a/smsapiTests/App.Config.example b/smsapiTests/App.Config.example deleted file mode 100644 index 0ad707e..0000000 --- a/smsapiTests/App.Config.example +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/smsapiTests/App.config b/smsapiTests/App.config new file mode 100644 index 0000000..8140d5f --- /dev/null +++ b/smsapiTests/App.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/smsapiTests/AuthorizationType.cs b/smsapiTests/AuthorizationType.cs deleted file mode 100644 index f00521c..0000000 --- a/smsapiTests/AuthorizationType.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SMSApi.Api.Tests -{ - public enum AuthorizationType - { - basic, - oauth - } -} diff --git a/smsapiTests/ConfigurationTest.cs b/smsapiTests/ConfigurationTest.cs index 25ed25f..a23416f 100644 --- a/smsapiTests/ConfigurationTest.cs +++ b/smsapiTests/ConfigurationTest.cs @@ -1,44 +1,30 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SMSApi.Api; -using System; -using System.Collections.Generic; +using System; using System.Configuration; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; -namespace SMSApi.Api.Tests +namespace smsapiTests; + +[TestClass] +public class ConfigurationTest { - [TestClass()] - public class ConfigurationTest + [TestMethod] + public void VerifyConfiguration() { - [TestMethod()] - public void VerifyConfiguration() - { - var authorizationType = ConfigurationManager.AppSettings["authorizationType"]; - if (authorizationType == AuthorizationType.basic.ToString()) - { - string password = ConfigurationManager.AppSettings["password"]; - Assert.IsNotNull(password); - Assert.AreNotEqual("", password); - } - else if (authorizationType == AuthorizationType.oauth.ToString()) - { - string token = ConfigurationManager.AppSettings["oauthToken"]; - Assert.IsNotNull(token); - Assert.AreNotEqual("", token); - } - - string username = ConfigurationManager.AppSettings["username"]; - Assert.IsNotNull(username); - Assert.AreNotEqual("", username); + ExeConfigurationFileMap map = new(); + map.ExeConfigFilename = "testhost.dll.config"; + Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); + + var token = ConfigurationManager.AppSettings["oauthToken"]; + Assert.IsNotNull(token); + Assert.AreNotEqual("", token); - var validTestNumber = ConfigurationManager.AppSettings["validTestNumber"]; - Assert.IsNotNull(validTestNumber); - Assert.AreNotEqual("", validTestNumber); + var validTestNumber = ConfigurationManager.AppSettings["validTestNumber"]; + Assert.IsNotNull(validTestNumber); + Assert.AreNotEqual("", validTestNumber); - ProxyAddress proxy; - Assert.IsTrue(Enum.TryParse(ConfigurationManager.AppSettings["addressType"], out proxy)); - } + ProxyAddress proxy; + Assert.IsTrue(Enum.TryParse(ConfigurationManager.AppSettings["addressType"], out proxy)); } -} \ No newline at end of file +} + diff --git a/smsapiTests/Contacts/ContactsTest.cs b/smsapiTests/Contacts/ContactsTest.cs index 5663b0f..3c62083 100644 --- a/smsapiTests/Contacts/ContactsTest.cs +++ b/smsapiTests/Contacts/ContactsTest.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace smsapiTests.Contacts { @@ -9,57 +10,38 @@ public class ContactsTest : ContactsTestBase private Contact _contact; private Group _group; - [TestInitialize] - public override void SetUp() + [TestMethod] + public void BindContactToGroup() { - base.SetUp(); + ErrorAwareResponse response = _factory.BindContactToGroup(_contact.Id, _group.Id).Execute(); + Assert.IsFalse(response.IsError()); - var contactsResponse = _factory.ListContacts().SetPhoneNumber(_validTestNumber).Execute(); - if (contactsResponse.Collection.Count > 0) - _contact = contactsResponse.Collection[0]; - else - _contact = _factory.CreateContact().SetPhoneNumber(_validTestNumber).Execute(); - - var groupsResponse = _factory.ListGroups().SetName("exampleGroup").Execute(); - if (groupsResponse.Collection.Count > 0) - _group = groupsResponse.Collection[0]; - else - _group = _factory.CreateGroup().SetName("exampleGroup").Execute(); + _factory.DeleteGroup(_group.Id).Execute(); } [TestCleanup] public void Cleanup() { - var contactsResponse = _factory.ListContacts().SetPhoneNumber(_validTestNumber).Execute(); - foreach (var contact in contactsResponse.Collection) + SMSApi.Api.Response.Contacts contactsResponse = + _factory.ListContacts().SetPhoneNumber(_validTestNumber).Execute(); + foreach (Contact contact in contactsResponse.Collection) { _factory.DeleteContact(contact.Id).Execute(); } - var groups = _factory.ListGroups().Execute(); - foreach (var group in groups.Collection) + Groups groups = _factory.ListGroups().Execute(); + foreach (Group group in groups.Collection) { _factory.DeleteGroup(group.Id).Execute(); } } - [TestMethod] - public void BindContactToGroup() - { - var response = _factory.BindContactToGroup(_contact.Id, _group.Id).Execute(); - Assert.IsFalse(response.isError()); - - _factory.DeleteGroup(_group.Id).Execute(); - } - [TestMethod] public void CreateContact() { Cleanup(); - var createdContact = _factory.CreateContact() - .SetPhoneNumber(_validTestNumber) - .Execute(); + Contact createdContact = _factory.CreateContact().SetPhoneNumber(_validTestNumber).Execute(); Assert.IsNotNull(createdContact); Assert.AreEqual(_validTestNumber, createdContact.PhoneNumber); @@ -68,9 +50,7 @@ public void CreateContact() [TestMethod] public void EditContact() { - var editContact = _factory.EditContact(_contact.Id) - .SetFirstName("Tester") - .Execute(); + Contact editContact = _factory.EditContact(_contact.Id).SetFirstName("Tester").Execute(); Assert.AreEqual(_contact.Id, editContact.Id); Assert.AreEqual("Tester", editContact.FirstName); @@ -79,23 +59,17 @@ public void EditContact() [TestMethod] public void GetContact() { - var getResponse = _factory.GetContact(_contact.Id).Execute(); + Contact getResponse = _factory.GetContact(_contact.Id).Execute(); Assert.AreEqual(_contact.PhoneNumber, getResponse.PhoneNumber); } - [TestMethod] - public void ListContacts() - { - _factory.ListContacts().Execute(); - } - [TestMethod] public void GetContactGroup() { _factory.BindContactToGroup(_contact.Id, _group.Id).Execute(); - var groupResponse = _factory.GetContactGroup(_contact.Id, _group.Id).Execute(); + Group groupResponse = _factory.GetContactGroup(_contact.Id, _group.Id).Execute(); Assert.AreEqual(_group.Id, groupResponse.Id); } @@ -105,10 +79,43 @@ public void ListContactGroups() { _factory.BindContactToGroup(_contact.Id, _group.Id).Execute(); - var groupsResponse = _factory.ListContactGroups(_contact.Id).Execute(); + Groups groupsResponse = _factory.ListContactGroups(_contact.Id).Execute(); Assert.AreEqual(1, groupsResponse.Collection.Count); Assert.AreEqual(_group.Id, groupsResponse.Collection[0].Id); } + + [TestMethod] + public void ListContacts() + { + _factory.ListContacts().Execute(); + } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + + SMSApi.Api.Response.Contacts contactsResponse = + _factory.ListContacts().SetPhoneNumber(_validTestNumber).Execute(); + if (contactsResponse.Collection.Count > 0) + { + _contact = contactsResponse.Collection[0]; + } + else + { + _contact = _factory.CreateContact().SetPhoneNumber(_validTestNumber).Execute(); + } + + Groups groupsResponse = _factory.ListGroups().SetName("exampleGroup").Execute(); + if (groupsResponse.Collection.Count > 0) + { + _group = groupsResponse.Collection[0]; + } + else + { + _group = _factory.CreateGroup().SetName("exampleGroup").Execute(); + } + } } } diff --git a/smsapiTests/Contacts/ContactsTestBase.cs b/smsapiTests/Contacts/ContactsTestBase.cs index af55dde..9de8369 100644 --- a/smsapiTests/Contacts/ContactsTestBase.cs +++ b/smsapiTests/Contacts/ContactsTestBase.cs @@ -1,10 +1,5 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace smsapiTests.Contacts { diff --git a/smsapiTests/Contacts/FieldsTest.cs b/smsapiTests/Contacts/FieldsTest.cs index 6f24f39..e5e07f1 100644 --- a/smsapiTests/Contacts/FieldsTest.cs +++ b/smsapiTests/Contacts/FieldsTest.cs @@ -8,21 +8,11 @@ public class FieldsTest : ContactsTestBase { private Field _field; - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - _field = _factory.CreateField() - .SetName("FieldX") - .SetType(Field.TextType) - .Execute(); - } - [TestCleanup] public void Cleanup() { - var fields = _factory.ListFields().Execute(); - foreach (var field in fields.Collection) + Fields fields = _factory.ListFields().Execute(); + foreach (Field field in fields.Collection) { _factory.DeleteField(field.Id).Execute(); } @@ -31,10 +21,7 @@ public void Cleanup() [TestMethod] public void CreateField() { - _field = _factory.CreateField() - .SetName("FieldXX") - .SetType(Field.TextType) - .Execute(); + _field = _factory.CreateField().SetName("FieldXX").SetType(Field.TextType).Execute(); Assert.IsNotNull(_field.Id); Assert.AreEqual("FieldXX", _field.Name); @@ -43,9 +30,7 @@ public void CreateField() [TestMethod] public void EditField() { - var editedField = _factory.EditField(_field.Id) - .SetName("FieldY") - .Execute(); + Field editedField = _factory.EditField(_field.Id).SetName("FieldY").Execute(); Assert.IsNotNull(editedField.Id); Assert.AreEqual(_field.Id, editedField.Id); @@ -61,9 +46,9 @@ public void ListFieldOptions() [TestMethod] public void ListFields() { - var fields = _factory.ListFields().Execute(); + Fields fields = _factory.ListFields().Execute(); - foreach (var field in fields.Collection) + foreach (Field field in fields.Collection) { Assert.IsNotNull("", field.Name); Assert.AreNotEqual("", field.Name); @@ -71,5 +56,12 @@ public void ListFields() Assert.AreNotEqual("", field.Type); } } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _field = _factory.CreateField().SetName("FieldX").SetType(Field.TextType).Execute(); + } } } diff --git a/smsapiTests/Contacts/GroupsTest.cs b/smsapiTests/Contacts/GroupsTest.cs index 5465a13..0699bdb 100644 --- a/smsapiTests/Contacts/GroupsTest.cs +++ b/smsapiTests/Contacts/GroupsTest.cs @@ -8,19 +8,11 @@ public class GroupsTest : ContactsTestBase { private Group _group; - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - - _group = _factory.CreateGroup().SetName("exampleGroup").Execute(); - } - [TestCleanup] public void Cleanup() { - var groups = _factory.ListGroups().Execute(); - foreach (var group in groups.Collection) + Groups groups = _factory.ListGroups().Execute(); + foreach (Group group in groups.Collection) { _factory.DeleteGroup(group.Id).Execute(); } @@ -29,33 +21,82 @@ public void Cleanup() [TestMethod] public void CreateGroup() { - var group = _factory.CreateGroup().SetName("exampleGroup1").Execute(); + Group group = _factory.CreateGroup().SetName("exampleGroup1").Execute(); Assert.AreEqual("exampleGroup1", group.Name); Assert.IsNotNull(group.Id); } + [TestMethod] + public void CreateGroupPermission() + { + GroupPermission groupPermission = _factory.CreateGroupPermission(_group.Id). + SetUsername(_username). + SetRead(true). + SetWrite(false). + SetSend(false). + Execute(); + + Assert.AreEqual(_username, groupPermission.Username); + } + [TestMethod] public void EditGroup() { - var response = _factory.EditGroup(_group.Id).SetName("GroupY").Execute(); + Group response = _factory.EditGroup(_group.Id).SetName("GroupY").Execute(); Assert.AreEqual(_group.Id, response.Id); Assert.AreNotEqual(_group.Name, response.Name); Assert.AreEqual("GroupY", response.Name); - Assert.AreEqual(_group.Idx, response.Idx); Assert.AreEqual(_group.Description, response.Description); + + if (string.IsNullOrEmpty(_group.Idx)) + { + Assert.IsTrue(string.IsNullOrEmpty(response.Idx)); + } + else + { + Assert.AreEqual(_group.Idx, response.Idx); + } + } + + [TestMethod] + public void EditGroupPermission() + { + GroupPermission groupPermission = _factory.EditGroupPermission(_group.Id, _username). + SetRead(true). + SetWrite(true). + SetSend(true). + Execute(); + + Assert.IsTrue(groupPermission.Read); + Assert.IsTrue(groupPermission.Write); + Assert.IsTrue(groupPermission.Send); } [TestMethod] public void GetGroup() { - var response = _factory.GetGroup(_group.Id).Execute(); + Group response = _factory.GetGroup(_group.Id).Execute(); Assert.AreEqual(_group.Id, response.Id); Assert.AreEqual(_group.Name, response.Name); - Assert.AreEqual(_group.Idx, response.Idx); Assert.AreEqual(_group.Description, response.Description); + + if (string.IsNullOrEmpty(_group.Idx)) + { + Assert.IsTrue(string.IsNullOrEmpty(response.Idx)); + } + else + { + Assert.AreEqual(_group.Idx, response.Idx); + } + } + + [TestMethod] + public void ListGroupPermissions() + { + _factory.ListGroupPermissions(_group.Id).Execute(); } [TestMethod] @@ -67,7 +108,7 @@ public void ListGroups() [TestMethod] public void ListGroupsWithFilterByName() { - var listResponse = _factory.ListGroups().SetName("exampleGroup").Execute(); + Groups listResponse = _factory.ListGroups().SetName("exampleGroup").Execute(); Assert.AreEqual(1, listResponse.Collection.Count); } @@ -75,42 +116,17 @@ public void ListGroupsWithFilterByName() [TestMethod] public void ListWithFilterByName_ShouldNotFound() { - var listResponse = _factory.ListGroups().SetName("missingGroup").Execute(); + Groups listResponse = _factory.ListGroups().SetName("missingGroup").Execute(); Assert.AreEqual(0, listResponse.Collection.Count); } - [TestMethod] - public void CreateGroupPermission() - { - var groupPermission = _factory.CreateGroupPermission(_group.Id) - .SetUsername(_username) - .SetRead(true) - .SetWrite(false) - .SetSend(false) - .Execute(); - - Assert.AreEqual(_username, groupPermission.Username); - } - - [TestMethod] - public void EditGroupPermission() + [TestInitialize] + public override void SetUp() { - var groupPermission = _factory.EditGroupPermission(_group.Id, _username) - .SetRead(true) - .SetWrite(true) - .SetSend(true) - .Execute(); - - Assert.IsTrue(groupPermission.Read); - Assert.IsTrue(groupPermission.Write); - Assert.IsTrue(groupPermission.Send); - } + base.SetUp(); - [TestMethod] - public void ListGroupPermissions() - { - _factory.ListGroupPermissions(_group.Id).Execute(); + _group = _factory.CreateGroup().SetName("exampleGroup").Execute(); } } } diff --git a/smsapiTests/HlrTest.cs b/smsapiTests/HlrTest.cs index e0a432d..80e60dd 100644 --- a/smsapiTests/HlrTest.cs +++ b/smsapiTests/HlrTest.cs @@ -1,8 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using SMSApi.Api.Tests; -using System; -using System.Configuration; +using SMSApi.Api.Response; namespace smsapiTests { @@ -11,20 +9,20 @@ public class HlrTest : TestBase { private HLRFactory _factory; - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - _factory = new HLRFactory(_client, _proxyAddress); - } - [TestMethod] public void CheckNumber() { - var response = _factory.ActionCheckNumber(_validTestNumber).Execute(); + CheckNumber response = _factory.ActionCheckNumber(_validTestNumber).Execute(); Assert.AreEqual(1, response.List.Count); Assert.IsNotNull(response.List[0].ID); } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new HLRFactory(_client, _proxyAddress); + } } } diff --git a/smsapiTests/Integration/Authorization/HttpClientAuthenticationTest.cs b/smsapiTests/Integration/Authorization/HttpClientAuthenticationTest.cs new file mode 100644 index 0000000..4449fc9 --- /dev/null +++ b/smsapiTests/Integration/Authorization/HttpClientAuthenticationTest.cs @@ -0,0 +1,28 @@ +using System; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; + +namespace smsapiTests.Integration.Authorization; + +[TestClass] +public class HttpClientAuthenticationTest : IntegrationTestBase +{ + [TestMethod] + public void request_contains_oauth_authentication_header() + { + var token = "any token"; + var client = new ClientOAuth(token); + var smsFactory = new SMSFactory(client, GetProxy()); + + SendAnyMessage(smsFactory); + + var expectedAuthHeader = $"Bearer {token}"; + RequestAssert.AssertContainsAuthorizationHeader(expectedAuthHeader); + } + + private static void SendAnyMessage(SMSFactory smsFactory) + { + SendActionHelper.SendAnySms(smsFactory); + } +} diff --git a/smsapiTests/Integration/IntegrationTestBase.cs b/smsapiTests/Integration/IntegrationTestBase.cs new file mode 100644 index 0000000..e6dcabd --- /dev/null +++ b/smsapiTests/Integration/IntegrationTestBase.cs @@ -0,0 +1,59 @@ +using System.Net; +using System.Net.Sockets; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; + +namespace smsapiTests.Integration; + +public abstract class IntegrationTestBase +{ + private static string _currentHost; + + [TestInitialize] + public void InitializeServer() + { + RunTestServer(); + } + + private static void RunTestServer() + { + _currentHost = FreeHost(); + + new WebHostBuilder() + .UseKestrel() + .UseStartup(typeof(Program)) + .UseUrls(_currentHost) + .Configure(app => app.UseMiddleware()) + .Build() + .Start(); + } + + protected static ProxyHTTP GetProxy() + { + return new ProxyHTTP(_currentHost); + } + + private static string FreeHost() + { + TcpListener l = new TcpListener(IPAddress.Loopback, 0); + l.Start(); + int port = ((IPEndPoint)l.LocalEndpoint).Port; + l.Stop(); + + return $"http://localhost:{port}"; + } +} + +public class Program +{ + public Program(IConfiguration config) + { + } + + public static void Configure(IApplicationBuilder applicationBuilder) + { + } +} diff --git a/smsapiTests/Integration/Metrics/UserAgentTest.cs b/smsapiTests/Integration/Metrics/UserAgentTest.cs new file mode 100644 index 0000000..8760363 --- /dev/null +++ b/smsapiTests/Integration/Metrics/UserAgentTest.cs @@ -0,0 +1,19 @@ + +using System; +using System.Reflection; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace smsapiTests.Integration.Metrics; + +[TestClass] +public class UserAgentTest : IntegrationTestBase +{ + [TestMethod] + public void request_contains_user_agent_header() + { + SendActionHelper.SendAnySms(GetProxy()); + + var expectedUserAgent = $"smsapi-csharp-client/{Assembly.GetExecutingAssembly().GetName().Version} {Environment.Version}"; + RequestAssert.AssertContainsUserAgentHeader(expectedUserAgent); + } +} diff --git a/smsapiTests/Integration/RequestAssert.cs b/smsapiTests/Integration/RequestAssert.cs new file mode 100644 index 0000000..5ed356d --- /dev/null +++ b/smsapiTests/Integration/RequestAssert.cs @@ -0,0 +1,33 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace smsapiTests.Integration; + +public static class RequestAssert +{ + public static void AssertContainsAuthorizationHeader(string value) + { + var headerExists = RequestStorage + .AuthorizationHeader + .Equals(value); + + Assert.IsTrue(headerExists, $"Found: {RequestStorage.AuthorizationHeader}"); + } + + public static void AssertContainsUserAgentHeader(string value) + { + var headerExists = RequestStorage + .UserAgentHeader + .Equals(value); + + Assert.IsTrue(headerExists, $"Expected {value}, Found: {RequestStorage.UserAgentHeader}"); + } + + public static void AsserPath(string path) + { + var pathEquals = RequestStorage + .Path + .Equals(path); + + Assert.IsTrue(pathEquals); + } +} diff --git a/smsapiTests/Integration/RequestInterceptorMiddleware.cs b/smsapiTests/Integration/RequestInterceptorMiddleware.cs new file mode 100644 index 0000000..2a71bea --- /dev/null +++ b/smsapiTests/Integration/RequestInterceptorMiddleware.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace smsapiTests.Integration; + +public class RequestInterceptorMiddleware +{ + private readonly RequestDelegate _next; + + public RequestInterceptorMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + RequestStorage.Method = context.Request.Method; + RequestStorage.AuthorizationHeader = context.Request.Headers.Authorization; + RequestStorage.UserAgentHeader = context.Request.Headers.UserAgent; + RequestStorage.Path = $"{context.Request.Scheme}://{context.Request.Host.Value}{context.Request.Path.Value}"; + + await _next(context); + } +} diff --git a/smsapiTests/Integration/RequestStorage.cs b/smsapiTests/Integration/RequestStorage.cs new file mode 100644 index 0000000..fd94ef8 --- /dev/null +++ b/smsapiTests/Integration/RequestStorage.cs @@ -0,0 +1,9 @@ +namespace smsapiTests.Integration; + +public static class RequestStorage +{ + public static string AuthorizationHeader; + public static string UserAgentHeader; + public static string Path; + public static string Method; +} diff --git a/smsapiTests/Integration/SendActionHelper.cs b/smsapiTests/Integration/SendActionHelper.cs new file mode 100644 index 0000000..80db9fc --- /dev/null +++ b/smsapiTests/Integration/SendActionHelper.cs @@ -0,0 +1,26 @@ +using System; +using SMSApi.Api; + +namespace smsapiTests.Integration; + +public static class SendActionHelper +{ + public static void SendAnySms(SMSFactory smsFactory) + { + try + { + smsFactory.ActionSend("48500100100", "any").Execute(); + } + catch (MissingMethodException) + { + } + } + + public static void SendAnySms(Proxy proxy) + { + var client = new ClientOAuth("any"); + var smsFactory = new SMSFactory(client, proxy); + + SendAnySms(smsFactory); + } +} diff --git a/smsapiTests/MmsTest.cs b/smsapiTests/MmsTest.cs index aac45f6..3462fe5 100644 --- a/smsapiTests/MmsTest.cs +++ b/smsapiTests/MmsTest.cs @@ -1,6 +1,7 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using System; +using SMSApi.Api.Response; namespace smsapiTests { @@ -9,40 +10,54 @@ public class MmsTest : TestBase { private MMSFactory _factory; - [TestInitialize] - public override void SetUp() + [TestMethod] + public void DeletingSentMessage_EmptyResponse() { - base.SetUp(); - _factory = new MMSFactory(_client, _proxyAddress); + Status sendResponse = + _factory.ActionSend(). + SetSubject("test subject"). + SetSmil( + ""). + SetTo(_validTestNumber). + Execute(); + + string[] ids = new string[sendResponse.Count]; + + for (int i = 0; i < sendResponse.List.Count; i++) + { + ids[i] = sendResponse.List[i].ID; + } + + Countable deletedResponse = _factory.ActionDelete().Ids(ids).Execute(); + + Assert.AreEqual(0, deletedResponse.Count); } [TestMethod] - public void Send_Get_Delete() + public void ScheduledSend_Get_Delete() { - var sendResponse = - _factory.ActionSend() - .SetSubject("test subject") - .SetSmil("") - .SetTo(_validTestNumber) - .SetDateSent(DateTime.Now.AddHours(2)) - .Execute(); + Status sendResponse = + _factory.ActionSend(). + SetSubject("test subject"). + SetSmil( + ""). + SetTo(_validTestNumber). + SetDateSent(DateTime.Now.AddHours(2)). + Execute(); Assert.AreEqual(1, sendResponse.Count); Assert.IsTrue(sendResponse.List[0].Points > 0, "Points must be greather then 0"); string[] ids = new string[sendResponse.Count]; - for (int i = 0, l = 0; i < sendResponse.List.Count; i++) + for (int i = 0; i < sendResponse.List.Count; i++) { - ids[l] = sendResponse.List[i].ID; - l++; + ids[i] = sendResponse.List[i].ID; } - System.Console.WriteLine("Get:"); - var getResponse = - _factory.ActionGet() - .Ids(ids) - .Execute(); + Console.WriteLine("Get:"); + Status getResponse = + _factory.ActionGet().Ids(ids).Execute(); Assert.AreEqual(sendResponse.Count, getResponse.Count); Assert.AreEqual(_validTestNumber, getResponse.List[0].Number); @@ -51,13 +66,17 @@ public void Send_Get_Delete() Assert.AreEqual(sendResponse.List[0].Points, getResponse.List[0].Points); Assert.AreEqual(sendResponse.List[0].Status, getResponse.List[0].Status); - var deletedResponse = - _factory - .ActionDelete() - .Ids(ids) - .Execute(); + Countable deletedResponse = + _factory.ActionDelete().Ids(ids).Execute(); Assert.AreEqual(sendResponse.Count, deletedResponse.Count); } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new MMSFactory(_client, _proxyAddress); + } } } diff --git a/smsapiTests/Properties/AssemblyInfo.cs b/smsapiTests/Properties/AssemblyInfo.cs index 7dc831f..49e4048 100644 --- a/smsapiTests/Properties/AssemblyInfo.cs +++ b/smsapiTests/Properties/AssemblyInfo.cs @@ -1,16 +1,15 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("smsapiTests")] +[assembly: AssemblyTitle("smsapiTests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("smsapiTests")] -[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("smsapiTests")] +[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +30,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.0.0")] -[assembly: AssemblyFileVersion("2.0.0.0")] +[assembly: AssemblyVersion("3.0.0.0")] +[assembly: AssemblyFileVersion("3.0.0.0")] diff --git a/smsapiTests/SenderTest.cs b/smsapiTests/SenderTest.cs index e079d76..0ce9b35 100644 --- a/smsapiTests/SenderTest.cs +++ b/smsapiTests/SenderTest.cs @@ -1,7 +1,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using System; -using System.Configuration; +using SMSApi.Api.Response; +using SMSApi.Api.Response.ResponseResolver; namespace smsapiTests { @@ -11,18 +11,21 @@ public class SenderTest : TestBase private SenderFactory _factory; private string _testName = "testName"; - [TestInitialize] - public override void SetUp() + [TestMethod] + public void Add_Delete() { - base.SetUp(); - _factory = new SenderFactory(_client, _proxyAddress); + ErrorAwareResponse addResponse = _factory.ActionAdd(_testName).Execute(); + Assert.IsFalse(addResponse.IsError(), addResponse.ErrorMessage); + + ErrorAwareResponse deleteResponse = _factory.ActionDelete(_testName).Execute(); + Assert.IsFalse(deleteResponse.IsError(), deleteResponse.ErrorMessage); } [TestMethod] public void List_Delete() { - var senders = _factory.ActionList().Execute(); - foreach (var sender in senders.List) + Array senders = _factory.ActionList().Execute(); + foreach (Sender sender in senders.List) { Assert.IsTrue(sender.Name.Length > 0); @@ -33,21 +36,11 @@ public void List_Delete() } } - [TestMethod] - public void Add_Delete() - { - var addResponse = _factory.ActionAdd(_testName).Execute(); - Assert.IsFalse(addResponse.isError(), addResponse.ErrorMessage); - - var deleteResponse = _factory.ActionDelete(_testName).Execute(); - Assert.IsFalse(deleteResponse.isError(), deleteResponse.ErrorMessage); - } - [TestMethod] public void SetDefault() { - var senders = _factory.ActionList().Execute(); - foreach (var sender in senders.List) + Array senders = _factory.ActionList().Execute(); + foreach (Sender sender in senders.List) { if ("ACTIVE".Equals(sender.Status) && !"Test".Equals(sender.Name)) { @@ -55,5 +48,12 @@ public void SetDefault() } } } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new SenderFactory(_client, _proxyAddress); + } } } diff --git a/smsapiTests/SmsTest.cs b/smsapiTests/SmsTest.cs index 7667c3e..938c664 100644 --- a/smsapiTests/SmsTest.cs +++ b/smsapiTests/SmsTest.cs @@ -1,6 +1,8 @@ using System; +using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; +using SMSApi.Api.Response; namespace smsapiTests { @@ -9,22 +11,31 @@ public class SmsTest : TestBase { private SMSFactory _factory; - [TestInitialize] - public override void SetUp() + [TestMethod] + public void DeletingSentMessage_ExceptionThrown() { - base.SetUp(); - _factory = new SMSFactory(_client, _proxyAddress); + Status sendResponse = + _factory.ActionSend().SetText("test message").SetTo(_validTestNumber).Execute(); + + string[] ids = new string[sendResponse.Count]; + + for (int i = 0; i < sendResponse.List.Count; i++) + { + ids[i] = sendResponse.List[i].ID; + } + + Assert.ThrowsException(() => _factory.ActionDelete().Id(ids[0]).Execute()); } [TestMethod] - public void Send_Get_Delete() + public void ScheduledSend_Get_Delete() { - var sendResponse = - _factory.ActionSend() - .SetText("test message") - .SetTo(_validTestNumber) - .SetDateSent(DateTime.Now.AddHours(2)) - .Execute(); + Status sendResponse = + _factory.ActionSend(). + SetText("test message"). + SetTo(_validTestNumber). + SetDateSent(DateTime.Now.AddHours(2)). + Execute(); Assert.AreEqual(1, sendResponse.Count); Assert.IsTrue(sendResponse.List[0].Points > 0, "Points must be greather then 0"); @@ -47,10 +58,8 @@ public void Send_Get_Delete() } } - var getResponse = - _factory.ActionGet() - .Ids(ids) - .Execute(); + Status getResponse = + _factory.ActionGet().Ids(ids).Execute(); Assert.AreEqual(sendResponse.Count, getResponse.Count); Assert.AreEqual(_validTestNumber, getResponse.List[0].Number); @@ -58,12 +67,9 @@ public void Send_Get_Delete() Assert.AreEqual(sendResponse.List[0].IDx, getResponse.List[0].IDx); Assert.AreEqual(sendResponse.List[0].Points, getResponse.List[0].Points); Assert.AreEqual(sendResponse.List[0].Status, getResponse.List[0].Status); - - var deletedResponse = - _factory - .ActionDelete() - .Id(ids[0]) - .Execute(); + + Countable deletedResponse = + _factory.ActionDelete().Id(ids[0]).Execute(); Assert.AreEqual(sendResponse.Count, deletedResponse.Count); } @@ -71,18 +77,25 @@ public void Send_Get_Delete() [TestMethod] public void SendMessageWithParams() { - var sendResponse = - _factory.ActionSend() - .SetText("test [%1%] message [%2%]") - .SetTo(_validTestNumber) - .SetParam(0, "par1") - .SetParam(1, "par2") - .SetTest(true) - .Execute(); + Status sendResponse = + _factory.ActionSend(). + SetText("test [%1%] message [%2%]"). + SetTo(_validTestNumber). + SetParam(0, "par1"). + SetParam(1, "par2"). + SetTest(). + Execute(); Assert.AreEqual(1, sendResponse.Count); Assert.IsTrue(sendResponse.List[0].Points > 0, "Points must be greather then 0"); Assert.IsNotNull(sendResponse.List[0].ID); } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new SMSFactory(_client, _proxyAddress); + } } } diff --git a/smsapiTests/TestBase.cs b/smsapiTests/TestBase.cs index bd998a7..0ee72dc 100644 --- a/smsapiTests/TestBase.cs +++ b/smsapiTests/TestBase.cs @@ -1,37 +1,26 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SMSApi.Api; -using SMSApi.Api.Tests; -using System; +using System; using System.Configuration; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; -namespace smsapiTests -{ - public abstract class TestBase - { - protected IClient _client; - protected ProxyAddress _proxyAddress; - protected string _validTestNumber; - protected string _username; - - [TestInitialize] - public virtual void SetUp() - { - var authorizationType = ConfigurationManager.AppSettings["authorizationType"]; - _username = ConfigurationManager.AppSettings["username"]; +namespace smsapiTests; - if (authorizationType == AuthorizationType.basic.ToString()) - { - var basicClient = new Client(_username); - basicClient.SetPasswordHash(ConfigurationManager.AppSettings["password"]); - _client = basicClient; - } - else if (authorizationType == AuthorizationType.oauth.ToString()) - { - _client = new ClientOAuth(ConfigurationManager.AppSettings["oauthToken"]); - } +public abstract class TestBase +{ + protected IClient _client; + protected ProxyAddress _proxyAddress; + protected string _username; + protected string _validTestNumber; - _proxyAddress = (ProxyAddress)Enum.Parse(typeof(ProxyAddress), ConfigurationManager.AppSettings["addressType"]); - _validTestNumber = ConfigurationManager.AppSettings["validTestNumber"]; - } + [TestInitialize] + public virtual void SetUp() + { + _client = new ClientOAuth(ConfigurationManager.AppSettings["oauthToken"]); + + _proxyAddress = (ProxyAddress)Enum.Parse( + typeof(ProxyAddress), + ConfigurationManager.AppSettings["addressType"]); + + _validTestNumber = ConfigurationManager.AppSettings["validTestNumber"]; } } diff --git a/smsapiTests/Unit/Action/MFA/CreateMFACodeResponseTest.cs b/smsapiTests/Unit/Action/MFA/CreateMFACodeResponseTest.cs new file mode 100644 index 0000000..ed3284b --- /dev/null +++ b/smsapiTests/Unit/Action/MFA/CreateMFACodeResponseTest.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action.MFA; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Action.MFA; + +[TestClass] +public class CreateMFACodeResponseTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void map_result_to_object() + { + var id = "5ADEF4DC3738305BEED02B0C"; + var code = "123456"; + var phoneNumber = "48500500500"; + var from = "Test"; + var response = new Dictionary + { + { + "id", id + }, + { + "code", code + }, + { + "phone_number", phoneNumber + }, + { + "from", from + }, + }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var result = CreateMfaCodeAction(GetAnyPhoneNumber()).Execute(); + + Assert.AreEqual(id, result.Id); + Assert.AreEqual(code, result.Code); + Assert.AreEqual(phoneNumber, result.PhoneNumber); + Assert.AreEqual(from, result.From); + } + + private static string GetAnyPhoneNumber() => "48500100100"; + + private CreateMFACode CreateMfaCodeAction(string phoneNumber) + { + var action = new CreateMFACode(phoneNumber); + action.Proxy(_proxyStub); + + return action; + } +} diff --git a/smsapiTests/Unit/Action/MFA/CreateMFACodeTest.cs b/smsapiTests/Unit/Action/MFA/CreateMFACodeTest.cs new file mode 100644 index 0000000..1312fee --- /dev/null +++ b/smsapiTests/Unit/Action/MFA/CreateMFACodeTest.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api.Action.MFA; + +namespace smsapiTests.Unit.Action.MFA; + +[TestClass] +public class CreateMFACodeTest +{ + private readonly SpyProxy _spyProxy = new(); + + [TestMethod] + public void valid_uri() + { + var phoneNumber = GetAnyPhoneNumber(); + + CreateMfaCodeAction(phoneNumber).Execute(); + + Assert.AreEqual("mfa/codes", _spyProxy.RequestedUri); + } + + [TestMethod] + public void request_contains_only_phone_number() + { + var phoneNumber = GetAnyPhoneNumber(); + + CreateMfaCodeAction(phoneNumber).Execute(); + + AssertParametersContain("phone_number", phoneNumber); + AssertParametersDoesNotContain("content"); + AssertParametersDoesNotContain("fast"); + AssertParametersDoesNotContain("from"); + } + + [TestMethod] + public void create_as_fast() + { + var create = CreateMfaCodeAction(GetAnyPhoneNumber()) + .AsFast(); + + create.Execute(); + + AssertParametersContain("fast", "1"); + } + + [TestMethod] + public void create_with_content() + { + var content = "any content"; + var create = CreateMfaCodeAction(GetAnyPhoneNumber()) + .WithContent(content); + + create.Execute(); + + AssertParametersContain("content", content); + } + + [TestMethod] + public void create_with_sendername() + { + var sendername = "abc"; + var create = CreateMfaCodeAction(GetAnyPhoneNumber()) + .FromSendername(sendername); + + create.Execute(); + + AssertParametersContain("from", sendername); + } + + private static string GetAnyPhoneNumber() => "48500100100"; + + private CreateMFACode CreateMfaCodeAction(string phoneNumber) + { + var action = new CreateMFACode(phoneNumber); + action.Proxy(_spyProxy); + + return action; + } + + private void AssertParametersContain(string name, string value) + { + var expectedParameter = new KeyValuePair(name, value); + + Assert.IsTrue( + _spyProxy.Parameters.Contains(expectedParameter), + $"Expected {value}, actual value: {_spyProxy.Parameters[name]}" + ); + } + + private void AssertParametersDoesNotContain(string name) + { + Assert.IsFalse( + _spyProxy.Parameters.ContainsKey(name), + $"Key not expected {name}" + ); + } +} diff --git a/smsapiTests/Unit/Action/MFA/VerifyMFACodeResponseTest.cs b/smsapiTests/Unit/Action/MFA/VerifyMFACodeResponseTest.cs new file mode 100644 index 0000000..9292fdb --- /dev/null +++ b/smsapiTests/Unit/Action/MFA/VerifyMFACodeResponseTest.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action.MFA; +using SMSApi.Api.Response.MFA.Exception; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Action.MFA; + +[TestClass] +public class VerifyMFACodeResponseTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void pass_when_code_is_valid() + { + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + new Dictionary().ToHttpEntityStreamTask(), + HttpStatusCode.NoContent + ); + + VerifyMfaCodeAction(GetAnyPhoneNumber(), GetAnyVerificationCode()).Execute(); + + Assert.IsTrue(true); + } + + [TestMethod] + public void throw_when_code_is_expired() + { + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + new Dictionary().ToHttpEntityStreamTask(), + HttpStatusCode.RequestTimeout + ); + + var action = () => VerifyMfaCodeAction(GetAnyPhoneNumber(), GetAnyVerificationCode()).Execute(); + + Assert.ThrowsException(action); + } + + [TestMethod] + public void throw_when_code_is_invalid() + { + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + new Dictionary().ToHttpEntityStreamTask(), + HttpStatusCode.NotFound + ); + + var action = () => VerifyMfaCodeAction(GetAnyPhoneNumber(), GetAnyVerificationCode()).Execute(); + + Assert.ThrowsException(action); + } + + private static string GetAnyPhoneNumber() => "48500100100"; + private static string GetAnyVerificationCode() => "123456"; + + private VerifyMFACode VerifyMfaCodeAction(string phoneNumber, string code) + { + var action = new VerifyMFACode(phoneNumber, code); + action.Proxy(_proxyStub); + + return action; + } +} diff --git a/smsapiTests/Unit/Action/MFA/VerifyMFACodeTest.cs b/smsapiTests/Unit/Action/MFA/VerifyMFACodeTest.cs new file mode 100644 index 0000000..bb96832 --- /dev/null +++ b/smsapiTests/Unit/Action/MFA/VerifyMFACodeTest.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api.Action.MFA; + +namespace smsapiTests.Unit.Action.MFA; + +[TestClass] +public class VerifyMFACodeTest +{ + private readonly SpyProxy _spyProxy = new(); + + [TestMethod] + public void valid_uri() + { + VerifyMfaCodeAction(GetAnyPhoneNumber(), GetAnyVerificationCode()).Execute(); + + Assert.AreEqual("mfa/codes/verifications", _spyProxy.RequestedUri); + } + + [TestMethod] + public void request_contains_phone_number_and_code() + { + var phoneNumber = GetAnyPhoneNumber(); + var code = GetAnyVerificationCode(); + + VerifyMfaCodeAction(phoneNumber, code).Execute(); + + AssertParametersContain("phone_number", phoneNumber); + AssertParametersContain("code", code); + } + + private static string GetAnyPhoneNumber() => "48500100100"; + private static string GetAnyVerificationCode() => "123456"; + + private VerifyMFACode VerifyMfaCodeAction(string phoneNumber, string code) + { + var action = new VerifyMFACode(phoneNumber, code); + action.Proxy(_spyProxy); + + return action; + } + + private void AssertParametersContain(string name, string value) + { + var expectedParameter = new KeyValuePair(name, value); + + Assert.IsTrue( + _spyProxy.Parameters.Contains(expectedParameter), + $"Expected {value}, actual value: {_spyProxy.Parameters[name]}" + ); + } +} diff --git a/smsapiTests/Unit/Action/Ping/PingServiceTest.cs b/smsapiTests/Unit/Action/Ping/PingServiceTest.cs new file mode 100644 index 0000000..ce3ae2e --- /dev/null +++ b/smsapiTests/Unit/Action/Ping/PingServiceTest.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action.Ping; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Action.Ping; + +[TestClass] +public class PingServiceTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + [DataRow(true)] + [DataRow(false)] + public void authorized_status(bool authorized) + { + var response = new Dictionary + { + { + "authorized", authorized + }, + { + "unavailable", new List() + } + }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var result = Ping().Execute(); + + Assert.AreEqual(authorized, result.Authorized); + Assert.AreEqual(0, result.UnavailableServices.Count()); + } + + [TestMethod] + public void unavailable_list() + { + var unavailableService = "fancy service"; + var response = new Dictionary + { + { + "authorized", true + }, + { + "unavailable", new List {unavailableService} + } + }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var result = Ping().Execute(); + + Assert.AreEqual(1, result.UnavailableServices.Count()); + Assert.AreEqual(unavailableService, result.UnavailableServices.First()); + } + + private PingService Ping() + { + var action = new PingService(); + action.Proxy(_proxyStub); + + return action; + } +} diff --git a/smsapiTests/Unit/Fixture/ProxyStub.cs b/smsapiTests/Unit/Fixture/ProxyStub.cs new file mode 100644 index 0000000..ef9264a --- /dev/null +++ b/smsapiTests/Unit/Fixture/ProxyStub.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SMSApi.Api; + +namespace smsapiTests.Unit.Fixture; + +public class ProxyStub : Proxy +{ + public HttpResponseEntity SyncExecutionResponse; + + public void Authentication(IClient client) + { + throw new System.NotImplementedException(); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, RequestMethod method) + { + throw new System.NotImplementedException(); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, Stream file, RequestMethod method) + { + throw new System.NotImplementedException(); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, Dictionary files, RequestMethod method) + { + return SyncExecutionResponse; + } + + public Task ExecuteAsync(string uri, NameValueCollection data, RequestMethod method, CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } + + public Task ExecuteAsync(string uri, NameValueCollection data, Stream file, RequestMethod method, CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } + + public Task ExecuteAsync(string uri, NameValueCollection data, Dictionary files, RequestMethod method, CancellationToken cancellationToken = default) + { + throw new System.NotImplementedException(); + } +} diff --git a/smsapiTests/Unit/Helper/DictionaryToStreamHelper.cs b/smsapiTests/Unit/Helper/DictionaryToStreamHelper.cs new file mode 100644 index 0000000..e90d323 --- /dev/null +++ b/smsapiTests/Unit/Helper/DictionaryToStreamHelper.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace smsapiTests.Unit.Helper; + +public static class DictionaryToStreamHelper +{ + public static Task ToHttpEntityStreamTask(this Dictionary dictionary) + { + var json = JsonConvert.SerializeObject(dictionary); + var bytes = Encoding.ASCII.GetBytes(json); + + return Task.FromResult(new MemoryStream(bytes) as Stream); + } +} diff --git a/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationExceptionTest.cs b/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationExceptionTest.cs new file mode 100644 index 0000000..2ed07bf --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationExceptionTest.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class LegacyResponseDeserializationExceptionTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + [DynamicData(nameof(ClientErrorCodes), DynamicDataSourceType.Method)] + public void throw_client_exception(int errorCode) + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary errorResponse = new() { { "error", errorCode } }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + errorResponse.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var execution = () => action.Execute(); + + Assert.ThrowsException(execution); + } + + [TestMethod] + [DynamicData(nameof(HostErrorCodes), DynamicDataSourceType.Method)] + public void throw_host_exception(int errorCode) + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary errorResponse = new() { { "error", errorCode } }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + errorResponse.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var execution = () => action.Execute(); + + Assert.ThrowsException(execution); + } + + private static IEnumerable ClientErrorCodes() + { + return new[] + { + new object[] {101}, + new object[] {102}, + new object[] {103}, + new object[] {105}, + new object[] {110}, + new object[] {1000}, + new object[] {1001}, + }; + } + + private static IEnumerable HostErrorCodes() + { + return new[] + { + new object[] {8}, + new object[] {201}, + new object[] {666}, + new object[] {999}, + }; + } + + private class TestAction : Action + { + protected override RequestMethod Method { get; } + + protected override string Uri() + { + return ""; + } + } + + private class BaseResponse : ErrorAwareResponse + { + } +} diff --git a/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationTest.cs b/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationTest.cs new file mode 100644 index 0000000..e844bd1 --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/LegacyResponseDeserializationTest.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Net; +using System.Runtime.Serialization; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class LegacyResponseDeserializationTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void map_response_to_object() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + var testValue = "test value"; + Dictionary errorResponse = new() { { "TestProperty", testValue } }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + errorResponse.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var result = action.Execute(); + + Assert.AreEqual(testValue, result.TestProperty); + } + + private class TestAction : Action + { + protected override RequestMethod Method { get; } + + protected override string Uri() + { + return ""; + } + } + + [DataContract] + private class BaseResponse : ErrorAwareResponse + { + [DataMember] public string TestProperty; + } +} \ No newline at end of file diff --git a/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerTest.cs b/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerTest.cs new file mode 100644 index 0000000..a6a7964 --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerTest.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Runtime.Serialization; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class RestJsonResponseDeserializerTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void throw_custom_action_exception() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary response = new(); + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.RequestTimeout + ); + + var execution = () => action.Execute(); + + var expectedMessage = "expired"; + Assert.ThrowsException(execution, expectedMessage); + } + + [TestMethod] + public void deserialize_to_object_when_no_exception_mapper_found() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary response = new() { { "TestProperty", "abc" } }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.OK + ); + + var result = action.Execute(); + + Assert.AreEqual("abc", result.TestProperty); + } + + private class TestAction : SMSApi.Api.Action.Action + { + protected override RequestMethod Method { get; } + + protected override ApiType ApiType() + { + return SMSApi.Api.Action.ApiType.Rest; + } + + protected override string Uri() + { + return ""; + } + } + + [DataContract] + private class ResponseWithExceptionMapper : IResponseCodeAwareResolver + { + [DataMember] public string TestProperty; + + public Dictionary> HandleExceptionActions() + { + return new Dictionary> + { + { 408, _ => throw new CustomException("expired", 408) } + }; + } + } + + private class CustomException : ClientException + { + public CustomException(string message, int code) : base(message, code) + { + } + } +} diff --git a/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerValidationErrorsTest.cs b/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerValidationErrorsTest.cs new file mode 100644 index 0000000..86083c3 --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/RestJsonResponseDeserializerValidationErrorsTest.cs @@ -0,0 +1,77 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class RestJsonResponseDeserializerValidationErrorsTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void map_validation_errors_to_message() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary response = new() + { + { + "message", "The value is not valid mobile number." + }, + { + "error", "invalid_request_data" + }, + { + "errors", new List> + { + new() + { + { + "message", "The value is not valid mobile number." + }, + { + "error", "invalid_request_data" + } + } + } + } + }; + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.BadRequest + ); + + var execution = () => action.Execute(); + + var exception = Assert.ThrowsException(execution); + var expectedMessage = "invalid_request_data: The value is not valid mobile number."; + Assert.AreEqual(expectedMessage, exception.Message); + Assert.AreEqual("400", exception.Code); + } + + private class TestAction : Action + { + protected override RequestMethod Method { get; } + + protected override ApiType ApiType() + { + return SMSApi.Api.Action.ApiType.Rest; + } + + protected override string Uri() + { + return ""; + } + } + + private class ResponseWithExceptionMapper : IResponseCodeAwareResolver + { + } +} diff --git a/smsapiTests/Unit/Response/Deserialization/TooManyRequestsResponseTest.cs b/smsapiTests/Unit/Response/Deserialization/TooManyRequestsResponseTest.cs new file mode 100644 index 0000000..48f9574 --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/TooManyRequestsResponseTest.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class TooManyRequestsResponseTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void map_validation_errors_to_message() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary response = new(); + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.TooManyRequests + ); + + var execution = () => action.Execute(); + + Assert.ThrowsException(execution); + } + + private class TestAction : Action + { + protected override RequestMethod Method { get; } + + protected override ApiType ApiType() + { + return SMSApi.Api.Action.ApiType.Rest; + } + + protected override string Uri() + { + return ""; + } + } + + private class ResponseWithExceptionMapper : IResponseCodeAwareResolver + { + } +} diff --git a/smsapiTests/Unit/Response/Deserialization/UnhandledRestCodeResponseTest.cs b/smsapiTests/Unit/Response/Deserialization/UnhandledRestCodeResponseTest.cs new file mode 100644 index 0000000..c18b45f --- /dev/null +++ b/smsapiTests/Unit/Response/Deserialization/UnhandledRestCodeResponseTest.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.Net; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api; +using SMSApi.Api.Action; +using SMSApi.Api.Response.ResponseResolver; +using smsapi.Api.Response.REST.Exception; +using smsapiTests.Unit.Fixture; +using smsapiTests.Unit.Helper; + +namespace smsapiTests.Unit.Response.Deserialization; + +[TestClass] +public class UnhandledRestCodeResponseTest +{ + private readonly ProxyStub _proxyStub = new(); + + [TestMethod] + public void map_validation_errors_to_message() + { + var action = new TestAction(); + action.Proxy(_proxyStub); + Dictionary response = new(); + _proxyStub.SyncExecutionResponse = new HttpResponseEntity( + response.ToHttpEntityStreamTask(), + HttpStatusCode.FailedDependency + ); + + var execution = () => action.Execute(); + + var ex = Assert.ThrowsException(execution); + Assert.AreEqual("Unknown http status code: 424", ex.Message); + Assert.AreEqual("FailedDependency", ex.Code); + } + + private class TestAction : Action + { + protected override RequestMethod Method { get; } + + protected override ApiType ApiType() + { + return SMSApi.Api.Action.ApiType.Rest; + } + + protected override string Uri() + { + return ""; + } + } + + private class ResponseWithExceptionMapper : IResponseCodeAwareResolver + { + } +} diff --git a/smsapiTests/Unit/SMS/SMSSendTest.cs b/smsapiTests/Unit/SMS/SMSSendTest.cs new file mode 100644 index 0000000..7989f38 --- /dev/null +++ b/smsapiTests/Unit/SMS/SMSSendTest.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SMSApi.Api.Action; + +namespace smsapiTests.Unit.SMS; + +[TestClass] +public class SMSSendTest : UnitTestBase +{ + private const string DateFormat = "yyyy-MM-ddTHH:mm:ssK"; + + private static readonly DateTime DateTime = DateTime.Now; + + [TestMethod] + public void action_has_proper_uri() + { + var action = CreateAction(); + + Execute(action); + + var expectedUri = "sms.do"; + Assert.IsTrue(SpyProxy.RequestedUri.Equals(expectedUri)); + } + + [TestMethod] + [DataRow("single", "0")] + [DataRow("nounicode", "0")] + [DataRow("flash", "0")] + [DataRow("fast", "0")] + [DataRow("details", "1")] + public void action_has_parameters_set_by_default(string expectedName, string expectedValue) + { + var action = CreateAction(); + + Execute(action); + + AssertParametersContain(expectedName, expectedValue); + } + + [TestMethod] + [DataRow("SetSingle", new object[] { true }, "single", "1")] + [DataRow("SetSingle", new object[] { false }, "single", "0")] + [DataRow("SetDataCoding", new object[] { "gsm" }, "datacoding", "gsm")] + [DataRow("SetFast", new object[] { true }, "fast", "1")] + [DataRow("SetFast", new object[] { false }, "fast", "0")] + [DataRow("SetFlash", new object[] { true }, "flash", "1")] + [DataRow("SetFlash", new object[] { false }, "flash", "0")] + [DataRow("SetGroup", new object[] { "any group" }, "group", "any group")] + [DataRow("SetNormalize", new object[] { true }, "normalize", "1")] + [DataRow("SetNoUnicode", new object[] { false }, "nounicode", "0")] + [DataRow("SetPartner", new object[] { "partner id" }, "partner_id", "partner id")] + [DataRow("SetSingle", new object[] { true }, "single", "1")] + [DataRow("SetTest", new object[] { true }, "test", "1")] + [DataRow("SetText", new object[] { "fancy message" }, "message", "fancy message")] + [DataRow("SetTemplate", new object[] { "template name" }, "template", "template name")] + [DynamicData(nameof(ExpirationDate), DynamicDataSourceType.Method)] + [DynamicData(nameof(SendDate), DynamicDataSourceType.Method)] + [DynamicData(nameof(SetTo), DynamicDataSourceType.Method)] + public void action_has_proper_parameters_binded(string methodName, object[] methodArgument, + string expectedParameterName, string expectedParameterValue, Type argumentType = null) + { + var action = CreateAction(); + GetActionMethod(action, methodName, argumentType).Invoke(action, methodArgument); + + Execute(action); + + AssertParametersContain(expectedParameterName, expectedParameterValue); + } + + protected override SMSSend CreateAction() + { + var action = base.CreateAction(); + AddNecessaryParameters(action); + + return action; + } + + private static void AddNecessaryParameters(SMSSend action) + { + action.SetText("any"); + action.SetTo("any"); + } + + private MethodInfo GetActionMethod(SMSSend action, string methodName, Type argumentType = null) + { + if (argumentType != null) return action.GetType().GetMethod(methodName, new[] { argumentType }); + + return action.GetType().GetMethod(methodName); + } + + private static IEnumerable ExpirationDate() + { + return new[] + { + new object[] + { "SetDateExpire", new object[] { "2000-01-01" }, "expiration_date", "2000-01-01", typeof(string) }, + new object[] + { + "SetDateExpire", new object[] { DateTime }, "expiration_date", DateTime.ToString(DateFormat), + typeof(DateTime) + } + }; + } + + private static IEnumerable SendDate() + { + return new[] + { + new object[] { "SetDateSent", new object[] { "2000-01-01" }, "date", "2000-01-01", typeof(string) }, + new object[] + { "SetDateSent", new object[] { DateTime }, "date", DateTime.ToString(DateFormat), typeof(DateTime) } + }; + } + + private static IEnumerable SetTo() + { + var recipients = new[] { "48500100100, 48600100100" }; + var expectedRecipientsString = string.Join(",", recipients); + + return new[] + { + new object[] + { "SetTo", new object[] { expectedRecipientsString }, "to", expectedRecipientsString, typeof(string) }, + new object[] + { "SetTo", new object[] { recipients }, "to", expectedRecipientsString, typeof(string[]) } + }; + } + + private void AssertParametersContain(string name, string value) + { + var expectedParameter = new KeyValuePair(name, value); + + Assert.IsTrue( + SpyProxy.Parameters.Contains(expectedParameter), + $"Expected {value}, actual value: {SpyProxy.Parameters[name]}" + ); + } +} \ No newline at end of file diff --git a/smsapiTests/Unit/SpyProxy.cs b/smsapiTests/Unit/SpyProxy.cs new file mode 100644 index 0000000..f93e406 --- /dev/null +++ b/smsapiTests/Unit/SpyProxy.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using SMSApi.Api; + +namespace smsapiTests.Unit; + +public class SpyProxy : Proxy +{ + public string RequestedUri { get; private set; } + + public Dictionary Parameters { get; } = new(); + + public void Authentication(IClient client) + { + throw new System.NotImplementedException(); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, RequestMethod method) + { + RequestedUri = uri; + SetParameters(data); + + return new HttpResponseEntity(new Task(() => new MemoryStream()), HttpStatusCode.OK); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, Stream file, RequestMethod method) + { + RequestedUri = uri; + SetParameters(data); + + return new HttpResponseEntity(new Task(() => new MemoryStream()), HttpStatusCode.OK); + } + + public HttpResponseEntity Execute(string uri, NameValueCollection data, Dictionary files, RequestMethod method) + { + RequestedUri = uri; + SetParameters(data); + + return new HttpResponseEntity(Task.FromResult(Stream.Null), HttpStatusCode.OK); + } + + public Task ExecuteAsync(string uri, NameValueCollection data, RequestMethod method, CancellationToken cancellationToken = default) + { + RequestedUri = uri; + SetParameters(data); + + return new Task(() => new HttpResponseEntity(new Task(() => new MemoryStream()), HttpStatusCode.OK)); + } + + public Task ExecuteAsync(string uri, NameValueCollection data, Stream file, RequestMethod method, CancellationToken cancellationToken = default) + { + RequestedUri = uri; + SetParameters(data); + + return new Task(() => new HttpResponseEntity(new Task(() => new MemoryStream()), HttpStatusCode.OK)); + } + + public Task ExecuteAsync(string uri, NameValueCollection data, Dictionary files, RequestMethod method, CancellationToken cancellationToken = default) + { + RequestedUri = uri; + SetParameters(data); + + return new Task(null); + } + + private void SetParameters(NameValueCollection collection) + { + Parameters.Clear(); + + var map = collection.AllKeys.SelectMany( + collection.GetValues, + (k, v) => new KeyValuePair(k ,v) + ); + + foreach (var entry in map) + { + Parameters.Add(entry.Key, entry.Value); + } + } +} diff --git a/smsapiTests/Unit/UnitTestBase.cs b/smsapiTests/Unit/UnitTestBase.cs new file mode 100644 index 0000000..956ebb5 --- /dev/null +++ b/smsapiTests/Unit/UnitTestBase.cs @@ -0,0 +1,29 @@ +using System; +using SMSApi.Api.Action; +using SMSApi.Api.Response; + +namespace smsapiTests.Unit; + +public abstract class UnitTestBase where T : SMSApi.Api.Action.Action +{ + protected readonly SpyProxy SpyProxy = new(); + + protected virtual T CreateAction() + { + var action = Activator.CreateInstance(); + action.Proxy(SpyProxy); + + return action; + } + + protected void Execute(T action) + { + try + { + action.Execute(); + } + catch (MissingMethodException) + { + } + } +} diff --git a/smsapiTests/UserTest.cs b/smsapiTests/UserTest.cs index 537b880..399a700 100644 --- a/smsapiTests/UserTest.cs +++ b/smsapiTests/UserTest.cs @@ -1,6 +1,7 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using System; +using SMSApi.Api.Response; namespace smsapiTests { @@ -9,47 +10,42 @@ public class UserTest : TestBase { private UserFactory _factory; - [TestInitialize] - public override void SetUp() - { - base.SetUp(); - _factory = new UserFactory(_client); - } - - [TestMethod] - public void GetCredits() - { - var pointsResponse = _factory.ActionGetCredits().Execute(); - Assert.IsNotNull(pointsResponse.Points); - Assert.IsFalse(pointsResponse.isError()); - } - [TestMethod] public void Add_Edit_List() { string usernName = "test_" + DateTime.Now.ToString("his"); - var addResponse = - _factory.ActionAdd() - .SetUsername(usernName) - .SetPassword("7815696ecbf1c96e6894b779456d330e") - .Execute(); + User addResponse = + _factory.ActionAdd().SetUsername(usernName).SetPassword("7815696ecbf1c96e6894b779456d330e").Execute(); - Assert.IsFalse(addResponse.isError()); + Assert.IsFalse(addResponse.IsError()); Assert.AreEqual("", addResponse.Info); - var editResponse = - _factory.ActionEdit(usernName) - .SetInfo("edited info") - .Execute(); + User editResponse = + _factory.ActionEdit(usernName).SetInfo("edited info").Execute(); - Assert.IsFalse(addResponse.isError()); + Assert.IsFalse(addResponse.IsError()); Assert.AreEqual(addResponse.Username, editResponse.Username); Assert.AreEqual("edited info", editResponse.Info); - var users = _factory.ActionList().Execute(); + Array users = _factory.ActionList().Execute(); Assert.IsTrue(users.List.Count > 0); } + + [TestMethod] + public void GetCredits() + { + Credits pointsResponse = _factory.ActionGetCredits().Execute(); + Assert.IsNotNull(pointsResponse.Points); + Assert.IsFalse(pointsResponse.IsError()); + } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new UserFactory(_client); + } } } diff --git a/smsapiTests/VmsTest.cs b/smsapiTests/VmsTest.cs index dcfd674..2360922 100644 --- a/smsapiTests/VmsTest.cs +++ b/smsapiTests/VmsTest.cs @@ -1,6 +1,7 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; using SMSApi.Api; -using System; +using SMSApi.Api.Response; namespace smsapiTests { @@ -9,47 +10,57 @@ public class VmsTest : TestBase { private VMSFactory _factory; - [TestInitialize] - public override void SetUp() + [TestMethod] + public void DeletingSentMessage_EmptyResponse() { - base.SetUp(); - _factory = new VMSFactory(_client, _proxyAddress); + Status sendResponse = + _factory.ActionSend(). + SetTTS("test message"). + SetTo(_validTestNumber). + SetTry(4). + SetTryInterval(300). + Execute(); + + string[] ids = new string[sendResponse.Count]; + + for (int i = 0; i < sendResponse.List.Count; i++) + { + ids[i] = sendResponse.List[i].ID; + } + + Countable deletedResponse = _factory.ActionDelete().Ids(ids).Execute(); + + Assert.AreEqual(0, deletedResponse.Count); } [TestMethod] - public void Send_Get_Delete() + public void ScheduledSend_Get_Delete() { - DateTime date = DateTime.Now; - if (date.Hour > 21 || date.Hour < 8) - { - date = date.AddHours(12); - } + DateTime tomorrow = DateTime.Now.AddDays(1); + var date = new DateTime(tomorrow.Year, tomorrow.Month, tomorrow.Day, 12, 0, 0); - var sendResponse = - _factory.ActionSend() - .SetTTS("test message") - .SetTo(_validTestNumber) - .SetDateSent(date) - .SetTry(4) - .SetTryInterval(300) - .Execute(); + Status sendResponse = + _factory.ActionSend(). + SetTTS("test message"). + SetTo(_validTestNumber). + SetDateSent(date). + SetTry(4). + SetTryInterval(300). + Execute(); Assert.AreEqual(1, sendResponse.Count); Assert.IsTrue(sendResponse.List[0].Points > 0, "Points must be greather then 0"); string[] ids = new string[sendResponse.Count]; - for (int i = 0, l = 0; i < sendResponse.List.Count; i++) + for (int i = 0; i < sendResponse.List.Count; i++) { - ids[l] = sendResponse.List[i].ID; - l++; + ids[i] = sendResponse.List[i].ID; } - System.Console.WriteLine("Get:"); - var getResponse = - _factory.ActionGet() - .Ids(ids) - .Execute(); + Console.WriteLine("Get:"); + Status getResponse = + _factory.ActionGet().Ids(ids).Execute(); Assert.AreEqual(sendResponse.Count, getResponse.Count); Assert.AreEqual(_validTestNumber, getResponse.List[0].Number); @@ -58,13 +69,17 @@ public void Send_Get_Delete() Assert.AreEqual(sendResponse.List[0].Points, getResponse.List[0].Points); Assert.AreEqual(sendResponse.List[0].Status, getResponse.List[0].Status); - var deletedResponse = - _factory - .ActionDelete() - .Ids(ids) - .Execute(); + Countable deletedResponse = + _factory.ActionDelete().Ids(ids).Execute(); Assert.AreEqual(sendResponse.Count, deletedResponse.Count); } + + [TestInitialize] + public override void SetUp() + { + base.SetUp(); + _factory = new VMSFactory(_client, _proxyAddress); + } } } diff --git a/smsapiTests/smsapiTests.csproj b/smsapiTests/smsapiTests.csproj index 01c6961..b984ac6 100644 --- a/smsapiTests/smsapiTests.csproj +++ b/smsapiTests/smsapiTests.csproj @@ -1,56 +1,25 @@  - net45;netcoreapp2.0;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1; false + net7.0 + 3.0.0 - - - - - - - - - - + - - - - - - - - - - 4.7.0 - - - - - - 4.7.0 - - - - - - 4.7.0 - - - - - - 4.7.0 - + + + + + + - \ No newline at end of file +