// TwitterSession.cs created with MonoDevelop
// User: raul@bgta.net at 7:02 31/05/2008
//
using System;
using System.Net;
using System.Web;
using System.Text;
using System.IO;
using gTwitter.Core.Serialization;
namespace gTwitter.Core
{
///
/// Twitter Session Class
///
public class TwitterSession : IDisposable
{
#region "Constants"
private const string PUBLIC_TIMELINE_URL = "http://twitter.com/statuses/public_timeline.xml?since_id={0}";
private const string USER_TIMELINE_URL = "http://twitter.com/statuses/user_timeline.xml?id={0}&count={1}&since={2}&since_id={3}";
private const string FRIENDS_TIMELINE_URL = "http://twitter.com/statuses/friends_timeline.xml?id={0}&since={1}";
private const string FRIENDS_URL = "http://twitter.com/statuses/friends.xml?id={0}&page={1}&lite={2}&since={3}";
private const string FOLLOWERS_URL = "http://twitter.com/statuses/followers.xml?page={0}&lite={1}";
private const string UPDATE_URL = "http://twitter.com/statuses/update.xml?status={0}";
private const string VERIFY_URL = "http://twitter.com/account/verify_credentials.xml";
private const string END_SESSION_URL = "http://twitter.com/account/end_session.xml";
private const string SHOW_STATUS_URL = "http://twitter.com/statuses/show/{0}.xml";
private const string SHOW_USER_URL = "http://twitter.com/users/show/{0}.xml?email={1}";
private const string REPLIES_URL = "http://twitter.com/statuses/replies.xml?page={0}&since={1}&since_id={2}";
private const string DESTROY_URL = "http://twitter.com/statuses/destroy/{0}.xml";
private const string FEATURED_URL = "http://twitter.com/statuses/featured.xml";
#endregion
#region "Events"
///
/// Raised on dispose
///
public event DisposeSessionEventHandler OnDispose;
///
/// Defines the shape of methods that are called in response to a Dispose event.
///
public delegate void DisposeSessionEventHandler(TwitterSession session,EventArgs e);
///
/// Raised when session is opened
///
///
/// A
///
public event OpenSessionEventHandler OnOpen;
///
/// Defines the shape of methods that are called in response to an Open Session event.
///
public delegate void OpenSessionEventHandler(TwitterSession session,EventArgs e);
///
/// Raised when session is closed
///
public event CloseSessionEventHandler OnClose;
///
/// Defines the shape of methods that are called in response to a Close Session event.
///
public delegate void CloseSessionEventHandler(TwitterSession session,EventArgs e);
#endregion
///
/// Session settings
///
protected TwitterSettings _settings;
///
/// Parent Factory.
///
protected TwitterFactory _parentFactory;
private bool Disposed = false;
///
/// Constructor
///
///
/// A configured Twitter Factory
///
internal TwitterSession(TwitterFactory parent)
{
this._parentFactory = parent;
this.Open();
}
#region "IDisposable"
///
/// Automatcly called when object is Disposed.
///
///
public void Dispose()
{
if(!this.Disposed)
{
this.Close();
}
this.Disposed = true;
this.OnDispose(this,new EventArgs());
}
#endregion
///
/// Get an initialized web request to twitter web service
///
///
/// A url to request
///
///
/// A initialized web request
///
protected HttpWebRequest GetInitializedWebRequest(string url)
{
return this.GetInitializedWebRequest(url,false);
}
///
/// Get an initialized web request to twitter web service
///
///
/// A url to request
///
///
/// A boolean that indicates if request should use POST web method
///
///
/// A initialized web request
///
protected HttpWebRequest GetInitializedWebRequest(string url, bool usePOST)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Proxy = this._parentFactory.Settings.Proxy.GetWebProxy();
request.PreAuthenticate = true;
request.Credentials = this._parentFactory.Settings.GetCredentials();
request.ProtocolVersion = HttpVersion.Version10;
request.Method = usePOST ? "POST" : "GET";
request.AllowWriteStreamBuffering = true;
request.Headers.Add("X-Twitter-Client: gTwitter");
request.Headers.Add("X-Twitter-Client-Version: "+System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
return request;
}
///
/// Get the response body of the twitter service. This function throw an exception
/// on error.
///
///
/// A web request
///
///
/// A response body string from server
///
protected string GetResponse(HttpWebRequest request)
{
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
switch(response.StatusCode)
{
case HttpStatusCode.NotModified: // There was no new data to return
response.Close();
throw new NotModifiedException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.BadRequest: // Your request is invalid, and we'll return an error message that tells you why. This is the status code returned if you've exceeded the rate limit (see below)
response.Close();
throw new BadRequestException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.Unauthorized: // either you need to provide authentication credentials, or the credentials provided aren't valid
response.Close();
throw new NotAuthorizedException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.Forbidden: // twitter service understand your request, but are refusing to fulfill it. An accompanying error message should explain why
response.Close();
throw new ForbiddenException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.NotFound: // either you're requesting an invalid URI or the resource in question doesn't exist (ex: no such user)
response.Close();
throw new NotFoundException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.InternalServerError: // gTwitter API did something wrong. Please post to the group about it and the gTwitter team will investigate
response.Close();
throw new InternalServerException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.BadGateway: // returned if Twitter is down or being upgraded
response.Close();
throw new BadGatewayException(Error.FromXml(this.GetWebResponseString(response)).Message);
case HttpStatusCode.ServiceUnavailable: // the Twitter servers are up, but are overloaded with requests. Try again later
response.Close();
throw new ServiceUnavailableException(Error.FromXml(this.GetWebResponseString(response)).Message);
default:
return this.GetWebResponseString(response);
}
}
///
/// Gets the response body of a web request
///
///
/// A
///
///
/// A
///
protected string GetWebResponseString(HttpWebResponse response)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string stringResponse = reader.ReadToEnd();
response.Close();
return stringResponse;
}
///
/// Converts a DateTime object to date/time twitter format string
///
///
/// A DateTime object
///
///
/// A date/time twitter format string
///
protected string GetDateTimeString(DateTime dt)
{
return HttpUtility.UrlEncode(dt.ToString("ddd MMM dd hh:mm:ss +0000 yyyy"));
}
#region "Public Methods"
///
/// Open the Twitter Session. Automaticly called from constructor.
///
public void Open()
{
this.GetResponse(this.GetInitializedWebRequest(VERIFY_URL));
this.OnOpen(this,new EventArgs());
}
///
/// Close the Twitter Session. Automaticly called from Dispose method.
///
public void Close()
{
this.GetResponse(this.GetInitializedWebRequest(END_SESSION_URL));
this.OnClose(this, new EventArgs());
}
#region "Statuses methods"
///
/// Returns the 20 most recent statuses from non-protected users who have set a custom user icon
///
///
/// A 20 most recent statuses
///
public Statuses GetPublicTimeLine()
{
return this.GetPublicTimeLine(String.Empty);
}
///
/// Returns the 20 most recent statuses from non-protected users who have set a custom user icon.
///
///
/// Returns only public statuses with an ID greater than (that is, more recent than) the specified ID
///
///
/// A 20 most recent statuses with an ID greater than the specified ID
///
public Statuses GetPublicTimeLine(string since_id)
{
Statuses statuses = Statuses.FromXml(this.GetResponse(this.GetInitializedWebRequest(string.Format(PUBLIC_TIMELINE_URL,since_id))));
return statuses;
}
///
/// Returns the 20 most recent statuses posted in the last 24 hours from the authenticating user and that user's friends.
///
///
/// A 20 most recent statuses posted in the last 24 hours from the authenticating user and that user's friends
///
public Statuses GetFriendsTimeLine()
{
return this.GetFriendsTimeLine(String.Empty,DateTime.Now);
}
///
/// Returns the 20 most recent statuses posted in the last 24 hours from the authenticating user and that user's friends.
///
///
/// Specifies the ID or screen name of the user for whom to return the friends_timeline
///
///
/// A .Narrows the returned results to just those statuses created after the specified HTTP-formatted date. The same behavior is available by setting an If-Modified-Since header in your HTTP request
///
///
/// A . The 20 most recent statuses posted in the last 24 hours from the authenticating user and that user's friends.
///
public Statuses GetFriendsTimeLine(string id,DateTime since)
{
Statuses statuses = Statuses.FromXml(this.GetResponse(this.GetInitializedWebRequest(string.Format(FRIENDS_TIMELINE_URL,id,this.GetDateTimeString(since)))));
return statuses;
}
///
/// Returns the 20 most recent statuses posted in the last 24 hours from the authenticating user.
///
///
/// A . The 20 most recent statuses posted in the last 24 hours from the authenticating user.
///
public Statuses GetUserTimeLine()
{
return this.GetUserTimeLine(string.Empty,0,DateTime.Now,string.Empty);
}
///
/// Returns the 20 most recent statuses posted in the last 24 hours from the authenticating user.
///
///
/// A .Specifies the ID or screen name of the user for whom to return the friends_timeline.
///
///
/// A . Specifies the number of statuses to retrieve. May not be greater than 20 for performance purposes. (0 = 20 most recent).
///
///
/// A . Narrows the returned results to just those statuses created after the specified HTTP-formatted date. The same behavior is available by setting an If-Modified-Since header in your HTTP request
///
///
/// A . Returns only statuses with an ID greater than (that is, more recent than) the specified. ID
///
///
/// A . The 20 most recent statuses posted in the last 24 hours from the authenticating user.
///
public Statuses GetUserTimeLine(string id, int count, DateTime since, string since_id)
{
string countStr = count == 0 ? string.Empty : count.ToString();
string url = String.Format(USER_TIMELINE_URL,id,countStr,this.GetDateTimeString(since),since_id);
Statuses statuses = Statuses.FromXml(this.GetResponse(this.GetInitializedWebRequest(url)));
return statuses;
}
///
/// Returns a single status, specified by the id parameter below. The status's author will be returned inline.
///
///
/// A .The numerical ID of the status you're trying to retrieve.
///
///
/// A . A single status, specified by the id parameter below.
///
public Status ShowStatus(string id)
{
return Status.FromXml(this.GetResponse(this.GetInitializedWebRequest(String.Format(SHOW_STATUS_URL,id))));
}
///
/// Updates the authenticating user's status.
///
///
/// A . The text of your status update. Be sure to URL encode as necessary. Must not be more than 160 characters and should not be more than 140 characters to ensure optimal display.
///
public void PostUpdate(string status)
{
status = HttpUtility.UrlEncode(status.Substring(0,160));
this.GetResponse(this.GetInitializedWebRequest(String.Format(UPDATE_URL,status),true));
}
///
/// Returns the 20 most recent replies (status updates prefixed with @username posted by users who are friends with the user being replied to) to the authenticating user. Replies are only available to the authenticating user; you can not request a list of replies to another user whether public or protected.
///
///
/// A . Retrieves the 20 next most recent replies.
///
///
/// A . Narrows the returned results to just those replies created after the specified HTTP-formatted date. The same behavior is available by setting an If-Modified-Since header in your HTTP request
///
///
/// A . Returns only statuses with an ID greater than (that is, more recent than) the specified ID
///
///
/// A . The 20 most recent replies.
///
public Statuses GetReplies(int page, DateTime since, string since_id)
{
string pageStr = page == 0 ? string.Empty : page.ToString();
string url = String.Format(REPLIES_URL,pageStr,this.GetDateTimeString(since),since_id);
Statuses statuses = Statuses.FromXml(this.GetResponse(this.GetInitializedWebRequest(url)));
return statuses;
}
///
/// Destroys the status specified by the required ID parameter. The authenticating user must be the author of the specified status
///
///
/// A . The ID of the status to destroy.
///
public void DestroyStatus(string id)
{
this.GetResponse(this.GetInitializedWebRequest(String.Format(DESTROY_URL,id)));
}
#endregion
#region "User Methods"
///
/// Returns up to 100 of the authenticating user's friends who have most recently updated, each with current status inline. It's also possible to request another user's recent friends list via the id parameter below
///
///
/// A . The ID or screen name of the user for whom to request a list of friends.
///
///
/// A . Retrieves the next 100 friends.
///
///
/// A . Prevents the inline inclusion of current status.
///
///
/// A . Narrows the returned results to just those friendships created after the specified HTTP-formatted date. The same behavior is available by setting an If-Modified-Since header in your HTTP request
///
///
/// A Up to 100 of the authenticating user's friends who have most recently updated, each with current status inline.
///
public Users GetFriends(string id, int page,bool lite, DateTime since)
{
string pageStr = page == 0 ? string.Empty : page.ToString();
string liteStr = lite ? "true" : "false";
string url = String.Format(FRIENDS_URL,id,pageStr,liteStr,this.GetDateTimeString(since));
Users users = Users.FromXml(this.GetResponse(this.GetInitializedWebRequest(url)));
return users;
}
///
/// Returns up to 100 of the authenticating user's friends who have most recently updated, each with current status inline. It's also possible to request another user's recent friends list via the id parameter below
///
///
/// A Up to 100 of the authenticating user's friends who have most recently updated, each with current status inline.
///
public Users GetFriends()
{
return this.GetFriends(string.Empty,0,true,DateTime.Now);
}///
/// Returns the authenticating user's followers, each with current status inline.
///
///
/// A . Retrieves the next 100 followers.
///
///
/// A . Prevents the inline inclusion of current status. Must be set to a value of true.
///
///
/// A . The authenticating user's followers
///
public Users GetFollowers(int page,bool lite)
{
string pageStr = page == 0 ? string.Empty : page.ToString();
string liteStr = lite ? "true" : "false";
string url = String.Format(FOLLOWERS_URL,pageStr,liteStr);
Users users = Users.FromXml(this.GetResponse(this.GetInitializedWebRequest(url)));
return users;
}
///
/// Returns the authenticating user's followers, each with current status inline.
///
///
/// A . The authenticating user's followers.
///
public Users GetFollowers()
{
return this.GetFollowers(0,true);
}
///
/// Returns a list of the users currently featured on the site with their current statuses inline.
///
///
/// A . List of the users currently featured.
///
public Users GetFeatured()
{
return Users.FromXml(this.GetResponse(this.GetInitializedWebRequest(FEATURED_URL)));
}
///
/// Returns extended information of a given user, specified by ID or screen name as per the required id parameter below. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences.
///
///
/// A .The ID or screen name of a user.
///
///
/// A . The email address of a user.
///
///
/// A . Extended information of a given user
///
public User ShowUser(string id, string email)
{
return User.FromXml(this.GetResponse(this.GetInitializedWebRequest(String.Format(SHOW_USER_URL,id,email))));
}
///
/// Returns extended information of a given user, specified by ID or screen name as per the required id parameter below. This information includes design settings, so third party developers can theme their widgets according to a given user's preferences.
///
///
/// A . Extended information of a given user
///
public User ShowUser(string id)
{
return this.ShowUser(id, string.Empty);
}
#endregion
#region "Direct Message Methods"
#endregion
#region "Friendship Methods"
#endregion
#region "Account Methods"
#endregion
#region "Favorite Methods"
#endregion
#region "Notification Methods"
#endregion
#region "Block Methods"
#endregion
#region "Help Methods"
#endregion
#endregion
}
}