Skip to content

Instantly share code, notes, and snippets.

@dodo5522
Last active May 4, 2023 21:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dodo5522/73dc07a0fb71af75dc81c07984126179 to your computer and use it in GitHub Desktop.
Save dodo5522/73dc07a0fb71af75dc81c07984126179 to your computer and use it in GitHub Desktop.
Python script to upload a photo into flickr.
#!/usr/bin/env python2
# -*- encoding:utf-8 -*-
from __future__ import print_function
import argparse
import datetime
import exifread
import flickrapi
import os
import sys
import time
def parse_args(args=sys.argv[1:]):
""" Get the parsed arguments specified on this script.
"""
parser = argparse.ArgumentParser(description="")
parser.add_argument(
'api_key',
action='store',
type=str,
help='flickr API key got on the official site.')
parser.add_argument(
'secret_key',
action='store',
type=str,
help='flickr secret key got on the official site.')
parser.add_argument(
'path_to_photo',
action='store',
type=str,
help='Full path to the photo uploading to flickr.')
parser.add_argument(
'-c', '--create-album',
action='store_true',
default=False,
required=False,
help='Create photoset automatically.')
return parser.parse_args(args)
def get_taken_datetime_of(photo):
""" Get the datetime of photo to be taken from EXIF data.
arguments:
photo: string to path of photo
return:
datetime object of photo to be taken if success, else None.
"""
dt_original = None
with open(photo, "rb") as p:
exif = exifread.process_file(p)
dt_original = exif.get("EXIF DateTimeOriginal")
return datetime.datetime.strptime(
dt_original.values, "%Y:%m:%d %H:%M:%S") if dt_original else None
def upload_photo(api, path_to_photo, title=None):
""" Upload the photo file to flickr.
arguments:
api: FlickrAPI object.
path_to_photo: Path to photo file.
title: photo file's name if None.
returns:
uploaded photo ID if success, else None.
"""
# res is instance of xml.etree.ElementTree.Element.
# This element has something like "<rsp><photoid>1234</photoid></rsp>".
res = api.upload(
filename=path_to_photo,
title=os.path.basename(path_to_photo) if not title else title,
is_private=True)
# FIXME: Cannot access to API if freqently uploaded
time.sleep(3)
if res.get("stat") != "ok":
return None
# Get the uploaded photo's ID.
return res.find("photoid").text
def add_photo_to_photoset(api, photo_id, photoset_title):
""" Add photo to photoset. If the photoset doesn't exist, create it.
arguments:
api: FlickrAPI object.
photo_id: uploading photo's ID.
photoset_title: adding the photo to this photoset.
returns:
photoset ID fot photo to be added.
"""
rsp = api.photosets.getList()
# FIXME: Cannot access to API if freqently uploaded
time.sleep(3)
# Example Response
# <photosets page="1" pages="1" perpage="30" total="2" cancreate="1">
# <photoset id="72157626216528324" primary="5504567858" photos="22" videos="0" date_create="1299514498" date_update="1300335009">
# <title>Avis Blanche</title>
# <description>My Grandma's Recipe File.</description>
# </photoset>
# <photoset id="72157624618609504" primary="4847770787" photos="43" videos="12" date_create="1280530593" date_update="1308091378">
# <title>Mah Kittehs</title>
# <description>Sixty and Niner. Born on the 3rd of May, 2010, or thereabouts. Came to my place on Thursday,</description>
# </photoset>
# </photosets>
id_ = None
for photosets in rsp.getchildren():
for photoset in photosets.getchildren():
if photoset.findtext("title") == photoset_title:
id_ = photoset.get("id")
break
if id_:
res = api.photosets.addPhoto(
photoset_id=id_,
photo_id=photo_id)
else:
res = api.photosets.create(
title=photoset_title,
description="",
primary_photo_id=photo_id)
id_ = res.find("photoset").get("id") if res.get("stat") == "ok" else None
return id_
def main(path_to_photo, api_key='', secret_key='', is_create_photoset=True):
""" Main routine to upload photo and create photoset.
"""
api = flickrapi.FlickrAPI(api_key, secret_key)
if not api.token_valid():
# OOB: out of band
api.get_request_token(oauth_callback="oob")
verifier = str(input("Get verifier code from {} and enter it here.\n: ".format(
api.auth_url(perms="write"))))
# Get access token and store it as ${HOME}/.flickr/oauth-tokens.sqlite.
# If you want to remove the cache, call api.token_cache.forget().
api.get_access_token(verifier)
# Upload photo and get the ID.
photo_id = upload_photo(api, path_to_photo)
if not photo_id:
print("flickrapi.upload({}) failed.".format(path_to_photo))
exit(1)
if not is_create_photoset:
return
try:
taken_dt = get_taken_datetime_of(path_to_photo)
photoset_title = u"{}年{}月".format(taken_dt.year, taken_dt.month)
except:
print("Cannot create album due to no exif data in {}.".format(path_to_photo))
exit(1)
photoset_id = add_photo_to_photoset(api, photo_id, photoset_title)
if not photoset_id:
print("flickrapi.photosets failed? ({}, {})".format(photoset_id, path_to_photo))
if __name__ == "__main__":
args = parse_args()
main(
args.path_to_photo,
api_key=args.api_key,
secret_key=args.secret_key,
is_create_photoset=args.create_album)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment