Creating a custom image service for Twitter for iPhone Tweetbot

Update Jan 13, 2012: It looks like setting a custom image service is no longer available on Twitter for iPhone. Tweetbot allows it though. This article still works for Tweetbot. For the rest of this article, please treat the text “Twitter for iPhone” as any app that supports custom image services (e.g. Tweetbot).

We’ve just recently deployed a custom endpoint to allow Twitter for iPhone users to post their pics through PicLyf.

When you attach an image to a tweet, Twitter for iPhone will upload that image to the image service of your choice. It allows you to choose from various image services (e.g. yFrog, Twitpic, TweetPhoto) or a custom image service. In our (PicLyf) case, it was custom. We made a custom endpoint: http://api.piclyf.com/twitter. Using this url as the custom image service, attached images will be uploaded to the user’s PicLyf account.

Implementation

This functionality works through the use of OAuth Echo. From Twitter:

OAuth Echo is a means to securely delegate OAuth authorization with a third party while interacting with an API. Within the Twitter ecosystem, we use OAuth Echo as a means to allow your application to use services such as Twitpic and yfrog.

You may want to read about OAuth Echo first. Basically, Twitter for iPhone sends you the image along with the OAuth credentials of the user who wants to upload the image. Note that the OAuth credentials also includes the app’s consumer key. What you’ll have to do is use these credentials and verify them with the Twitter API. If the verification succeeds, you will receive the user’s Twitter information. You may then save the image in your server and link it with the user’s Twitter account. Lastly, you will have to return the correct response to Twitter for iPhone specifying the url where the image can be viewed:

<mediaurl>http://foo.com/bar/pic-url.html</mediaurl>

Sample code in PHP

Here is a sample class which encapsulates the OAuth Echo process:

class TwitterOAuthEcho
{
  public $verificationUrl = 'https://api.twitter.com/1/account/verify_credentials.json';
  public $userAgent = __CLASS__;

  public $verificationCredentials;

  /**
   *
   * @var int
   */
  public $resultHttpCode;
  /**
   *
   * @var array
   */
  public $resultHttpInfo;
  public $responseText;

  /**
   * Save the OAuth credentials sent by the Consumer (e.g. Twitter for iPhone, Twitterrific)
   */
  public function setCredentialsFromRequestHeaders()
  {    
    $this->verificationCredentials = isset($_SERVER['HTTP_X_VERIFY_CREDENTIALS_AUTHORIZATION']) 
      ? $_SERVER['HTTP_X_VERIFY_CREDENTIALS_AUTHORIZATION'] : '';
  }

  /**
   * Verify the given OAuth credentials with Twitter
   * @return boolean
   */
  public function verify()
  {
    $curl = curl_init($this->verificationUrl);
    curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'Authorization: ' . $this->verificationCredentials,
      ));

    $this->responseText = curl_exec($curl);
    $this->resultHttpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $this->resultHttpInfo = curl_getinfo($curl);
    curl_close($curl);

    return $this->resultHttpCode == 200;
  }
}

The setCredentialsFromRequestHeaders method saves the OAuth credentials sent by the consumer (e.g. Twitter for iPhone, Twitterrific). These credentials will be used in the verify method which sends the verification request to Twitter.

Using the class above, your custom image service page (e.g. http://api.piclyf.com/twitter) should handle the request like this:

$oauthecho = new TwitterOAuthEcho();
$oauthecho->userAgent = 'My Custom Image Service App 1.0';
$oauthecho->setCredentialsFromRequestHeaders();
if ($oauthecho->verify()) {      
  // Verification was a success, we should be able to access the user's Twitter info from the responseText.
  $userInfo = json_decode($oauthecho->responseText, true);
  $twitterId = isset($userInfo['id']) ? $userInfo['id'] : null;      
  // You can use $userInfo or $twitterId above to maybe check if you have a record of this user
  // in your db.

  // You can access the uploaded image using $_FILES. Save it and create a url where it can be accessed.

  // Return the image url back to the consumer
  $imagePageUrl = 'http://somwhere.com/image1';
  echo '<mediaurl>' . $imagePageUrl . '</mediaurl>';

} else {
  // verification failed, we should return the error back to the consumer
  $response = json_decode($oauthecho->responseText, true);      
  $message = isset($response['error']) ? $response['error'] : null;      
  if (!headers_sent())
    header('HTTP/1.0 ' . $oauthecho->resultHttpCode);
  echo $message;
}

The code above is just a sample and your final code will look very different especially if you’re using a framework. I’ve also left out the part where you’ll get the image from $_FILES and save/process it. That is beyond the scope of this article.

Notes

The note in Twitter for iPhone’s custom image service screen says you can get more (developer) info in this url: http://developer.atebits.com. As of this writing, the information on that page is no longer accurate. Twitter for iPhone no longer sends you the user’s username and password. The info at Twitterrific is more accurate. And yes, if your service works for Twitter for iPhone, it should work on Twitterrific too.

Further reading:

  • vic

    Thank you very much! It’s an awesome post! ;-)

  • louk

    Very well documented and useful post! thanks dude!

  • Brendan

    Works well! Thanks! Only one thing though.. How do you get the current tweet that was tweeted? The userInfo only has the last tweet and the user’s info stored in the json response..

  • Shiki

    Hi Brendan, it’s sent by Twitter for iPhone. You can get it from $_POST['message'].

  • Pingback: Tweets that mention OAuth Echoとな。 -- Topsy.com

  • http://twitter.com/stressfree stressfree

    Anyone knows if any other Twitter clients support configuring custom image services? I know only of Twitterrific and Twitter for iPhone.

    I’m interested in finding out if other apps support this. Specially for other platfoms like Andrioid, Blackberry, Windows Phone 7, Symbian, etc.

  • Ravnda

    Hi, very nice article. One question, is there a way I can get twitter to recognize my link as a picture?( LIke yfrog and twitpic).

  • Shiki

    @Ravnda if you’re talking about the preview pane in twitter.com, I think they only support selected content providers: http://www.quora.com/When-will-Twitter-open-up-embedding-of-third-party-content-in-the-slide-out-pane

  • Cabal2002

    Hi,

    cant get this to work OAUTH seems to be the culprit here is what the request looks like

    OAuth oauth_timestamp=\”1318347386\”, oauth_version=\”1.0\”, oauth_consumer_key=\”IQKbxxxxxxxxxxxxxxxHUA\”, oauth_token=\”1xxxxxxx5-wT2yyns04jBSGzFCgIcxxxxxxxxxxxxxxxxxxYrD\”, oauth_signature=\”Jaeq%2F0U3xxxxxxxxxxxxxxxxxxo%3D\”, oauth_nonce=\”0BEDxxxx-3B95-4EEA-xxxx-0EC3Bxxxx41D\”, oauth_signature_method=\”HMAC-SHA1\”

    The reply from twitter is: Status: 401 Unauthorized\r\n Could not authenticate with OAuth.

    Can someone please help me?

    Regards Cabal

  • Cabal

    It should be noted that the response in the example is incomplete. A complete response would be: abc123 http://twitpic.com/abc123

  • Cabal

    After upgrading to IOS5 this doesnt work anymore when using the official Twitter App see https://dev.twitter.com/discussions/2933. It is still not clear to me wether this is a Bug in the Twitter App or by design. Twitteriffic is still able to upload images via custom image service. It might be possible that this is related to the tight integration of twitter into IOS.

  • Shiki

    @Cabal thanks for the info dude. I’ll also look into this.

  • ASK

    Thanks for this excellent article and code sample. Anxious to launch my own custom image upload, but will have to wait until the iOS5 thing gets straightened out… apparently, it is a bug in the Twitter app.

    https://dev.twitter.com/discussions/2933

  • http://twitter.com/alienvenom alienvenom

    Does anyone have a fix for this for iOS 5?

  • cham

    The image upload’s custom field is disabled in Twitter for iPhone ver. 4.0.1.

    OMG.

  • Shiki

    Hi guys, thank you for the feedback.

    It looks like custom image services is no longer available on the Twitter app (at least on the iPad). I was however able to test this on Tweetbot (iOS 5) and it still works.