using System;
using System.IO;
using System.Net;
using Interop.Clickatell;
namespace Neo.Afx.WinService.Messages
{
///
/// A wrapper class for sending SMS's using the Clickatell (Vodazone) API.
///
public class SmsVodazone : ISmsSender
{
private string ApiID { get; set; }
private string UserName { get; set; }
private string Password { get; set; }
#region Initialization
///
/// Initializes a new instance of the class
/// by using the given values.
///
/// The API ID to be queried.
/// The user name to be queried.
/// The password to be queried.
public SmsVodazone(string apiID, string userName, string password)
{
try
{
ApiID = apiID;
UserName = userName;
Password = password;
var reply = Authenticate();
string replyText;
if (!ReplyOk(reply, "OK: ", out replyText))
{
throw new Exception(replyText);
}
}
catch (Exception ex)
{
throw new Exception(GetInnermostMessage(ex));
}
}
#endregion
#region Credits
///
/// Gets the number of credits left.
///
public int Credits
{
get
{
var balance = QueryBalance();
string credits;
if(ReplyOk(balance, "Credit: ", out credits))
{
if (credits.Contains("."))
{
credits = credits.Substring(0, credits.IndexOf("."));
}
return (int)float.Parse(credits);
}
return 0;
}
}
#endregion
#region Send
///
/// Sends the given message to the given cell number.
///
/// The message to be sent.
/// The cell number to which the message is sent.
/// When this method returns, contains the error message if
/// the SMS was not sent successfully; otherwise contains a null references.
///
/// true if successful; false otherwise.
///
public bool Send(string message, string cellNumber, out string error)
{
var successful = true;
try
{
string replyText;
var reply = SendMsg(message, cellNumber);
if(ReplyOk(reply, "ID: ", out replyText))
{
#region Check if successful
reply = QueryMsg(replyText);
if(ReplyOk(reply, "Status: ", out replyText))
{
var messageStatus = (eSMSMsgStatus)Int32.Parse(replyText);
error = messageStatus.ToString();
#region Set successful based on message status
switch(messageStatus)
{
case eSMSMsgStatus.SMS_MSG_CANCELLED:
successful = false;
break;
case eSMSMsgStatus.SMS_MSG_DELIVERED:
break;
case eSMSMsgStatus.SMS_MSG_ERR_DELIVERING_MSG:
successful = false;
break;
case eSMSMsgStatus.SMS_MSG_ERR_WITH_MSG:
successful = false;
break;
case eSMSMsgStatus.SMS_MSG_EXPIRED:
successful = false;
break;
case eSMSMsgStatus.SMS_MSG_OK:
break;
case eSMSMsgStatus.SMS_MSG_QUEUED:
break;
case eSMSMsgStatus.SMS_MSG_QUEUED_LATER_DELIV:
break;
case eSMSMsgStatus.SMS_MSG_RECEIVED:
break;
case eSMSMsgStatus.SMS_MSG_ROUTING_ERROR:
successful = false;
break;
case eSMSMsgStatus.SMS_MSG_UNKNOWN:
break;
}
#endregion
}
else
{
error = replyText;
successful = false;
}
#endregion
}
else
{
error = replyText;
successful = false;
}
}
catch(Exception ex)
{
error = GetInnermostMessage(ex);
successful = false;
}
return successful;
}
#endregion
#region ReplyOk
static bool ReplyOk(string reply, string tag, out string message)
{
const string Marker = "ERR: ";
message = null;
if(!String.IsNullOrEmpty(reply))
{
var p1 = reply.IndexOf(Marker);
if(p1 == -1)
{
p1 = reply.IndexOf(tag);
message = p1 == -1 ? reply : reply.Substring(p1 + tag.Length);
return true;
}
// An error occurred so get error message
message = reply.Substring(p1 + Marker.Length);
}
return false;
}
#endregion
#region GetInnermostMessage
public string GetInnermostMessage(Exception ex)
{
if (ex.InnerException == null)
{
return ex.Message;
}
else
{
return GetInnermostMessage(ex.InnerException);
}
}
#endregion
#region Helper Methods
private string Authenticate()
{
return RequestGET("auth","");
}
private string QueryBalance()
{
return RequestGET("getbalance", "");
}
private string SendMsg(string message, string cellNumber)
{
return RequestGET("sendmsg", "to=" + cellNumber + "&text=" + message);
}
private string QueryMsg(string replyText)
{
return RequestGET("querymsg", "apimsgid=" + replyText);
}
public string RequestGET(string action, string queryString)
{
try
{
var baseUri = String.Format("https://api.clickatell.com/http/{0}?user={1}&password={2}&api_id={3}", action ,UserName, Password, ApiID);
baseUri += "&" + queryString;
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(baseUri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string result = "";
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
result = rdr.ReadToEnd();
}
return result;
}
catch (Exception ex)
{
return "ERROR: " + GetInnermostMessage(ex);
}
}
#endregion
}
}