PHP + Twitter + Google Calendar + SMS

Working on a little side project, I wanted to be able to add an event to Google Calendar by text message like our American friends can using GVENT. I figured I could hook my Twitter account up to Google Calendar using their APIs. I tinkered with it for a couple of hours and it works!

Background

If you don’t know about Twitter, it’s a free service that allows you to share messages with your network of friends by a number of means, which includes via text messages sent to Twitter from your mobile phone.

Twitter has this useful feature called direct messages. It enables private messaging between friends over the Twitter system, provided you and your friend are following each other on Twitter. This means that you can send a message over the system without it turning up in your public time line of messages – your ‘tweets’. You just put a letter ‘D’ and your friend’s Twitter username in front of your message and send. So, I can send a text message to Jon via Twitter like this “d jontangerine Why, I’d love tangerines by post! Thank you!”

How is this useful for adding an event to Google Calendar? Well, a short text message is all I need to add an event using Google Calendar’s really smart Quick Add feature. A script set up to periodically check for new direct messages via the Twitter API can take the body of any message and pass it to the Google Calendar API.

It’s a bit round about in implementation, but it allows you to update a Google Calendar by SMS. In fact, you could use any Twitter-ing interface (Twitter.com, Twitterific), but then you may as well Quick Add your event with Quicksilver (Mac users) or some other widget or even – shock horror – sign into the Google Calendar site!

Obviously, I’m not the only person who’s thought of hooking up the APIs; Twittercal will give you basic functionality if that’s all you need. It doesn’t allow you to post to any calendar other than your default one, which wasn’t useful for my application, and I wanted to be able to do a bit of processing in PHP before posting the event to the calendar.

Twitter to PHP

So, I can set up a new Twitter account for my application, become friends with it (!) and send messages to it. That’s a good start. Now I need a PHP script that listens in for new direct messages on my new Twitter account.

To interact with Twitter, it helps to be familiar with the Twitter API. You might also find a wrapper for the Twitter API useful. It’s not entirely necessary, but will save you a bit of time. Here’s one David Billingham made earlier: Twitter PHP Library (Ver 0.1). It’s not complete, but it’s a good start.

I’ll not use the library for now so that I can show you how to talk to Twitter using our friendly PHP CURL functions.

  1. Set yourself up with an account for your application. Follow the new account and make sure it’s following you as well. Direct messages won’t work unless the feeling’s mutual!
  2. Grab the code below and save it to a new file on your Web server, e.g. “tcal.php”. The code is commented to guide you through what it does.
  3. Set TWITTER_CREDENTIALS to your application’s Twitter username and password.
  4. Make sure you have some direct messages sent to the Twitter account. Try sending it a test message, something like “d yourapp Smashing Pumpkins in The O2 Arena on Saturday at 7pm”.
  5. Run the script and you should see your messages in XML.
<?php

// Define credentials for the Twitter account define('TWITTER_CREDENTIALS', 'twitter_username:twitter_password');
// Set up CURL with the Twitter URL and some options $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/direct_messages.xml'); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Twitter uses HTTP authentication, so tell CURL to send our Twitter account details curl_setopt($ch, CURLOPT_USERPWD, TWITTER_CREDENTIALS);
// Execute the curl process and then close $data = curl_exec($ch); curl_close($ch);
// If nothing went wrong, we should now have some XML data echo '<pre>'.htmlentities(print_r($data, true)).'</pre>';
?>

Using a library obviously tidies things up and should provide some built-in error checking and return an XML object to us. You can use the library I mentioned earlier, but you’ll need make sure you add your Twitter account details to the class. We end up with this:

<?php

// The Twitter library require_once 'twitter.class.php';
// Create a new Twitter object and query for direct messages $twitter = new Twitter(); $direct_messages = $twitter->directMessages();
// We should now have some XML data in an object echo '<pre>'.htmlentities(print_r($direct_messages, true)).'</pre>';
?>

Okay, now we have a nice XML object to work with.

Google Calendar from PHP

Now we’re tuned into Twitter, we want to send any messages on to Google Calendar.

The Google Calendar API is a Google data (GData) API. The easiest way to interact with Google Calendar in PHP is with Zend’s standalone GData client library. This library also comes as part of the Zend Framework, but unless your application uses the framework already, it’s a bit of a sledgehammer!

The GData client library needs PHP version 5.1.4 or higher. If you want PHP 4 compatibility, this might make life a bit harder for you. PHP 4 coming to the end of its life and support for it ceased at the end of 2007. If you’re not yet using PHP 5, I strongly suggest your developments move towards using it.

After downloading the client library and installing the ‘Zend’ directory somewhere useful in your application, you can start to use it! Try adding this chunk of code in place of where we echoed the XML data from Twitter. Again, the comments tell you what’s going on.

<?php

// Define credentials for the Google Calendar account define('GCAL_USER', 'google_user@example.com'); define('GCAL_PASS', 'google_password');
// If you need to target a specific calendar, uncomment and enter // its calendar ID here. The calendar ID is available on the // calendar settings page, next to the Calendar Address buttons. //define('GCAL_ID', '[hash]@group.calendar.google.com');
// Include Zend GData client library require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); Zend_Loader::loadClass('Zend_Gdata_Calendar');
// Get Google Calendar service name (predefined service name for calendar) $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
// Authenticate with Google Calendar $client = Zend_Gdata_ClientLogin::getHttpClient(GCAL_USER, GCAL_PASS, $service);
// Iterate through the direct messages we got from Twitter foreach ($direct_messages as $dm) { $message = (string)$dm->text;
// If you echo the message body here, you'll notice that the // extraneous text is removed from its beginning for us //echo $message;continue;
// You could do some processing here if you wanted; // e.g. allow only direct messages from certain users detect // a particular flag or message format for processing
// Create a new Google Calendar object $calendar = new Zend_Gdata_Calendar($client);
// Create a new event $event = $calendar->newEventEntry();
// Make it a Quick Add event $event->quickAdd = $calendar->newQuickAdd('true');
// Add our message as the event content $event->content = $calendar->newContent($message);
// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Play nice and ensure there's a wait between calls sleep(1); }
?>

Running that should post your direct message on to Google Calendar and, provided Google Calendar understood your message, a new event will be added.

Once we’ve used the message, we don’t want it to get picked up and processed when the script is next run. We can delete a message using the Twitter API, but we’ll need to add something to the Twitter library we’ve been using. The following function can be added to the Twitter class to allow us to delete a direct message using its ID. I put this in after the other direct message functions.

<?php	// ...

/** * Deletes a direct message */ function deleteDirectMessage($id) { if (!is_numeric($id)) { return false; } $request = 'http://twitter.com/direct_messages/destroy/'.$id.'.xml'; return $this->process($request); }
// ... ?>

Now we just call this new method of the Twitter class to delete the message once we’re done with it.

<?php	// ...

// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Delete the direct message $twitter->deleteDirectMessage((integer)$dm->id);

// Play nice and ensure there's a wait between calls sleep(1); }
?>

And we’re done! All that’s left to do it set up a cron job on a server to run our script periodically.

I advise not running the script too often – bombarding the Twitter servers. I set mine to run every 20 minutes, but from what I’ve read you should be able to run it every minute without any trouble. If you’re going to be doing anything particularly intensive, you should probably contact Twitter first.

Here’s the code in full. Enjoy!

<?php

// Define credentials for the Google Calendar account define('GCAL_USER', 'google_user@example.com'); define('GCAL_PASS', 'google_password');
// If you need to target a specific calendar, uncomment and enter // its calendar ID here. The calendar ID is available on the // calendar settings page, next to the Calendar Address buttons. //define('GCAL_ID', '[hash]@group.calendar.google.com');
// The Twitter library // Make sure you've set your Twitter username and password and // added the function deleteDirectMessage() require_once 'twitter.class.php';
// Include Zend GData client library require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata'); Zend_Loader::loadClass('Zend_Gdata_ClientLogin'); Zend_Loader::loadClass('Zend_Gdata_Calendar');
// Create a new Twitter object and query for direct messages $twitter = new Twitter(); $direct_messages = $twitter->directMessages();
// Get Google Calendar service name (predefined service name for calendar) $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
// Authenticate with Google Calendar $client = Zend_Gdata_ClientLogin::getHttpClient(GCAL_USER, GCAL_PASS, $service);
// Iterate through the direct messages we got from Twitter foreach ($direct_messages as $dm) { $message = (string)$dm->text;
// If you echo the message body here, you'll notice that the // extraneous text is removed from its beginning for us //echo $message;continue;
// You could do some processing here if you wanted; // e.g. allow only direct messages from certain users detect // a particular flag or message format for processing
// Create a new Google Calendar object $calendar = new Zend_Gdata_Calendar($client);
// Create a new event $event = $calendar->newEventEntry();
// Make it a Quick Add event $event->quickAdd = $calendar->newQuickAdd('true');
// Add our message as the event content $event->content = $calendar->newContent($message);
// Send the new event to be added to Google Calendar if (defined('GCAL_ID')) { $newEvent = $calendar->insertEvent($event, 'http://www.google.com/calendar/feeds/'.GCAL_ID.'/private/full'); } else { $newEvent = $calendar->insertEvent($event); }
// Delete the direct message $twitter->deleteDirectMessage((integer)$dm->id);
// Play nice and ensure there's a wait between calls sleep(1); }
?>

Related