Flickr and Google Drive photo synchronization in Python
- OAuth sign in
- Upload/download photos to/from Flickr albums and Google Drive folders
- Delete photos photos from Flickr and Google Drive
- Synchronize photos with Flickr and Google Drive
-
Depending on what service you plan to use, go to Flickr API and/or Drive API page to optain key and secret. Update them in photoSync/__init__.py respectively.
-
If you wish to specify folders to exclude from syncing, do so by changing EXCLUDE and/or EXCLUDE_IN_TITLE in photoSync/constants.py.
Default values:
EXCLUDE
=["^\.", "^__", "^@eaDir$"]
# Matching folders and its subfolders will not be syncedEXCLUDE_IN_TITLE
=["^_"]
# Matching folders will be synced but its parent folder will be chosen as an album name
-
Install the package
$ python3 setup.py install
Requires requests library and Python v3.+
For the most common usage is the app.py file located in the bin folder. This script can synchronize all your photos with Flickr and/or Google Drive. Run python3 app.py --help
to see how to use it. See bin/run.sh for an example.
While authorizing Flickr it usually throws signature_invalid error. If it occurs, authorize again, it should succeed after a couple of tries.
Signature is created in helper.py by fr_build_signature(url, s, post, secret) function. Weirdly it always works when logged in but sometimes fails when not.
Classes:
Other files:
- __init__.py
- constants.py
- helper.py
-
__init__(directory = os.path.dirname(os.path.realpath(__file__)), scope = 0)
- arguments directory -- session file folder scope -- 1: use Flickr only, 2: use Google Drive only, 0: use both
-
check()
- checks if authorization required
- arguments
None
- return values 0 -- already signed in 1 -- authorization required
-
authorize()
- makes the authorization given the scope
NEEDS USER INTERACTION AND WEB BROWSER
- arguments
None
- return values 0 -- success (signed in) 1 -- error
-
sync(self, directory, upload = True, save = True, delete = False, max = 0, wait = 0)
- synchronizes local photos with the cloud services
IF ANY ERRORS OCCUR, IT SKIPS THE FILE/ALBUM AND TRIES TO CONTINUE
- arguments directory -- the 'root' folder where the albums are upload, save, delete -- [True/False] whether to upload, save or/and delete photos in cloud max -- maximal number of operations for each service (0 means unlimited) wait -- time in seconds to wait between operations
- return values 1 -- error that made impossible to continue None -- otherwise
Static class to handle local files.
- get_all_albums(directory) @static
- searches through the folders to create album list
- arguments directory -- 'root' folder for the albums
- return values {} -- sorted dictionary of {album name: [all matching folders]} due to the 'EXCLUDE_IN_TITLE' and naming of subfolders, there can be multiple folders to one album name
- get_photos_in_directories(directories) @static
- finds all photos in given directories
- arguments directories -- array of directories to search through ALL FILENAMES ACROSS THE DIRECTORIES HAVE TO BE UNIQUE
- return values {} -- sorted dictionary of {photo file name: path to the photo}
- compare_photosets(ps1, ps2) @static
- compares photosets and returns missing files in each one
- arguments ps1 -- first photoset (dictionary of {'name': object}) ps2 -- second photoset
- return values tuple -- (dictionary of {'name': object} missing in the first one, the same for the 2nd)
Class to handle both Flickr and Google Drive authorization.
- __init__(sclass)
- arguments sclass -- Session-class object
- fr_auth(), gd_auth()
- makes the authorization and stores user's credentials to the session file
- arguments
None
- return values 0 -- success 1 -- error
- get_authorization_code(url) -- called by fr_auth and gd_auth
- gets authorization code which is passed as paremeter in callback URL
- arguments url -- url to open in browser
- return values string -- callback URL with the needed parameter
- gd_refresh()
- refreshes the Google access token (required at least every hour)
- arguments
None
- return values 0 -- success 1 -- error
Class to handle loading and storing login data to a .session file.
- SCOPE -- 1: use Flickr only, 2: use Google Drive only, 0: use both
- SESSION -- the session variable
- __init__(directory)
- arguments directory -- session file folder
- set_scope(scope)
- sets scope variable used throughout the app to determine what to sync
- arguments scope -- scope to use (sets the SCOPE variable)
- session_load()
- loads session file to variable
- session_write(data)
- updates the session variable and the session file
- arguments data -- (updated) session variable
- session_check(scope = None)
- checks if session file contains necessary tokens given the scope
- arguments scope -- 1: use Flickr only, 2: use Google Drive only, 0: use both if None, the scope variable is used
Class to handle the cloud work
scope -- 1: Flickr function, 2: Google Drive function, 0 not permitted
- __init__(sclass)
- arguments sclass -- Session-class object
- gd_get_base_folder(search = False, create = True)
- loads stored, searches Google Drive and/or creates the base folder for the albums if necessary
- arguments search (optional) -- [True/False] search the root folder for 'DRIVE_FOLDER_NAME' create (optional) -- [True/False] create the folder
- return values 0 -- base folder exists returned also when it was impossible to store the folder id forever 1 -- error
- create_album[scope](name[, primary_photo_id, description = ""])
- creates Google Drive album folder or creates and adds the first photo to a new album on Flickr
- arguments name -- album name FLICKR: primary_photo_id -- id of a album cover photo (the photo is automaticaly added to the album) description (optional) -- album description
- return values string -- album id 1 -- error
- upload_file[scope](path, name, album_id)
- uploads file to Google Drive folder of to Flickr and adds it to an album (if specified)
- arguments path -- path to the file name -- file name album_id -- id of an album which the photo is uploaded to (FLICKR: when uploading first photo of album, leave empty since album does not exit yet)
- return values string or integer -- file id 1 -- error
- list_albums[scope]()
- lists all folders in Google Drive BASE_FOLDER or lists all albums on Flickr
- arguments
None
- return values {} -- sorted dictionary of pairs {album name: album id} 1 -- error
- list_photos[scope](album_id)
- lists all photos in Google Drive folder or lists photos in album on Flickr
- arguments album_id -- album id to list from
- return values {} -- sorted dictionary of pairs {photo file name: {photo object as specified in Drive and Flickr API}} 1 -- error
- download_file[scope](photo, directory)
- downloads a photo to a local folder
- arguments photo -- photo object from list_photos function directory -- path where to store the photo
- return values 0 -- success 1 -- error
- delete_file[scope](id)
- deletes file specified by its id
- arguments id -- file id
- return values 0 -- success 1 -- error