Creating A Twitter Integration
I have been doing some work using Twitter as a notification mechanism for case events taking place in Dovetail CRM. I also wanted to expose an API of sorts driven by Twitter direct messages which would allow support agents to work on cases via Twitter. I created a twitter account for Dovetail and went crazy. To the right is a screen shot of my favorite twitter client showing me being notified of a case created by a customer and accepting it via Twitter.
This goal of this post is a brain dump what I have learned so far on my journey into Twitterland.
Twitter? – what is this Twitter you speak of
Twitter is a micro-blogging service on which you can post short messages called tweets. People usually post what they are up to, thinking about, and sadly what clothing they are putting on their cats. You can also follow other Twitter users and see their tweets as a timeline. When two Twitter users are following each other they are considered friends and can send direct messages to each other. It seems that most people currently use twitter as a mix of social networking and instant messaging.
I have been a Twitter user for almost a year and seen my usage grow quickly as many people I know are embracing the medium. Personally, I use Twitter to keep up-to-date with what my friends and colleagues are doing to while I am at the computer (using Twhirl) and away from the computer (using SMS). These days I am instant messaging less and less and twittering more and more.
It’s a messaging platform
The beauty of Twitter is its flexibility as a messaging bus. You can easily get data into and out of Twitter. You can start out using their Web site. Add your phone as a SMS device or an Instant Messenger client to receive notifications when certain special twitterers tweet. I like to catch up with my missed Tweets via RSS feed. If you are a geek like me you could write a program that talks to the Twitter HTTP API.
A great example of a company integrating with Twitter is Remember The Milk (RTM). I use RTM to keep track stuff I need to get done. Send their Twitter user a direct message and they create a task for you.
As an Agent I want to be notified via Twitter when a case is dispatched to the support queue to improve customer response time by being constantly aware of new support cases.
Doing this was easy as I was able to leverage our integration with Campfire. Dovetail CRM has a windows service called RuleManager that can invoke actions based on application events. We already have a rule that fires when a case is dispatched to our support queue so all I had to do was added a new action on that rule that invokes a script. Sam Tyson wrote a script that basically sends a direct message to the twitter account of each queue member. We map their Dovetail CRM account to a twitter screen name using a custom field on the user table.
The bit of code that sends the direct message is actually shelling out to a handy command line utility for automating HTTP interactions called cURL. I just followed the instructions on the Twitter API Documentation Google Group. Here is a command line that sends a direct message using cURL:
curl -u <sender>:<password> -d text="<message>" -d user="<recipient>" http://twitter.com/direct_messages/new.xml
Essentially we ended up with a script that sends a direct message to all queue members that are twitter users.
We are not quite done though. It is important to know if someone already accepted the case we were notified about.
As an Agent I want to be notified when a case has been accepted so that I do not duplicate effort that another support agent whose initiative is faster than mine.
Our system already has a rule present for the accept case event. With the script we already wrote in our pocket all we need to do is add an action to the accept case rule. And we get this…
Taking action via Twitter
As a Twitter using support agent I want to be able to accept, close, and log notes to cases via Twitter so that I can work on cases while away from a PC.
We brainstormed up functionality that we would expose to twitter. Below are the commands we currently support and what their responses look like.
- Help – what you get if we don’t understand what you are saying (looks best with line returns).
- Accept <caseId>
- Log <caseId> <notes> – logging a note to a case
- Close <caseId> <optional notes>
How did he do that?
This story requires that we have a Twitter automaton hanging around listening for direct messages from our followers that are Dovetail CRM users. Basically I poll for direct messages sent to our Dovetail Twitter user and parse the message body. If I find a command such as Accept 1234. I invoke our Dovetail SDK Accept Case API as the message sender’s clarify user. Delete the direct message and continue.
I didn’t want to write my own direct message handling code so I looked into using a Twitter library. There are plenty of libraries out there for your favorite languages. I have worked with two .Net libraries. I started with twitterbots ran into some issues and moved to the Witty client’s – TwitterLib.
A first look twitterbots seems like a great fit for me. it is open source has tests, had seams exposed to make testing easier and it is setup specifically as a Twitter bot framework. Everything worked great but I quickly ran into throttling issues as it seems that the twitterbots framework is quite chatty and Twitter has a 70 request per hour limit against their HTTP API. It seems that the people that wrote twitterbots have an exemption from throttling as they are geared for disaster response and will have spiky usage. Also their logging framework was coupled to Linq over Entities.
Witty is a WPF based Twitter client. It is opensource-ish and pretty and is improving but I’ll stick with Twhirl. Witty has all of their Twitter HTTP service calls contained in an assembly called TwitterLib. Thanks Scott Hansleman for pointing this out to me.
I do have concerns about TwitterLib their direct message object is not really treated as a domain object it is more like a user interface data transfer object. I would rather it be a plain old C# object (POCO) as I don’t plan on displaying it to a user.
Worse yet the TwitterNet class has Get<X> methods that return collections which are coupled to doing persistence. If I call RetrieveMessages() it tries to save direct messages to a file. A terrible separation of concerns. How do you unit test this? Most likely you don’t. I commented out couplings to XAML and persistence in their collection classes. If I stick with this library I hope to submit a patch decoupling their domain objects from at least persistence if not user interface concerns.
While using the Twitter HTTP API works fine. The 70 HTTP request per hour limit (every 52 seconds on average) is a real barrier to using this API to poll for direct messages. I quickly realized that we would get throttled while trying to be responsive and if a spike in activity happens we would quickly exceed the limit. It is really no fun to get a HTTP Status of 400 telling you that you have been throttled.
My next direction is to explore using XMPP (a.k.a Jabber) to send and receive direct messages to hopefully overcome the throttling issue. I am going to start with jabber-net and see where it takes me.
What kind of Twitter integrations do you want to write?