Weekend hack: Posting to Twitter via SMS in China

twitter-smsTwitter provides phone numbers to allow you to update your status via SMS. Unfortunately, local numbers are only available in a few countries: the US, Canada and India. Elsewhere, you need to text their international number in the UK, which can be quite expensive. ReignDesign is based in Shanghai, China - so how to update Twitter for the price of a local SMS? Via a local Twitter-like service Fanfou.com, and a simple PHP script, it's possible!

Step 1 - Sign up for Fanfou.com

Go to http://fanfou.com/register. The image below shows what to enter in each field. You'll receive a confirmation email with a link to click to verify your email.

register

At the next step, you're prompted to enter IM information. For now, click the Skip link (circled below).

skip

You can also skip the suggested friends page.

suggestedusers

As you've used Twitter, you'll find Fanfou's interface very familiar! You should go into the settings menu and set your "web address" (public URL). This can be the same as your username.

web-address

Step 2 - Connect your mobile phone with Fanfou

Go to settings > mobile phone, and enter your mobile phone number.

phone

When you click the button to confirm, you'll receive a small popup like this. You need to text the four-letter code to the number indicated to confirm that the mobile phone is yours. The number depends on whether you're using China Mobile or China Unicom. It's the same number you'll use to update your Fanfou (and Twitter) status!

code

Step 3 - Post an update to Fanfou

Send a text to the Fanfou number from your phone. Check it appears in your public timeline at http://fanfou.com/home. You may notice that the update is in ALL CAPS. This seems to be a Fanfou bug, we'll work around this in our PHP script.

all-caps

Step 4a - Sync your Fanfou updates to Twitter (the simple way)

This is the final and most important step. We want to get our updates from Fanfou to Twitter. Both Fanfou and Twitter provide APIs for getting and setting statuses, we just need to glue them together.

One simple way is to use a service like Twitterfeed. Twitterfeed will read an RSS feed and post to Twitter each time it detects a new item.

Your RSS feed is in the form
http://api.fanfou.com/statuses/user_timeline/exampleuser.rss, replacing exampleuser with your public name. If you're asked for a password when you view that page, check you set your public name correctly in Step 1. You can enter this URL into Twitterfeed and set it to post to your Twitter account automatically.

There are a few problems with this however:

  • Twitterfeed only updates once an hour
  • Your customisation options are limited (for example, it would be nice to remove the ALL CAPS).

Step 4b - Sync your Fanfou updates to Twitter (the better way)

If you have a web hosting account that lets you run regular scripts (cronjobs), you can write a simple script to update Twitter from Fanfou as often as you like, using Fanfou's and Twitter's REST APIs. I created this simple PHP script on my Bluehost account. It's run every 2 minutes.

Requirements: PHP 5 with CURL, David Grudl's PHP Twitter library.

  1.  
  2. <?
  3. require('Twitter.class.php'); // from http://phpfashion.com/twitter-for-php
  4. //replace with your credentials
  5. $fanfou_username="exampleuser";
  6. $twitter_username = "exampleuser";
  7. $twitter_password="yourpassword";
  8.  
  9. //check what the id of your last fanfou update was
  10. $id=file_get_contents($fanfou_username.".last");
  11. //grab the latest update from Fanfou in XML format
  12. $url='http://api.fanfou.com/statuses/user_timeline.xml?id='.$fanfou_username.'&count=1';
  13. $buffer=getContentsOfUrl($url);
  14. if (empty($buffer)) {
  15. die("ERROR failed to get fanfou statusn");
  16. }
  17.  
  18. //parse the xml
  19. $xml = simplexml_load_string($buffer);
  20. $newid= (string)$xml->status->id; //must cast to string here
  21. $text= (string)$xml->status->text; //must cast to string here
  22. $text=strtolower($text); //fanfou uses all caps
  23.  
  24. //we only need to update twitter if the status id has changed
  25. if ($id!==$newid) {
  26. echo ("INFO new status: ".$text);
  27. $t = new Twitter($twitter_username,$twitter_password);
  28. if ($t->send($text)) {
  29. echo("updated twitter");
  30. file_put_contents($fanfou_username.".last",$newid); //store the id to a file for next time
  31. } else {
  32. echo("ERROR could not update twitter");
  33. }
  34. } else {
  35. echo ("INFO status has not changed");
  36. }
  37.  
  38.  
  39. //simple function to get contents of an URL as a string using CURL
  40. function getContentsOfUrl($url) {
  41. $curl_handle = curl_init();
  42. curl_setopt($curl_handle, CURLOPT_URL, $url);
  43. curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
  44. curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
  45. curl_setopt($curl_handle, CURLOPT_GET, 1);
  46. $buffer = curl_exec($curl_handle);
  47. curl_close($curl_handle);
  48. return $buffer;
  49. }
  50.  

We load the latest status from Fanfou in XML format, and check if the id has changed since last time we checked (this is stored in a file called username.last - you will need to set the permissions on this file to allow writing by the web server user). If the id has changed, we post the text of the update to Twitter.

Sure, we could add more robust error handling, and cope with the situation but this is just a quick hack, and works pretty well. There are obviously lots of ways you could extend the script to do more interesting things. Let me know of any cool ideas in the comments!

Thanks to J. Wan for the idea, and Panda Passport for inspiration.

4 Comments

  1. John | August 25th, 2009

    Bad timing… It would appear that Fanfou has been shut down by the powers that be.

    Would you consider doing another similar article for Zuosa.com or another similar service?

  2. Matt Mayer Matt Mayer | August 25th, 2009

    Yes indeed :( Will check out some of the alternative sites and try an updated blog post :)

    Matt

  3. Matt Mayer | August 29th, 2009

Post a Comment