#!/usr/bin/env python2.6 """ The author furnishing this item "as is". The author does not provide any warranty of the item whatsoever, whether express, implied, or statutory, including, but not limited to, any warranty of merchantability or fitness for a particular purpose or any warranty that the contents of the item will be error-free. In no respect shall the author incur any liability for any damages, including, but limited to, direct, indirect, special, or consequential damages arising out of, resulting from, or any way connected to the use of the item, whether or not based upon warranty, contract, tort, or otherwise; whether or not injury was sustained by persons or property or otherwise; and whether or not loss was sustained from, or arose out of, the results of, the item, or any services that may be provided by the author. """ import logging import optparse import os import sys import ConfigParser import urllib2 import Flickr.API __author__ = "Gilad Raphaelli" logger = logging.getLogger("flickrcall") logger.addHandler(logging.StreamHandler()) def get_auth_token_or_exit(api, perms): """ get an authentication token for a given permission level """ try: import json except ImportError: try: import simplejson as json except ImportError: print "this script can't get an auth token without json or simplejson" sys.exit(1) logger.debug("geting a frob from Flickr") frob_rsp = execute_request_or_exit(api, Flickr.API.Request( method='flickr.auth.getFrob', format='json', nojsoncallback=1) ) frob = None if frob_rsp.code == 200: frob_rsp_json = json.load(frob_rsp) if frob_rsp_json['stat'] == 'ok': frob = str(frob_rsp_json['frob']['_content']) logger.debug("got frob: %s" % frob) else: logger.debug("didn't get a frob, got: %s" % json.dumps(frob_rsp_json)) if frob is None: print "unable to get a frob" sys.exit(1) auth_url = api.get_authurl(perms, frob=frob) print "auth me: %s" % (auth_url,) input = raw_input("done [y]: ") if input.lower() not in ('', 'y', 'Y'): print "Can't continue without authorizing" sys.exit() logger.debug("getting a token from Flickr") token_rsp = execute_request_or_exit(api, Flickr.API.Request( method='flickr.auth.getToken', frob=frob, format='json', nojsoncallback=1) ) token = None if token_rsp.code == 200: token_rsp_json = json.load(token_rsp) if token_rsp_json['stat'] == 'ok': token = str(token_rsp_json['auth']['token']['_content']) logger.debug("got token: %s" % token) else: logger.debug("didn't get a token, got: %s" % json.dumps(token_rsp_json)) if token is None: print "unable to get a token" sys.exit(1) return token def process_options(argv): """ process options or display usage and exit on bad usage """ try: homedir = os.path.expanduser("~") except: homedir = "." cfg = None parser = optparse.OptionParser(usage="usage: %prog [options] api.method [key=val ... ]") # api configuration options parser.add_option("-c", "--config", dest="config", help="flickr config file", default=os.path.join(homedir, ".flickr.cfg")) parser.add_option("--no-sign", dest="sign", help="don't sign request", action="store_true", default=True) parser.add_option("-k", "--key", dest="key", help="Flickr API key") parser.add_option("-s", "--secret", dest="secret", help="Flickr API secret") parser.add_option("-n", "--no-secret", dest="nosecret", help="don't use the Flickr API secret", action="store_true") # authentication options parser.add_option("-p", "--permissions", dest="perms", help="permissions", default="read") parser.add_option("-t", "--get-auth-token", dest="doauth", help="get an authentication token first", action="store_true") # format shortcuts parser.add_option("-b", "--nojsoncallback", dest="nojsoncallback", help="nojsoncallback=1", action="store_true") parser.add_option("-j", "--json", dest="response_format", help="request response in json", action="store_const", const="json") parser.add_option("-x", "--xml", dest="response_format", help="request response in xml (rest)", action="store_const", const="rest") parser.add_option("-D", "--debug", dest="debug", help="print some details about what's going on", action="store_true") (options, args) = parser.parse_args(argv) if options.debug: logger.setLevel(logging.DEBUG) secret = options.secret key = options.key # we must have a key from somewhere if key is None: logger.debug("loading config from %s" % options.config) cfg = ConfigParser.ConfigParser() cfg.read(options.config) try: key = cfg.get("api", "key") except ConfigParser.Error, e: print "unable to load your Flickr API Key: %s" % e.message sys.exit(1) logger.debug("got key from config file: %s" % key) # only load the secret from config if the key and secret # were not supplied on command line if secret is None and not options.nosecret: secret = cfg.get("api", "secret") logger.debug("got secret from config file: %s" % secret) if options.nosecret: secret = None if len(args) == 0: parser.print_help() sys.exit(1) return (key, secret, options, args) def execute_request_or_exit(api, request, **kwargs): """ convenience method for executing an api request and exiting on error. """ try: return api.execute_request(request, **kwargs) except urllib2.URLError, e: print "Error executing request: %s" % str(e) sys.exit(1) except Exception, e: print "Error executing request: %s" % str(e) sys.exit(1) def make_api_args(options, args, **kwargs): """ convert command line options into kwargs for use in flickr api calls """ method = args[0] apiargs = dict(map(lambda x: x.split("="), args[1:])) apiargs['method'] = method if options.response_format is not None: apiargs["format"] = options.response_format if options.nojsoncallback: apiargs["nojsoncallback"] = 1 apiargs.update(kwargs) return apiargs def main(*args, **kwargs): """ process command-line-style options and build an api request with optional authentication token dancing. returns the response from Flickr as a file-like object or exits on error """ (key, secret, options, sysargs) = process_options(list(args)) logger.debug("using: key: %s, secret: %s" % (key, secret)) api = Flickr.API.API(key, secret) # Build the Request apiargs = make_api_args(options, sysargs, **kwargs) # Get the auth token if requested if options.doauth: token = get_auth_token_or_exit(api, options.perms) apiargs["auth_token"] = token # Log some information logger.debug("api params: %s" % str(apiargs)) logger.debug("request call signing: %s" % ("yes" if options.sign else "no",)) if options.sign and secret is None: logger.debug("Flickr.API will not sign this call") if "auth_token" in apiargs.keys() and not options.sign: logger.debug("This call will fail because signing is off") # Make the request rsp = execute_request_or_exit(api, Flickr.API.Request(**apiargs), sign=options.sign) for attr in ('code', 'msg', 'url', 'headers'): logger.debug("response.%s: %s" % (attr, str(getattr(rsp, attr)))) if options.doauth: if token is not None: sys.stderr.write("try auth_token=%s next time for %s permissions\n" % (token, options.perms)) return rsp if __name__ == '__main__': """ format command line arguments for calling main() """ rsp = main(*sys.argv[1:]) r = rsp.read() print r