Last active
May 4, 2023 21:40
-
-
Save dodo5522/73dc07a0fb71af75dc81c07984126179 to your computer and use it in GitHub Desktop.
Python script to upload a photo into flickr.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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