Skip to content
This repository has been archived by the owner on Apr 15, 2023. It is now read-only.
Nick Hodge edited this page Dec 6, 2014 · 44 revisions

Welcome to BoxKite.Twitter

boxkite logo

BoxKite.Twitter is a .NET Library that provides an interface to Twitter API 1.1, licensed MS-PL.

Supporting Windows 8.x, Windows Phone 8.x and .NET 4.5.x Portable Class Libraries; it uses modern .NET development mechanisms async/await and Reactive Extensions.

Questions? You can find me on Twitter, of course! @RealNickHodge

##Copyright, License Information

BoxKite.Twitter was started by Brendan Forster (https://github.com/shiftkey/) as a part of a larger Twitter project now on permanent hiatus.

BoxKite.Twitter is Licensed under: MS-PL

Copyright: Nick Hodge and Brendan Forster 2012-2014

BoxKite Logo is Copyright 2012 Nick Hodge

##NuGet Package

BoxKite.Twitter listing on NuGet

Install-Package BoxKite.Twitter

Introduction

Written in C# as a Portable Class Library, BoxKite.Twitter uses two outstanding third party libraries: Newtonsoft's Json.NET and Microsoft's Portable version of the HTTP Client Libraries. Json.NET converts the incoming/outgoing data as JSON; and generates the objects. The Portable HTTP Client Libraries provides a single "view" of the underlying transport to the Twitter Service. OAuth and the creation of the REST GET/POST mechanisms are inbuilt into BoxKite.Twitter.

Additionally, BoxKite.Twitter uses two modern .NET mechanisms. Async/Await: which makes the programming of network access alarmingly easy and Microsoft's open sourced Reactive Extensions. The latter libraries provide a publish/subscribe model to data - especially streamed data.

There is a backstory on the project name

Twitter Connection

The central point of entry is the TwitterConnection route as described here which is still under completion as I test out different client scenarios.

See the code below for examples of the Low Level API

Twitter API Coverage

At the present time, BoxKite.Twitter supports the Twitter API version 1.1 of the following:

Extra Info and Documentation

Just Show Me Some Code Samples!

NOTE: these are based on BoxKite.Twitter 1.0.x

2.1 update coming

These are some snippets from a .NET 4.5 Console application, after installing BoxKite.Twitter via NuGet:

Example 1: Simple Get Tweets

System.Console.WriteLine("Welcome to BoxKite.Twitter from Console");

// Provide a platform specific adaptor for Web browser display and HMACSHA1
// example: https://github.com/nickhodge/BoxKite.Twitter/blob/master/src/Boxkite.Twitter.Console/Helpers/DesktopPlatformAdaptor.cs
// this class need to implement BoxKite.Twitter.IPlatformAdaptor
// source: https://github.com/nickhodge/BoxKite.Twitter/blob/master/src/BoxKite.Twitter/Interfaces/IPlatformAdaptor.cs
var desktopPlatformAdaptor = new DesktopPlatformAdaptor();

// Using consumerkey and consumersecret, start the OAuth1.0a process
var twitterauth = new TwitterAuthenticator(//CONSUMERKEYHERE//, //CONSUMERSECRETHERE//, desktopPlatformAdaptor);
var authstartok = await twitterauth.StartAuthentication();

// if OK
if (authstartok)
{
	// Now the User will see a Web browser asking them to log in to Twitter, authorise your app
	// and remember a PIN
	// This PIN is then entered here to complete the Authentication of the Credentials
	System.Console.Write("pin: ");
	var pin = System.Console.ReadLine();
	var twittercredentials = await twitterauth.ConfirmPin(pin);

	// Credentials OK, now OK to communicate with Twitter
	if (twittercredentials.Valid)
	{
		// Create a new "session" using the OK'd credentials and the platform specific stuff
		var session = new UserSession(twittercredentials, desktopPlatformAdaptor);

		// Let's check the user is OK
		var checkUser = await session.GetVerifyCredentials();
		if (checkUser.OK)
		{
			System.Console.WriteLine(twittercredentials.ScreenName +
				" is authorised to use BoxKite.Twitter.");

			// START GOOD STUFF HAPPENS HERE	
			// grab the latest 10 mentions for the Auth'd user
			var mentionslist = await session.GetMentions(count: 10);

			foreach (var tweet in mentionslist)
			{
				System.Console.WriteLine(String.Format("ScreenName: {0}, Tweet: {1}", tweet.User.ScreenName,
					tweet.Text));
			}
			// END GOOD STUFF HAPPENS HERE
		}
		else
		{
			System.Console.WriteLine("Credentials could not be verified");
		}
	}
	else
	{
		System.Console.WriteLine(
			"Authenticator could not start. Do you have the correct Client/Consumer IDs and secrets?");
	}
	System.Console.WriteLine("Press return to exit");
	System.Console.ReadLine();
}

This example starts a fresh client authentication, including the Twitter OAuth1.0a PIN login flow. Then it displays the most recent 10 mentions for the authenticated user.

Note that the twittercredentials can be saved (please do this in a secure fashion) and be re-used, so much of the OAuth 'ceremony' is once-off.

The other thing to note is the DesktopPlatformAdaptor. Portable Class Libraries have limits; so to provide an interface to the underlying operating system, BoxKite.Twitter uses an Interface mechanism.

A platform adaptor must implement the BoxKite.Twitter.IPlatformAdaptor interface; and example Desktop adaptor is here

As at BoxKite.Twitter 0.8.0, there is a .NET 4.5 Full version that has the IPlatformAdaptor "pre-installed" to make starting out quicker. No need to create them yourself and pass them in.

Try out the intellisense when typing var mentionslist = session. you will see all of the Low Level API calls available in BoxKite.Twitter.

Example 2: Upload a new Avatar

(note: only the code between the // START ... //END GOOD STUFF HAPPENS HERE from Example 1 is shown)

var fileName = "C:\\Users\\Nick\\Pictures\\My Online Avatars\\666.jpg";
if (File.Exists(fileName))
{
	var newImage = File.ReadAllBytes(fileName);

	var uploadedimage = await session.ChangeAccountProfileImage(Path.GetFileName(fileName), newImage);

	if (uploadedimage.twitterFaulted)
	{
		System.Console.WriteLine(String.Format("Twitter Error: {0} {1}",
		uploadedimage.TwitterControlMessage.twitter_error_code,
		uploadedimage.TwitterControlMessage.twitter_error_message));
	}
	else
	{
		System.Console.WriteLine("All is well");
	}
}

Example 2a Send Tweet with Image, using a FileStream

var fileName = /* some file path here */;

using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{                               
	var tw = await session.SendTweetWithImage(/* Text of tweet in here */, Path.GetFileName(fileName), fileStream);

	if (tw.OK)
	{
		System.Console.WriteLine(String.Format("Tweet sent: ScreenName: {0}, Tweet: {1}", tw.User.ScreenName, tw.Text))
	}

}

These examples takes a picture from the local file system, and uploads it to Twitter. The current authenticated user's Avatar changes to the new image.

Also shown is the error mechanism. Rather than throwing exceptions everywhere, which makes it difficult to finely manage REST responses, each response to a BoxKite.Twitter call can quickly check:

uploadedimage.twitterFaulted and, if you prefer your dev positive uploadimage.OK (the latter is just the opposite what whatever twitterFaulted is)

Any ways, if twitterFaulted is true, something is wrong. The attached TwitterControlMessage can be interrogated to determine what is going on.

A good example of a potential response is a "Rate Limit Exceeded" error. The TwitterControlMessage will be populated with enough information for your app to do something intelligent rather than eating all of the exceptions.

Example 3: User Streams

(note: only the code between the // START ... ``//END GOOD STUFF HAPPENS HERE` from Example 1 is shown)

userstream = session.GetUserStream();
userstream.Tweets.Subscribe(t => System.Console.WriteLine(String.Format("ScreenName: {0}, Tweet: {1}", t.User.ScreenName, t.Text)));

while (userstream.IsActive)
{
	 Thread.Sleep(TimeSpan.FromSeconds(0.5));
} 

What is even going on here?

Here, again once the session has been authenticated, we can create a UserStream.

The userstream.Tweets.Subscribe... uses the Reactive Extensions to "listen" for published tweets. BoxKite.Twitter sends the lambda t=> ... mechanism iterates or works with each tweet in turn.

There are other things that can be .Subscribed to from the userstream including DirectMessages, etc.

Example 4: Search Streams

(note: only the code between the // START ... //END GOOD STUFF HAPPENS HERE from Example 1 is shown)

searchstream = session.StartSearchStream(track: "xbox");
searchstream.FoundTweets.Subscribe(t => System.Console.WriteLine(String.Format("ScreenName: {0}, Tweet: {1}", t.User.ScreenName, t.Text)));

while (searchstream.IsActive)
{
	Thread.Sleep(TimeSpan.FromMinutes(3));
	var sr = new StreamSearchRequest();
	sr.tracks.Add("windows8");
	searchstream.SearchRequests.Publish(sr);
} 

Similar to Example 3, this creates a SearchStream from an authenticated session. Again, using the Reactive Extensions Publish/Subscribe mechanism.

The "track: xbox" is quite self explanatory; in the while loop, we wait for 3 minutes before changing the Search request. You will see the resulting tweets in the stream change.

Example 5:

(note: only the code between the // START ... //END GOOD STUFF HAPPENS HERE from Example 1 is shown)

// note: longitude,latitude of SW corner - longitude,latitude of NE corner "bounding box"
var sydneybounds = new List<string> { "150.700493", "-34.081953", "151.284828", "-33.593316" };

searchstream = session.StartSearchStream(locations: sydneybounds);

var tweetcount = 0;
double minutes = 10;
searchstream.FoundTweets.Subscribe(t =>
								   {
									   System.Console.WriteLine(String.Format("ScreenName: {0}, Tweet: {1}", t.User.ScreenName, t.Text));
									   tweetcount++;
								   });

while (searchstream.IsActive)
{
	Thread.Sleep(TimeSpan.FromMinutes(minutes));
	searchstream.Stop();
	double twpm = tweetcount / minutes;
	double twps = twpm / 60;
	System.Console.WriteLine(String.Format("Tweets per minute: {0}", twpm.ToString("0,0.00")));
	System.Console.WriteLine(String.Format("Tweets per second: {0}", twps.ToString("0,0.00")));
}

Similar to Example 4, this shows using the Locations SearchStreaming capabilities of Twitter.

Note the format of the Latitude and Longitude; this is in correct form for Twitter: Longitude first, Latitude second.

I've also added a quick tweet rate measurement mechanism into this example. So far, the highest rate of out I've tested is 48 tweets per second being ingested by BoxKite.Twitter