Version 3 of flickroo

Updated 2013-12-09 22:46:11 by ABU

ABU 23-apr-2012

flickroo -- OO Flickr API

flickroo is an object-oriented wrapper around the Flickr API.

This module is based on the tcl flickr project ver 0.2

 Copyright (c) 2006 by the Swedish Institute of Computer Science.

 Credits to Andrew O. Shadoura, Schelte Bron and the whole Tcl community
 for some reused parts

 2012 - oo-wrapping by A.Buratti

MAJOR FEATURES

This package is strongly based on flickr ver 0.2 with some differences and enhancements:

  • All features of original flickr-0.2 package are still available, although with a (very) different syntax.
  • Flickroo provides an object-oriented API (based on snit)
  • Flickroo provides support for the new OAuth authentication protocol - the original auth protocol is deprecated and won't be supported by flickr.com after July 2012
  • Flickr API calls don't return XML responses. Responses are (equivalent) tcl-lists (or better, tcl-dictionaries) far more easy to parse.
  • All Flickr API calls may be be perfomed in sync-mode or in an async-mode

Download

  http://irrational-numbers.googlecode.com/files/flickroo-1.1.zip%|%flickroo-1.1 

REQUIRED PACKAGES

IMPORTANT NOTE

All the required packages should have been installed under standard library path.

HOW TO USE IT

Flickroo is an object-oriented (snit) wrapper around the Flickr API.

For full usage, you need a flickr.com account and also a Flickr API consumer-key (along with a consumer-key-secret). You can ask for a consumer-key (and a consumer-key-secret) to flickr.com

You can also use this package and be able to download almost everything from flickr.com even without a Flickr account or a consumer-key-secret. In this case you cannot upload nor write to flickr.com; you only won't be able to call some API requiring authentication (usually API for writing).

Anyway, even for simple (and powerful) read-only API calls, you need at least a *consumer-key*.

Within the FAQ section of this document you can find instruction for grabbing a .. public .. consumer-key.

 # Load the package
package require flickroo

 # Create a flickr object.
 # ! you need a consumer-key
set CONSUMER_KEY 12356123345
set fObj [flickr new $CONSUMER_KEY] 

 # First simple test
set response [$fObj flickr.test.echo]
 # if everything is OK, you'll get a list (a tcl-dictionary) containing some
 # dummy data fetched from flickr.com  

 # Dispose the flickr object (this is a standard snit pattern)
$fObj destroy


 # Restart with a new flickr object
set fObj [flickr new $CONSUMER_KEY] 
 # get a list of 10 photos having tag "watamu" 
set response [$fObj flickr.photos.search -tags "watamu" -per_page 10]
 # response is a tcl-dictionary like this  ...
 #   * Note: this is a pretty-printed representation *
{
    photos {
        page 1 
        pages 726 
        perpage 10 
        total 7257 
        photo {
            {id 6974156079 owner 74957296@N08 secret 005d743f82 server 7197 farm 8 title {Kenya Watamu "Deep Sea Fishing" "Indian Ocean" "Blue Marlin"} ispublic 1 isfriend 0 isfamily 0} 
            {id 6822988100 owner 52857411@N08 secret 56630c18e8 server 7183 farm 8 title {Gedi Ruins, Local Guide} ispublic 1 isfriend 0 isfamily 0} 
            {id 6822981062 owner 52857411@N08 secret c06c7387e6 server 7205 farm 8 title {Gedi Ruins, Old Palace} ispublic 1 isfriend 0 isfamily 0} 
            {id 6969088883 owner 52857411@N08 secret 5bc841e5ae server 7207 farm 8 title {Gedi Ruins, Old Mosque} ispublic 1 isfriend 0 isfamily 0} 
            {id 6969095639 owner 52857411@N08 secret 9868c7816b server 7189 farm 8 title {Gedi Ruins, Old Palace} ispublic 1 isfriend 0 isfamily 0} 
            {id 6969081657 owner 52857411@N08 secret b58dc72e7d server 7180 farm 8 title {Local Sailing Boat} ispublic 1 isfriend 0 isfamily 0} 
            {id 6822917466 owner 52857411@N08 secret 56b89c1636 server 7061 farm 8 title {Local Boy, Mida Creek} ispublic 1 isfriend 0 isfamily 0} 
            {id 6822924000 owner 52857411@N08 secret 03c0e4c7c1 server 7176 farm 8 title {Local Man, Mida Creek} ispublic 1 isfriend 0 isfamily 0} 
            {id 6969025843 owner 52857411@N08 secret 3c08ddc2e2 server 7180 farm 8 title {Sea Crab, Watamu} ispublic 1 isfriend 0 isfamily 0} 
            {id 6822909640 owner 52857411@N08 secret f4e392ea36 server 7063 farm 8 title {Local Fisherman, Mida Creek} ispublic 1 isfriend 0 isfamily 0}
        }
    } 
    stat ok
} 

 # You can extract some info
set nOfPhotos [dict get $response "photos" "total"]
 # print each photo-id and title
foreach ph [dict get $response "photos" "photo"] {
   dict with ph {
      puts "$id --- $title"
   }
}

 # For a complete list of Flickr API calls (more than 190) you must consult 
 #  http://www.flickr.com/services/api/
 # In order to use them in a tcl app, you only need to follow these rules:
 # A) the general tcl pattern is:
 #     set response [$fObj flickr.XX.XX -key value ... -key value]
 #    where
 #      flickr.XX.XX is a Flickr method
 #      followed by zero or more pairs   -key value 
 #          -key : the Flickr API argument name (you must add a leading "-")
 #          value: the Flickr API argument value
 #    The order of {-key value} pairs is unimportant. 
 #    Each Flickr API has mandatory and optional keys. 
 #    Arguments are checked before transmitting anything to flickr.com;
 #    an error is raised if mandatory arguments are missing.
 # B) Do NOT specify the special "api_key" key; flickroo will transmit it for you.
 # C) $fObj flickr.XX.XX  ...
 #    always returns a tcl-dictionary with a "positive response 
 #      (e.g. with "stat" key equal to "ok")
 #    OR raises an error.
 #    Mispelling a Flickr-Method or a Flickr-Argument-Name always raises an
 #    error (without the need to transmit anything to flickr.com).
 #    "Negative" responses (such as those aroused by using an invalid id) and 
 #    "network/connection" erros raise a tcl "error" (that should be properly caught (catch))

ASYNC calls

If the "--onEnd callback" option is specified (note the double dash), then the API call is done in the background.

The API call returns immediately an http-token and the callback proc (usually a GUI callback) is called when data are available.

Here is a template for the callback:

  proc aFlickrCallback { errMsg response } {
    if { $errMsg != {} } {
         .... alert the caller something was wrong ...
        return
    }
    ... extract data from $reponse ...
  }

NOTE that a flickroo callback always gets two additional parameters: errMsg and response

  • errMg : if not empty you should take some actions and skip the reponse processing.
  • response : a tcl-dictionary containing data returned by flickr API call. Note that response is meaningless if errMsg is not empty.

Given these rules, the previous example can be rewritten in async-mode as:

 proc On!photos.search {errMsg response} {
    if { $errMsg != {} } {
        puts "I'm soryy\n$errMsg"
        return
    }
     # print each photo-id and title
    foreach ph [dict get $response "photos" "photo"] {
       dict with ph {
          puts "$id --- $title"
       }
    }
 }
 #
 set httpToken [$fObj flickr.photos.search -tags "watamu" -per_page 10 \
  --onEnd On!photos.search]
 puts "request sent to flickr.com; result will be available later"
 # ... now do something else

Notes about httpToken

The only valid use for an httpToken returned from an *async* flickr API call is for resetting the http transaction

  http::reset $httpToken

Also note that the httpToken is *always* automatically cleared when the http transaction ends - just before the flickr-callback is called.

Thereforeit cannot be used within the flickr-callback, nor in the main "thread" after the flickr-callback has been processed.

Login

Obtaining an authenticated access to flickr.com, for security reasons is a multi-step process that can be only partially automatized by Flickr API.

Here is a short preview of the required steps:

  1. (from your app) get a special login-url
  2. Open a web-browser and go to the login-url page
  3. (through the web-browser) enter your credentials
  4. (from the web-browser) grab the one-time PIN
  5. Return to your app and enter the PIN.

Now the details:

  • (from your app) get a special login-url
 # this is the time you need the consumer-key-secret
 # note that we (try to) require a "write" permission. 
 set CONSUMER_KEY_SECRET  987654321
 set loginUrl [$fObj getLoginUrl $CONSUMER_KEY_SECRET write]
  • Open a web-browser and go to the login-url page
 ... this step SHOULD be automatized.
 ... It's not detailed since it strongly depends on your OS and your web-browser
  • (through the web-browser) enter your credentials
 ... this is a step that cannot be driven by your app, since flickr.com provides
     different *interactive* ways to enter your credential (you can even switch
     to Google or Facebook for your Identity-check). Moreover, after your ID
     has been checked, you are forced to perform some other interactive actions
     on some flickr.com pages.
     It's not a long procedure; simply it is not designed (nor documented) to be
     an automation procedure.
     Anyway, at the end you'll see a page showing you a PIN like this
       123-456-789
  • (from the web-browser) grab the one-time PIN
  ... copy the PIN ... 
  • Return to your app and enter the PIN.
  even this step is a manual step ...
  You can use copy&paste, drag&drop, or simply retype.
  Once you have this value in your app (let's say within the PIN variable), you 
  should complete the login with the following command:
 $fObj login $PIN

Now your app is authorized to access flickr.com, with your credentials, and with "write" permission.

It looks complicated, but it is for your security.

Please note that you never passed your userid/password to the app ; your userid/password were directly transmitted through your web-browser to flickr.com (or to another supported Identity-Provider such as Google or Facebook).


FAQ

Q: I haven't a direct Internet connection; how can I use a proxy-server ?

Usually the autoxproxy package is all you need:

      package require http
      package require autoxproxy
      autoproxy::init
       # if a username/password is required ..
      autoproxy::configure -basic -username XXXXX -password YYYYYY

If autoproxy cannot get web access settings from system's standard locations, you must configure them explicitely

      autoproxy::configure -proxy_host MYPROXY  -proxy_port 8080

Q: Does a public consumer-key exist ?

Just for testing, you can grab the api-key used by API Explorer

     http://www.flickr.com/services/api/explore/flickr.test.echo

but this key is everytime different.

Simlpy press the (Call Method...) button and grab the "api_key" value from the full URL under the response box.

Of course you cannot get the consumer-key-secret, therefore you won't be able to call those API requring a login.

Q: How can I check for a valid consumer-key ?

Try with these commands:

           set fObj [flickr new XXXXXXXXXX]
           $fObj flickr.test.echo

If the last command raises an error, you should destroy fObj and then recreate it with the right key