TweetSharp is a complete .NET library for microblogging platforms that allows you to write short and sweet expressions that convert automatically to web queries and fly to Twitter on your behalf. We strive to cover 100% of the Twitter API and actively keep up with enhancements and changes from Twitter itself. TweetSharp was developed by Daniel Crenna and Jason Diller.

30 October 2009 ~ Comments

TweetSharp Preview 17 – And a response to API versioning

Earliery today Joel Spolsky sent these messages out during the DevDays conference:

“Twitter changed API on the fly, breaking TweetSharp, so
tweets were not showing on screen at #devdays. http://is.gd/4HYJe”

(http://twitter.com/spolsky/status/5283936128)

“In the old days, platform vendors used version numbers to
avoid breaking their developers. Today they don’t care.”

(http://twitter.com/spolsky/status/5283940571)

There was speculation that TweetSharp didn’t yet use API versioning announced by Twitter on October 16th and this was the cause of the issue. As a result we have released Preview 17 which does use the V1 endpoint. We apologize for not acting on this announcement sooner.

However, unit testing against both the V1 endpoint and the former endpoint using Preview 16 showed no adverse effects or sudden API changes. We do know that in the past that TweetSharp wouldn’t respond well to Twitter API changes after we went through through the pain of the the geo-tagging features being introduced to small groups of users, causing erratic behavior when our deserialization routines failed.

As a result, we relaxed the deserialization rules to break on the absence of only a handful of defining properties and released those changes as part of Preview 16. So while we don’t yet know what version DevDays was using when the error occurred, we could not reproduce the issues reported as of Preview 16. Either way we are sorry it happened, we love the conference and are thrilled that they chose TweetSharp to power it.

Twitter does care about versioning and has provided the first branch for versioning for its API, we are sorry for the past issues with deserialization when the Twitter API changes, we think we have the right pieces in place to do our best not to break your apps when things do change as of Preview 16 released October 22nd, and Preview 17 released today is using the versioned API endpoint, hopefully ensuring that future changes to Twitter’s API will occur on a new endpoint.

Please update your version of TweetSharp (both the TweetSharp library and JSON.NET that is bundled with it, as they upgraded it to handle null values for required fields without throwing exceptions) or live on the edge by building off the trunk to get changes as soon as we find them. Let us know if you still see discrepancies with returned API entities on Twitter, and send us the raw output so we can test it thoroughly with our unit tests to find the problem quickly.

Keep building great applications!

22 October 2009 ~ Comments

Tweetsharp Preview 16 – Cursors and Spam Reporting

TweetSharp Preview 16 is now released and includes support for Twitter’s new cursor-based pagination of friends and followers list, ID lists in the SocialGraph APIs, as well as the recently added spam reporting API. For details on the spam reporting API, you can see more on Jason’s blog here. The following code snippets will show you how to page through friends and followers using cursors.

var twitter = FluentTwitter.CreateRequest()
                .AuthenticateAs(USERNAME, PASSWORD)
                .Users()
                .GetFriends()
                .CreateCursor()  //this will start paging and get the 1st page
                .AsXml();

//make the call to twitter
var response = twitter.Request();
//get the first page of users from the response.
var friends = response.AsUsers();
//get the value of the next cursor page (a nullable 64-bit integer)
var nextCursor = response.AsNextCursor();

if ( nextCursor.HasValue && nextCursor.Value != 0 )
{
    //get next page
    twitter = FluentTwitter.CreateRequest()
                .AuthenticateAs(USERNAME, PASSWORD)
                .Users()
                .GetFriends()
                .GetCursor(nextCursor.Value)
                .AsJson();

    //make another request
    var secondResponse = twitter.Request();

    //get the users from the request
    var secondCursorPage = secondResponse.AsUsers();

    //get the id of the previous cursor page if you want to go back.
    var previous = secondResponse.AsPreviousCursor();
}

Things to know:

  • Currently the cursor pages for friends and followers are 100 users each (give or take – blocked users are eliminated on the fly, so you may get less than 100 on any given page).
  • Cursor ids can be negative numbers. A return value of 0 from AsNextCursor() or AsPreviousCursor() indicates that there is no next or previous page, correspondingly.
  • The SocialGraph methods that return IDs only return pages of 5000 ids at a time (or slightly less, if because of blocks)
  • Passing an ID of -1 to the GetCursor() method has the same effect as calling CreateCursor()
  • The old method of paging through users has been deprecated and will eventually stop working. The extension methods that use these APIs have been marked as obsolete, so if your code is using them you will see warnings when you compile against this preview.

The code for paging through IDs in your social graph is similar:

 //Using a user with more than 5000 followers
 var twitter = FluentTwitter.CreateRequest()
               .AuthenticateAs(USERNAME, PASSWORD)
               .SocialGraph().Ids().ForFollowersOf("hodgman")
               .CreateCursor()
               .AsXml();

 var response = twitter.Request();
 var nextCursor = response.AsNextCursor();
 var ids = response.AsIds();

 while (nextCursor.HasValue && nextCursor.Value != 0 )
 {
     var pagedTwitter = FluentTwitter.CreateRequest()
                                 .AuthenticateAs(USERNAME, PASSWORD)
                                 .SocialGraph().Ids().ForFollowersOf("hodgman")
                                 .GetCursor(nextCursor.Value)
                                 .AsJson();
     var pagedResponse = pagedTwitter.Request();
     ids.AddRange(pagedResponse.AsIds());
     nextCursor = pagedResponse.AsNextCursor();
 }

See also the Twitter API documentation:
Statuses/Friends
Statuses/Followers
SocialGraph/Friends/IDs
SocialGraph/Followers/IDs

01 October 2009 ~ Comments

TweetSharp Preview 15 – Retweeting and Geotagging

TweetSharp Preview 15 is now released and includes support for Twitter’s upcoming retweeting and geotagging features. This does not mean that geo-tagging or retweeting are officially live, but when they are you will be able to use them immediately. You can download it here. It appears that geotagging data is starting to appear in responses, so this preview is a required update to properly deserialize responses to data classes. The following code snippets will help you make use of the geotagging API. The details are on Twitter’s wiki.

User profile changes
In order to use geo-tagging, the authenticating user must be enabled to use it. This status is indicated via the IsGeoEnabled property of the TwitterUser class.

var twitter = FluentTwitter.CreateRequest()
                .Users().ShowProfileFor(TWITTER_USERNAME)
                .Request();

var user = twitter.AsUser();
Console.WriteLine("User's geo enabled status: {0}", user.IsGeoEnabled);

Updating statuses with geotagging
To send statuses with geo-tagging data, you can use the From() extension method and pass in the latitude and longitude coordinates. You can also pass latitude and longitude in the Update() method overload.

var twitter = FluentTwitter.CreateRequest()
 .Statuses().Update("Checking out Twitter's upcoming geotagging from @tweetsharp")
 .From(37.78029, -122.39697)
 .AsJson();

Comparing geo-distances
The TwitterStatus class now possesses a Location property which is a GeoLocation class containing its latitude and longitude coordinates. You can use this information in your application to make decisions based on location using the GeoLocation extension methods.

var dimebrainHq = new GeoLocation(45.4235, -75.6979);
var twitterHq = new GeoLocation(37.78029, -122.39697);

// Get the distance between two locations
var miles = dimebrainHq.MilesFrom(twitterHq);

// Compare two locations by range,
// i.e. "Dimebrain HQ is within X miles of Twitter HQ"
var withinRange = dimebrainHq.IsWithin(miles, twitterHq);

// Additional extension methods let you convert miles to kilometers and yards
var closeEnoughToBike = dimebrainHq.IsWithin(20.Kilometers(), twitterHq);