Skip to content

Instantly share code, notes, and snippets.

@tgray
Last active September 8, 2015 10:35
Show Gist options
  • Save tgray/ea28780f4fae618fa37c to your computer and use it in GitHub Desktop.
Save tgray/ea28780f4fae618fa37c to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# !/usr/bin/python
from flickrapi import FlickrAPI
from os.path import basename, splitext
import sys, os
import argparse
import errno
import shutil
import mimetypes
from random import randint
import datetime
import pytz
import json
import subprocess as sb
import shlex
myTZ = pytz.timezone('US/Eastern')
timeperiod = datetime.timedelta(days=1)
timeperiod = timeperiod - datetime.timedelta(minutes=10)
# Flickr parameters
def get_rc():
"""Get flickr credentials for ~/.flickr_rc."""
# The blog's XMLRPC URL and username.
try:
f = open(os.path.join(os.environ['HOME'], '.flickr_rc'))
lines = f.read()
lines = lines.strip().split('\n')
userdat = dict([[a.strip() for a in l.split(':', 1)] for l in lines])
f.close()
except:
print """Must set flickr credentials in .flickr_rc file. Obtain at:
https://www.flickr.com/services/apps/create/apply/
Example contents:
fuser: username
key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
secret: xxxxxxxxxxxxxxxx
upphotodir: /path/of/photos/to/upload/
upoutdir: /directory/to/move/uploaded/photos/to/"""
sys.exit(1)
return userdat
# the following two auth functions are taken from
# http://stuvel.eu/media/flickrapi-docs/documentation/3-auth.html
def auth_web(flickr):
flickr.authenticate_via_browser(perms='read')
def auth_cli(flickr):
import webbrowser
print('Step 1: authenticate')
# Only do this if we don't have a valid token already
if not flickr.token_valid(perms='read'):
# Get a request token
flickr.get_request_token(oauth_callback='oob')
#
# Open a browser at the authentication URL. Do this however
# you want, as long as the user visits that URL.
authorize_url = flickr.auth_url(perms='read')
webbrowser.open_new_tab(authorize_url)
# Get the verifier code from the user. Do this however you
# want, as long as the user gives the application the code.
verifier = unicode(raw_input('Verifier code: '))
# Trade the request token for an access token
flickr.get_access_token(verifier)
def get_xmp(fn):
cmd = 'exiftool -json ' + fn
cmd2 = shlex.split(cmd)
out = sb.check_output(cmd2)
outj = json.loads(out)
return outj[0]
def upload(fn, dryrun = False):
print "Uploading %s..." % fn
t = splitext(basename(fn))[0] # file name w/o extension
try:
dat = get_xmp(fn)
except:
dat = {}
title = dat.get('Headline', t)
descrip = dat.get('Description', ' ')
if not dryrun:
response = flickr.upload(filename=fn, title=title, description =
descrip, is_public=public, format='etree')
photoID = response.find('photoid').text
photoURL = 'http://www.flickr.com/photos/%s/%s/' % (fuser, photoID)
print " %s" % photoURL
try:
shutil.move(fn, outdir)
except:
print 'move problem'
sys.exit(2)
def not_already_uploaded():
l = flickr.test_login()
userid = l[0].attrib['id']
out = flickr.people_getPublicPhotos(user_id=userid, per_page=1)
photoid = out[0][0].attrib['id']
p = flickr.photos_getInfo(photo_id=photoid)
d = p[0].attrib['dateuploaded']
dt = datetime.datetime.utcfromtimestamp(float(d))
utc = pytz.utc
mydt = utc.localize(dt).astimezone(myTZ)
# period since last picture
d = myTZ.localize(datetime.datetime.now()) - mydt
# must be greater than timeperiod specified
out = d > timeperiod
if not out:
print('Already uploaded a file {} ago on {}.'.format(d, mydt))
print('Must wait {}, until {}.'.format(timeperiod, mydt+timeperiod))
return out
userdat = get_rc()
fuser = userdat['fuser']
photodir = userdat['upphotodir']
outdir = userdat['upoutdir']
try:
parser = argparse.ArgumentParser(
description = ('Upload pictures to flickr.'))
parser.add_argument('-n', '--number',
dest = 'number',
action = 'store',
default = 1,
type = int,
metavar = 'N',
help = 'number of images to upload')
parser.add_argument('-p', '--private',
dest = 'private',
action = 'store_true',
help = 'make uploads private')
parser.add_argument('--dry-run',
dest = 'dryrun',
action = 'store_true',
help = 'dry run - does not upload and move files')
parser.add_argument('-l', '--last',
dest = 'last',
action = 'store_true',
help = "only uploads if a photo hasn't been uploaded in the last day")
parser.add_argument('-a', '--auth',
dest = 'auth',
action = 'store_true',
help = "authenticate with flickr with a web browser")
parser.add_argument('--auth-cli',
dest = 'authcli',
action = 'store_true',
help = "authenticate with flickr from the CLI")
parser.add_argument('file',
nargs = '*',
help = 'file to upload')
args = parser.parse_args()
except:
sys.exit(2)
if args.private:
public = 0
else:
public = 1
# Upload the files on the command line.
flickr = FlickrAPI(api_key=userdat['key'], secret=userdat['secret'])
if args.auth or args.authcli:
if args.auth:
auth_web(flickr)
elif args.authcli:
auth_cli(flickr)
if flickr.token_valid(perms='write'):
print('authenticated')
sys.exit(0)
else:
print('error authenticating')
sys.exit(1)
# make our outdir
try:
os.mkdir(outdir)
except OSError, e:
if e.errno != errno.EEXIST:
raise e
pass
# upload our selected number of images, randomly selected
if args.file:
for fn in args.file:
upload(os.path.abspath(fn), args.dryrun)
elif not args.last or not_already_uploaded():
files = os.listdir(photodir)
ftypes = [mimetypes.guess_type(f)[0] for f in files]
fileinfo = zip(files, ftypes)
# get just images
files = [f[0] for f in fileinfo if (f[1] and f[1].startswith('image/'))]
cwd = os.getcwd()
os.chdir(photodir)
for i in xrange(args.number):
try:
n = randint(0, len(files)-1)
fn = files.pop(n)
except:
print 'no more files'
sys.exit(2)
upload(os.path.abspath(fn), args.dryrun)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment