Twitter Picture Previews with Ruby

As part of a pet project (coming soon!) I have been investigating extracting previews (thumbnails) of pictures from services such as TwitPic, yfrog and plixi in Twitter feeds. Last week I added this feature to the Forward technology website. It is a neat feature as it adds some visual spice to the page. It also gives some insight into what we get up to at work (mostly being geeky and drinking too much).

The hard(ish) bit

What makes this process a little bit awkward is the sheer number of different twitter picture services that are out there. I decided to handle the most popular amongst the people I follow: TwitPic, yfrog and plixi. None of these services share a common interface but after a bit of Googling (this article was especially helpful) and digging around the API documentation (TwitPic API page, yfrog API page and plixi API page) I came up with the following translation:

Service Picture page URL Picture preview URL Example page URL Picture preview
TwitPic http://twitpic.com/{id} http://twitpic.com/show/thumb/{id}.jpg http://twitpic.com/ibhev
http://twitpic.com/show/thumb/ibhev.jpg
yfrog http://yfrog.com/{id} http://yfrog.com/{id}:small http://yfrog.com/bggccwj
http://yfrog.com/bggccwj:small
Plixi http://plixi.com/p/24330722 http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=The picture page url http://plixi.com/p/24330722
http://api.plixi.com/api/tpapi.svc/imagefromurl?size=thumbnail&url=http://plixi.com/p/24330722

Generally the link to the picture page will contain a unique ID that identifies the picture. This ID is easy to extract and use to build the URL to the image preview.

The easy bit

After figuring out the how the URL the code is pretty straightforward. I use the Twitter gem to search for tweets with links from the user on my timeline and then build a set of image previews.

require 'twitter'
require "yajl"

class TwitterPictures

  class TwitpicAdapter
    def self.match?(url)
      !(url =~ /twitpic\.com/).nil?
    end

    def self.html(url, text)
      uri = URI.parse(url)
      id = uri.path
      "<a href="\&quot;#{url}\&quot;"><img title="\&quot;#{text}\&quot;/" src="\&quot;http://twitpic.com/show/thumb/#{id}.jpg\&quot;" alt="" /></a>"
    end
  end

  class YfrogAdapter
    def self.match?(url)
      !(url =~ /yfrog\.com/).nil?
    end

    def self.html(url, text)
      uri = URI.parse(url)
      id = uri.path
      "<a href="\&quot;#{url}\&quot;"><img title="\&quot;#{text}\&quot;/" src="\&quot;http://yfrog.com#{id}:small\&quot;" alt="" /></a>"
    end
  end

  class PlixiAdapter
    def self.match?(url)
      !(url =~ /plixi\.com/).nil?
    end

    def self.html(url, text)
      "<a href="\&quot;#{url}\&quot;"><img title="\&quot;#{text}\&quot;" src="\&quot;http://api.plixi.com/api/tpapi.svc/imagefromurl?size=small&url=#{url}\&quot;" alt="" /></a>"
    end
  end

  def self.for_users(users)
    tweets = fetch_tweets(users)
    build_pictures_html(tweets)
  end

  private

    def self.extract_urls(text, urls = [])
      url_regex =  Regexp.new('\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))')
      url_regex.match(text) do |match|
        urls << match[0]
        extract_urls(match.post_match, urls)
      end
      urls
    end

    def self.build_pictures_html(tweets)
      pictures = {}
      tweets.each do |t|
        pictures_for_text = build_picture_html("from @#{t.from_user}: #{t.text}")
        pictures.merge!(pictures_for_text)
      end
      pictures.values
    end

    def self.fetch_tweets(users)
      @client = Twitter::Search.new
      users_query = users.join(' OR ')
      query = "http (#{users_query})"
      @client.containing(query).per_page(200)
    end

    def self.build_picture_html(text)
      adapters = [TwitpicAdapter, PlixiAdapter, YfrogAdapter]
      pictures = {}
      urls = extract_urls(text)
      urls.each do |url|
        adapters.each do |adapter|
          pictures[url] = adapter.html(url, text) if adapter.match? url
        end
      end
      pictures
    end
end

An example is on github if you want to read more.

More hard bits

Extracting instagr.am preview pictures is a little bit trickier. I will talk about how to do that in an upcoming blog post.

Advertisements

One thought on “Twitter Picture Previews with Ruby

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s