Philippe Khin
Autodownload/rename your photos on Google Drive with Python.
25 November 2016
First usage of an external API!
python
script
google-drive

Do you want to keep your Google Drive account clean ? This little script written in Python allows you to autodownload the latest photos someone share with you on Google Drive, and rename them according to the time they were taken, like 20161125_172800.jpg. Indeed, when a photo is taken, the photo file store a type of data called EXIF, with which you can get access to various information, like taken time, geolocation and other metadata.

But you can also modify the code to only download all the videos stored on your drive, or only pdf/word documents or anything else. This can be done by using the Google Drive API.  There's a library for Python called google-api-python-client. But I use PyDrive which is a wrapper library of google-api-python-client that simplifies many common Google Drive API tasks.

Note :  Photos that have been sent on Facebook Messenger, LINE or other chat app, loose their EXIF data, due to privacy stuff.

First, here's how the code looks like :

# Script to download the last updated pictures on Google Drive,
# and rename them if Exif data is available, if not, keep their original name.

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
import datetime, time

gauth = GoogleAuth()
gauth.LocalWebserverAuth() # Creates local webserver and auto handles authentication.

drive = GoogleDrive(gauth)

newFileUploadedFolder     = "newFileUploaded\\"
newFileUploadNoExifFolder = "newFileUploadNoExif\\"

# In order not to be asked to accept the user request of google each time the program is executed,
# several parameters are set in settings.yaml, which create the credentials.txt file to store informations.



def downloadFile(destinationFolder, file):
    filePic = drive.CreateFile({'id':file['id']})
    filePic.GetContentFile(destinationFolder + file['title'])

def renameFileWithExif(file):
    pictureName = file['imageMediaMetadata']['date']
    pictureName = pictureName.replace(":", "").replace(" ", "_")
    file['title']  = pictureName+".jpg"
    file.Upload()

def getCreatedDateOfFile(file):
    fileCreatedDate = file['createdDate']
    fileCreatedDate, head, tail = fileCreatedDate.partition(".")
    fileCreatedDate = fileCreatedDate.replace(":", "").replace("-", "").replace("T","")
    return fileCreatedDate

# Recursion from the root (MyDrive main folder) through others folder by using their ID,
# 'root' is the main MyDrive folder.
def ListFolder(parent):
    file_list = drive.ListFile({'q': "'%s' in parents and trashed=false" % parent}).GetList()
    for f in file_list:
        if f['mimeType']=='image/jpeg':
            if int(getCreatedDateOfFile(f)) < int(lastUploadedTime):
                pass
            else:
                try:
                    renameFileWithExif(f)
                    downloadFile(newFileUploadedFolder, f)
                    print("Downloading new uploaded files with EXIF...")
                    print (f['title'])
                except Exception:
                    print("Downloading new uploaded files with NO EXIF...")
                    downloadFile(newFileUploadNoExifFolder, f)
                    print (f['title'])

        if f['mimeType']=='application/vnd.google-apps.folder':     #if folder
            ListFolder(f['id'])



lastUploadedTime = open("lastUploadedTime.txt", "r").read()
ListFolder('root')
lastUploadedTime = open("lastUploadedTime.txt", "w").write(time.strftime("%Y%m%d%H%M%S", time.gmtime()))
print("\n================ DONE ================\n")
print("New files downloaded, last update: " + open("lastUploadedTime.txt","r").read())

finish = input("Quit? y (yes)\n")
if finish == "y":
  pass

Few things here:

- A folder can't be accessed directly by their name. The only folder that can be accessed is the root (the first folder when you open your Drive). That's why I do a recursive function which will check ALL the file on your drive. But this is done very quickly !

- Each time you launch this script, Google Drive's gonna ask you to log in. To keep logged in, you have to write this in a file (settings.yaml) you create in the same directory as your script. Here's the content :

save_credentials: true
save_credentials_backend: file
save_credentials_file: credentials.txt
client_config_file: client_secrets.json

This will create the credentials.txt file in the same directory file, which uses the client_secrets.json created when you activate the Google Drive API usage.

The trick here to download only the last photos uploaded, is to create a file in the same directory called lastUploadedTime.txt, whose content is only the date of the last time you launch this script. So start writing a date in this format :

20161125192231

which stands for : 2016/11/25 at 19:22:31.

So, photos that will be uploaded after this time, gonna be automatically download.

The script will download the latest uploaded and put them respectively in two folders you have to create beforehand (newFileUploaded and newFileUploadedNoExif) : one for photos which contain EXIF data, and another one without. For the latter, you have to modify manually their name, or just modify a little bit the code to rename them like picture_001.jpg, picture_002.jpg etc.

To get all the attributes of a file you can refer to the Google API Documentation.

Voila ! No need to bother yourself to do this tedious task !

For the complete code, please check my GitHub repository.

© 2020, Philippe Khin