using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace DCC.Scraper.TBS
{
/// <summary>
/// Connect to The Best Spinner API. Allows you to automate some features the client provides.
/// </summary>
public class BestSpinnerClient : ScraperBase
{
private string _username;
private string _password;
private string _sessionId;
private string _baseUrl;
public BestSpinnerClient()
{
_baseUrl = "
http://thebestspinner.com/api.php";
}
public string Username
{
set {
_username = value;
}
get {
return _username;
}
}
public string Password
{
set {
_password = value;
}
get {
return _password;
}
}
public int ApiQueries
{
get
{
BestSpinnerRequest req = new BestSpinnerRequest("apiQueries");
req.Expected.Add("output");
BestSpinnerResponse resp = SendCommand(req);
return int.Parse(resp.Values["output"]);
}
}
private string SessionId
{
set {
_sessionId = value;
}
get {
return _sessionId;
}
}
public void Login(string username, string password)
{
Username = username;
Password = password;
this.Initialize();
}
/// <summary>
/// Identify Synonyms
/// </summary>
/// <param name="text">The text to perform the synonym identification on.</param>
/// <param name="maxSyns">The maximum number of synonyms to return for a word/phrase.</param>
/// <returns>A spin-ready string.</returns>
public string IdentifySynonyms(string text, int maxSyns)
{
BestSpinnerRequest req = new BestSpinnerRequest("identifySynonyms");
req.AddParam("text", text);
req.AddParam("maxsyns", maxSyns.ToString());
req.Expected.Add("output");
BestSpinnerResponse resp = SendCommand(req);
return resp.Values["output"];
}
/// <summary>
/// Replace Everyone's Favorites
/// </summary>
/// <param name="text">The text to perform the synonym identification on.</param>
/// <param name="maxSyns">The maximum number of synonyms to return for a word/phrase.</param>
/// <param name="quality">The level of replacements.</param>
/// <returns>A spin-ready string.</returns>
public string ReplaceEveryonesFavorites(string text, int maxSyns, SpinQuality quality)
{
BestSpinnerRequest req = new BestSpinnerRequest("replaceEveryonesFavorites");
req.AddParam("text", text);
req.AddParam("maxsyns", maxSyns.ToString());
req.AddParam("quality", quality.ToString());
req.Expected.Add("output");
BestSpinnerResponse resp = SendCommand(req);
return resp.Values["output"];
}
/// <summary>
/// Creates a unique article based on spin-formatted text.
/// </summary>
/// <param name="text">Spin-formatted text.</param>
/// <returns>A randomly spun version of text.</returns>
public string RandomSpin(string text)
{
BestSpinnerRequest req = new BestSpinnerRequest("randomSpin");
req.AddParam("text", text);
req.Expected.Add("output");
BestSpinnerResponse resp = SendCommand(req);
return resp.Values["output"];
}
private void Initialize()
{
if (string.IsNullOrEmpty(SessionId))
{
SessionId = this.Authenticate();
}
}
private string Authenticate()
{
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
throw new ArgumentNullException("You must Login() or set the Username and Password before proceeding.");
BestSpinnerRequest req = new BestSpinnerRequest("authenticate");
req.AddParam("username", Username);
req.AddParam("password", Password);
req.Expected.Add("session");
BestSpinnerResponse resp = this.SendCommand(req);
if (resp.Success)
{
return resp.Values["session"];
}
else
{
throw new InvalidOperationException(resp.Values["error"]);
}
}
private BestSpinnerResponse SendCommand(BestSpinnerRequest request)
{
if (request == null)
throw new ArgumentNullException("Request missing.");
if (request.Expected.Count < 1)
throw new ArgumentNullException("Request missing expected response fields.");
if (request.Values.Count < 1)
throw new ArgumentNullException("Request missing parameters.");
if (!request.Values["action"].Equals("authenticate") && string.IsNullOrEmpty(SessionId))
throw new ArgumentNullException("You are not authenticated, please Login().");
string url = string.Format("&session={0}&format=xml&{1}", SessionId, request.ToString());
#if DEBUG
Console.WriteLine("REQUEST: " + url);
#endif
string xml = base.Post(this._baseUrl, url);
BestSpinnerResponse r = this.ParseResponse(request, xml);
if (!r.Success)
{
throw new InvalidOperationException(string.Format("Action: {0}, Message: {1}", request.Values["action"], r.Values["error"]));
}
return r;
}
private BestSpinnerResponse ParseResponse(BestSpinnerRequest request, string response)
{
if (request == null)
throw new ArgumentNullException("Request missing.");
if (string.IsNullOrEmpty(response))
throw new ArgumentNullException("Missing an XML API response.");
#if DEBUG
Console.WriteLine("RESPONSE: " + response);
#endif
BestSpinnerResponse r = new BestSpinnerResponse();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(response);
string isValid = xmlDoc.DocumentElement.SelectSingleNode("success").InnerText;
r.Success = bool.Parse(isValid);
if (r.Success)
{
foreach (string node in request.Expected)
{
if (node == null)
throw new InvalidOperationException("A null request parameter was found!");
string value = xmlDoc.DocumentElement.SelectSingleNode(node).InnerText;
r.AddParam(node, value);
}
}
else
{
r.AddParam("error", xmlDoc.DocumentElement.SelectSingleNode("error").InnerText);
}
return r;
}
}
/// <summary>
/// The values for a given API request.
/// </summary>
public class BestSpinnerRequest : BestSpinnerPacket
{
private List<string> _expected;
public BestSpinnerRequest(string action)
{
AddParam("action", action);
_expected = new List<string>();
}
/// <summary>
/// Stores names of values expected in the response.
/// </summary>
public List<string> Expected
{
set {
_expected = value;
}
get {
return _expected;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> item in Values)
{
sb.Append(string.Format("{0}={1}&", item.Key, item.Value));
}
return sb.ToString();
}
}
/// <summary>
/// The results of a API request.
/// </summary>
public class BestSpinnerResponse : BestSpinnerPacket
{
private bool _success;
public BestSpinnerResponse()
{
_success = false;
}
/// <summary>
/// Was the API request successful?
/// </summary>
public bool Success
{
set {
_success = value;
}
get {
return _success;
}
}
}
public class BestSpinnerPacket
{
private Dictionary<string, string> _values;
public BestSpinnerPacket()
{
_values = new Dictionary<string,string>();
}
public void AddParam(string name, string value)
{
Values.Add(name, value);
}
/// <summary>
/// Stores query string parameters on a Request. Stores result values on a Response.
/// </summary>
public Dictionary<string, string> Values
{
set {
_values = value;
}
get {
return _values;
}
}
}
public enum SpinQuality
{
Good = 1,
Better = 2,
Best = 3
}
}
--------- Here are some Unit Tests to see how it works ----------
using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using DCC.Scraper.TBS;
namespace UnitTests
{
[TestFixture]
public class BestSpinnerTests
{
private BestSpinnerClient CreateClient()
{
BestSpinnerClient tbs = new BestSpinnerClient();
tbs.Login("your-tbs-email", "your-tbs-api-key");
return tbs;
}
[Test]
public void Can_Authenticate_Client()
{
BestSpinnerClient tbs = this.CreateClient();
Console.WriteLine("Queries: " + tbs.ApiQueries);
Assert.IsTrue(tbs.ApiQueries >= 0);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void Stops_If_Not_Logged_In()
{
BestSpinnerClient tbs = new BestSpinnerClient();
int queries = tbs.ApiQueries;
}
[Test]
public void Can_Identify_Synonyms()
{
BestSpinnerClient tbs = this.CreateClient();
string spinText = tbs.IdentifySynonyms("Losing weight can be a difficult thing to do.", 3);
//Console.WriteLine(spinText);
Assert.IsTrue(spinText.IndexOf("{") > -1);
Assert.IsTrue(spinText.IndexOf("}") > -1);
Assert.IsTrue(spinText.IndexOf("|") > -1);
}
[Test]
public void Can_Replace_Everyones_Favories()
{
BestSpinnerClient tbs = this.CreateClient();
string spinText = tbs.ReplaceEveryonesFavorites("Losing weight can be a difficult thing to do.", 3, SpinQuality.Good);
//Console.WriteLine(spinText);
Assert.IsTrue(spinText.IndexOf("{") > -1);
Assert.IsTrue(spinText.IndexOf("}") > -1);
Assert.IsTrue(spinText.IndexOf("|") > -1);
}
[Test]
public void Can_Spin_Text()
{
BestSpinnerClient tbs = this.CreateClient();
string spun = tbs.RandomSpin("{Losing|Dropping|Shedding} {weight|fat|bodyweight|excess weight} can be a {difficult|challenging|tough|hard} {thing|factor|issue|point} to do.");
//Console.WriteLine(spun);
Assert.IsTrue(spun.IndexOf("{") == -1);
Assert.IsTrue(spun.IndexOf("}") == -1);
Assert.IsTrue(spun.IndexOf("|") == -1);
}
}
}