PyFlickrUploadr Page

PyFlickrUploadr is a Python script to upload images to Flickr. It uses the Python Flickr API designed by Brian "Beej Jorgensen" Hall.

Changelog

Download

Download the tarball here. It includes everything needed to run PyFlickrUploadr.

Contact

Email : deepakDOTjoisATgmailDOTcom

Source

The source code of the script is given below. The syntax highlighting is courtesy the SilverCity Online Styler Interface

#!/usr/bin/python
#
# PyFlickrUploader : A commandline Flickr photo uploader 
#
# I had developed a Java based commandline Flickr uploader
# called JFlickrUploader (http://jflickruploader.blogspot.com).
# Then, in an effort to practise some Python coding, I decided to
# rewrite it in Python. This script makes use of the Flickr API
# client writen by Brian "Beej Jorgensen" Hall.
#
http://beej.us/flickr/flickrapi/
#
# Release 1    [27 Sept 2005]: initial release
# Release 1.01 [ 2 Oct  2005]: minor license changes
#
# USAGE
# -----
# - Copy flickrapi.py from <http://beej.us/flickr/flickrapi/> and
#   put it in the same folder as this script. This step is not required
#   if you downloaded the tarball from
#   <http://jflickruploader.sourceforge.net/pyflickruploadr.html
#
# - Change the FlickrAPIKey and the flickrSecret variables. See
#   <http://www.flickr.com/services/api/misc.api_keys.html>
#   to get one.
#
# - Change the browser variable to the path of the browser of 
#   your choice
#
# - Use this script. Use the -h option for help.

# Example :
# python PyFlickrUploader.py --files /home/deepak/test.jpg --tags test1
#
# TODO
# ----
# - Fix the help display
# - Display help in certain error situations
# - Use auth.checkToken function if available, and wait after opening browser
#

__author__      = 'Deepak Jois'
__version__     = '1.01'
__copyright__   = '(c) 2005 Deepak Jois'
__license__     = 'Public Domain'
__url__         = 'http://jflickruploader.sourceforge.net/pyflickruploadr.html'

from optparse import OptionParser
from flickrapi import FlickrAPI
import sys
import os
import string

#file parsing
def files_parse(arg):
        
"""Parse file or folder from the string and return an array of image file names."""
        
if os.path.isfile(arg):
                
#File
                
if (arg.lower().endswith("jpg") or arg.lower().endswith("png") or arg.lower().endswith("gif")):
                        
return [arg]
                
else:
                        
sys.stderr.write(string.join([arg,"is not an image file!\n"]))
                        
return []
        
else:
                
if os.path.isdir(arg):
                        
#Folder
                        
sys.stdout.write(string.join(["checking folder", arg, "for image files\n"]))
                        
imagefilelist = [filename for filename in os.listdir(arg) if (filename.lower().endswith("jpg") or filename.lower().endswith("png") or filename.lower().endswith("gif"))]
                        
imagefilelist = [string.join([os.path.normpath(arg),imgFile],"/") for imgFile in imagefilelist]
                        
return imagefilelist
        
sys.stderr.write(string.join([arg,"is neither a file or folder\n"]))
        
return []

# callback function definitions
def files_callback(option, opt_str, value, parser):
        
"""Callback function to process the --files argument."""
        
assert value is None
        
done = 0
        
value = []
        
rargs = parser.rargs
        
while rargs:
                
arg = rargs[0]

                
if ((arg[:2] == "--" and len(arg) > 2) or
                        
(arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
                        
break
                
else:
                        
value.append(arg)
                        
del rargs[0]
        
filelist = []
        
for arg in value:
                
filelist.extend(files_parse(arg))

        
if len(filelist)<1:
                
raise ValueError, "No files specified"

        
#Filter duplicates
        
result = []
        
for item in filelist:
                
if item not in result:
                        
result.append(item)

        
setattr(parser.values, "filelist", result)

def tags_callback(option, opt_str, value, parser):
        
"""Callback function to process the --tags argument."""
        
assert value is None
        
done = 0
        
value = []
        
rargs = parser.rargs
        
while rargs:
                
arg = rargs[0]

                
if ((arg[:2] == "--" and len(arg) > 2) or
                        
(arg[:1] == "-" and len(arg) > 1 and arg[1] != "-")):
                        
break
                
else:
                        
value.append(arg)
                        
del rargs[0]
        
        
if len(value)<1:
                
raise ValueError, "No tags specified"
        
setattr(parser.values, "taglist", value)

# flickr auth information
flickrAPIKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  # API key
flickrSecret = "yyyyyyyyyyyyyyyy"                  # shared "secret"
browserName = "/usr/bin/firefox"                   # for out-of-band auth inside a web browser

# init commandline options parser
parser = OptionParser(usage="PyFlickrUploadr.py --files FILE1 FOLDER1.. [--tags TAG1 TAG2] [options]")
# files option
parser.add_option("-f","--files", action="callback", callback=files_callback,
                  
help="Files to upload. If folder is specified, all image files in the folder are uploaded. File names are used as titles automatically.", metavar="FILE1 FOLDER1...")
# tags option
parser.add_option("-t","--tags", action="callback", callback=tags_callback,
                  
help="tags to add to photos, separated by whitespace.", metavar="TAG1 TAG2..")
# friends privacy option
parser.add_option("-r", "--friends", action="store_true", dest="friends",
                  
help="Photos made visible to contacts marked as friends. Default is private.")
# family privacy option
parser.add_option("-m", "--family", action="store_true", dest="family",
                  
help="Photos made visible to contacts marked as family. Default is private")
# public privacy option
parser.add_option("-p", "--public", action="store_true", dest="public",
                  
help="Photos made visible to everybody (overrides any other privacy settings). Default is private")

# parse the arguments
(options, args) = parser.parse_args()


#flag error if no files specified
if not hasattr(options, "filelist"):
        
raise ValueError, "No valid files specified"

#Set tags to null if they don't exist
if not hasattr(options, "taglist"):
        
options.taglist=[]

#Set privacy tags to false if not specified
if (options.friends == None):
        
options.friends = False
if (options.family == None):
        
options.family = False
if (options.public == None):
        
options.public = False

# debug values 
# print string.join(["file list : ",str(options.filelist)])
# print string.join(["tags list : ", str(options.taglist)])
# print string.join(["friends : ", str(options.friends)])
# print string.join(["family : ", str(options.family)])
# print string.join(["public : ", str(options.public)])

# initialise FlickrAPI object
fapi = FlickrAPI(flickrAPIKey, flickrSecret)

# proceed with auth
# TODO use auth.checkToken function if available, and wait after opening browser
print "authorising.."
token = fapi.getToken(browser = browserName)

# upload the images
for imgFile in options.filelist:
        
sys.stdout.write(string.join(["uploading", imgFile,"...\n"]))
        
rsp = fapi.upload(filename=imgFile, api_key=flickrAPIKey, auth_token=token, \
                
title=os.path.splitext(os.path.basename(imgFile))[0], \
                
tags=string.join(options.taglist), \
                
is_public=options.public and "1" or "0", \
                
is_friend=options.friends and "1" or "0", \
                
is_family=options.family and "1" or "0")
        
if rsp == None:
                
sys.stderr.write("can't find file\n")
        
else:
                
fapi.testFailure(rsp,exit=False)
        
        
if rsp['stat'] == 'ok':
                
sys.stdout.write("successful!\n")