Manage your Twitter Friends and Followers with Tweetsharp – Part 2 – Refactoring
In Part 1 we covered getting all of our friends and followers then using LINQ to find users who appeared in only one or the other collections.
However, the code to fetch followers and friends had a lot of duplication in it because they both use cursors to page through the results, and require a loop and some cursor management code to make sure we get all the results.
We can take care of that duplication by moving all the cursor stuff into a generic method that uses its generic type parameter a lambda expression to take care of the context-specific stuff:
static IEnumerable<T> GetAllCursorValues<T>(ITwitterLeafNode twitter, Func<string, IEnumerable<T>> conversionMethod)
{
long? nextCursor = -1 ;
var ret = new List<T>();
do
{
twitter.Root.Parameters.Cursor = nextCursor;
var response = twitter.Request();
IEnumerable<T> values = conversionMethod(response);
if (values != null)
{
ret.AddRange(values);
}
nextCursor = response.AsNextCursor();
} while (nextCursor.HasValue && nextCursor.Value != 0);
return ret;
}
This method will work with any of the APIs that use cursors. The type parameter T represents the type of object you expect to get back (as an IEnumerable) -in our case we’re expecting TwitterUser, and the conversionMethod is the method that deserializes the response into the expected format – in our case we we’re using the AsUsers method.
Note that we’ve “opted-out” of the fluent nature of the Tweetsharp interface and we’re setting the Cursor property directly on the Parameters object of the root FluentTwitter instance.
So, the code to get friends and followers is now a lot cleaner, we can omit all of the cursor stuff from it and use our new method to handle that:
//create the tweetsharp request to get followers
//omit any cursor stuff as that's handled by the GetAllCursorValues method
var getFollowersReq = FluentTwitter.CreateRequest()
.AuthenticateAs(_userName, _password)
.Users().GetFollowers()
.AsJson();
//call our new method to get all of the values back - will make multiple calls if necessary
var followers = GetAllCursorValues(getFollowersReq , response => response.AsUsers());
//do the same to get friends.
var getFriendsReq = FluentTwitter.CreateRequest()
.AuthenticateAs(_userName, _password)
.Users().GetFriends()
.AsJson();
var followers = GetAllCursorValues(getFriendsReq , response => response.AsUsers());
//again, use the LINQ extension methods on IEnumerable<T> to get the differences between the two lists
var jerks = friends.Except(followers);
var spammers = followers.Except(friends);
Much nicer.
Now that that’s taken care of, we need some user interface – we’ll do that in Part 3.