DABR Twitter Web Client Mini Blog Yo Mama Jokes Sports Bookmarklets About Us

November 24, 2009

Expanding DABR Photo-Upload options



 

One of the most underrated parts of Dabr IMO is the Twitpic upload page. It allows you to interact with a Twitter helper service that uses the same login information as your twitter account. And since Twitter has speced out how the uploadAndPost process works, lots of other Twitter helper services use it in their API – such as YFrog, Twitgoo, Twitvid, and Posterous (which slickly reverse matches your autopost-twitter information in order to validate your posterous account). But Posterous is pretty slick all around – probably the best tumble blog/micro blog/media blog service out there and certainly the most expandable. Perhaps in the future I might try to integrate some more later.

Dabr photo upload twitpic yfrog twitgoo twitvid posterous imgurAnyways, I figure I’d give it a go to add some more services to the twitpic page – keyed off a service dropdown. The hardest part in reality was managing the options allowed by each service (i.e. URL upload instead of file upload, additional message body). In addition, I wanted to add support for a site that I use all the time – Imgur. They didn’t implement the uploadAndPost spec so I had to make a few exceptions as well as add an extra step to post the tweet along with the uploaded image file. Took a while to work out all the kinks (one large kink remaining is that Twitvid uploads don’t work LOL) but this page pretty much saves me from ever having to go to those sites again to upload images!

function twitter_twitpic_page($query) {
  // Check for oAuth credentials
  if (user_type() == 'oauth') {
    return theme('page', 'Error', '<p>You can't do media uploads while accessing Dabr using an OAuth login.</p>');
  }

  //verify that we're entering this page from posting the form  
  if ($_POST['service']) {
  
    // format and shrink/truncate associated status message
    $status = prepare_status($_POST['message'],120);
     
    // set the  api url based on the service name (all similar except imgur)
    $postUrl = 'http://'.$_POST['service'].'.com/api/uploadAndPost';

     // prepare the fields array with the common elements
    $postData = array(
      'username' => user_current_username(),
      'password' => $GLOBALS['user']['password'],
      'message' => $status,);
       
     // perform service-specific tasks
     switch ($_POST['service']){
         case 'imgur':
               if (!defined('IMGUR_API_KEY')){
                    twitter_refresh('twitpic/fail/'.$_POST['service'].'/'.urlencode('API KEY undefined'));
               }
               
               // imgur doesn't use the Twitter standard uploadAndPost spec
               $postUrl = 'http://imgur.com/api/upload.xml';
               
               //if URL is provided, send URL for imgur to rehost, otherwise use selected file
              if (empty($_POST['url'])){
                   $postData = array(
                         'key' => IMGUR_API_KEY, 
                         'image' => '@'.$_FILES['media']['tmp_name']);
              } else {
                   $postData = array(
                         'key' => IMGUR_API_KEY, 
                         'image' => $_POST['url']);
              }
               break;
          case 'yfrog': 
               if (!defined('YFROG_API_KEY')){
                    twitter_refresh('twitpic/fail/'.$_POST['service'].'/'.urlencode('API KEY undefined'));
               }
               $postData['key'] = YFROG_API_KEY;
               
              // Yfrog can also accept a URL as the media source
              if (!empty($_POST['url'])){
                   $postData['url'] = $_POST['url'];
              } else {
                    $postData['media'] = '@'.$_FILES['media']['tmp_name'];
               }
               break;
          case 'posterous':
              // Posterous has an additional comments element and will fall through to the default
               $postData['body'] = stripslashes($_POST['body']);
         default:
               $postData['media'] = '@'.$_FILES['media']['tmp_name'];
     }

     // make the api call
    $response = twitter_process($postUrl,$postData);

     // check response XML for associated IDs
     // for uploadAndPost supporting services
    if (preg_match('#mediaid>(.*)</mediaid#', $response, $matches)) {
      $id = $matches[1];
       
       // Twitvid allows crossposting to Youtube
      if (preg_match('#youtube_id>(.*)</youtube_id#', $response, $matches)) {
           $altid = $matches[1];
      }
       
       // Posterous sends back a separate shortened URL code
      if (preg_match('#mediaurl>http://post.ly/(.*)</mediaurl#', $response, $matches)) {
           $altid = $matches[1];
      }
       
       // show success messsage and pass IDs to create links to media
      twitter_refresh("twitpic/confirm/".$_POST['service']."/$id/$altid");
    } 
     // response for imgur uses different element names
     elseif (preg_match('#image_hash>(.*)</image_hash#', $response, $matches)) {
      $id = $matches[1];
       
       // the secret delete link/code is offered only once and should be shown in the confirmation
      if (preg_match('#delete_hash>(.*)</delete_hash#', $response, $matches)) {
           $deleteid = $matches[1];
      }
       
       // we need the actual imgur link in order to post status to Twitter 
      if (preg_match('#original_image>(.*)</original_image#', $response, $matches)) {
           $imglinkid = $matches[1];
      }

       // update status with the image link
      $status .= " $imglinkid ";

       // post the status to twitter
      $response = twitter_process('http://twitter.com/statuses/update.json',
           array('source' => 'dabr', 'status' => $status));

       // show success message, link to image, and hidden delete link
      twitter_refresh("twitpic/confirm/".$_POST['service']."/$id/$deleteid");
    } else {
          // collect errors from response
         if (preg_match('#error_code>(.*)</error_code#', $response, $matches)) {
              $error = "Error Code: $matches[1]. ";
         }
         if (preg_match('#error_msg>(.*)</error_msg#', $response, $matches)) {
              $error .= "Error Msg: $matches[1]. ";
         }
         if (preg_match('#err.code="(.*)" msg="(.*)" />#', $response, $matches)) {
               $error = "Error Code: $matches[1] Error Msg: $matches[2]";
         }
            
          // show failure messages
         twitter_refresh('twitpic/fail/'.$_POST['service'].'/'.urlencode($error));
    }
  } 
  // Page mode to show confirmation and media links
  elseif ($query[1] == 'confirm') {
    $postedlink = "Media: http://$query[2].com/$query[3]";
    if ($query[2] == 'imgur' && !empty($query[4])){
         $postedlink .= " // Hidden delete link: http://imgur.com/delete/$query[4]";
    }
    if ($query[2] == 'twitvid' && !empty($query[4])){
         $postedlink .= " // Youtube:  http://www.youtube.com/watch?v=$query[4]";
    }
    if ($query[2] == 'posterous' && !empty($query[4])){
         $postedlink = "Post: http://post.ly/$query[4]";
    }
     
     // show formatted confirmation to add thumbnails
    $content = "<p>Upload success.</p><p>".twitter_parse_tags($postedlink)."</p>";
  } 
  // page mode for failure - show errors
  elseif ($query[1] == 'fail') {
    $content = "<p>$query[2] upload failed: $query[3]</p>";
  } 
  // otherwise show form
  else {
    $content = '<style type="text/css">.disabletrue{background:#ddd;}.disablefalse{background:#fff;}</style>
          <script type="text/javascript">function disable(sel){service=sel.options[sel.selectedIndex].value;sel.form.url.disabled= (service != 'yfrog' && service != 'imgur');sel.form.body.disabled= (service != 'posterous');sel.form.url.className= 'disable'+(service != 'yfrog' && service != 'imgur');sel.form.body.className= 'disable'+(service != 'posterous');}</script>
          <form name="twitpic" method="post" action="twitpic" enctype="multipart/form-data"><br />Service: <select name="service" onChange="disable(this);"><option value="twitpic">Twitpic</option><option value="twitgoo">Twitgoo</option><option value="yfrog">Yfrog</option><option value="imgur">Imgur</option><option value="twitvid">Twitvid</option><option value="posterous">Posterous</option></select><br />Upload: <input type="file" name="media" /><br />Message: <input type="text" name="message" maxlength="120" /><br />Image Url: <input type="text" name="url" maxlength="120" /><br />Body:<br><textarea style="position:relative;top:-14px;left:67px;" cols=50 rows=3" name="body"></textarea><br /><input type="submit" value="Upload" /></form>
          <script type="text/javascript">disable(document.forms['twitpic'].service);</script>';
  }
  return theme('page', 'Twitpic Upload', $content);
}

I also had to update the twitter_photo_replace function, which I use to show the thumbnail of the image on the confirm page, to add the imgur regexes

    '#imgur.com/([w]{5})[s.ls][.w]*#i' => 'http://imgur.com/%ss.png',
    '#imgur.com/gallery/([w]+)#i' => 'http://imgur.com/%ss.png',
    '#imgur.com/delete/([w]+)#i' => 'images/trash.gif',

A lot of code, but to me it’s worth it!

Bookmark and Share Blog This Facebook Twiit Google Yahoo! Buzz Ping StumbleUpon Fark Propellor Netvouz Newsvine reddit Simpy Blinklist Blogmarks Mr Wong Startaid Segnalo Wists Boxed Up

Popularity: unranked [?]

2 Comments »

  1. Of the tens of thousands of messages that are sent through dabr.co.uk daily, only about 200 of them are Twitpic uploads. I’m not keen on encouraging it because modern camera phones are becoming higher resolution and since Dabr is only a website, it can’t shrink those photos for you before you upload.

    I do like finding blog posts like this to see different directions people take Dabr though :)

    Comment by David Carrington — January 11, 2010 @ 5:40 am

  2. It really is more an exercise in coding than anything and as i think you mentioned elsewhere, some phones can’t even do file uploads correctly. I guess this was more for my laziness on the desktop version :)

    Comment by webadmin — January 12, 2010 @ 2:32 am

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress

Blog Information