def upload_single(self, filepath, test=False): self.modified = False google_cache = GoogleLibrary.cache() google_image_filenames = google_cache.get('image_filenames') filename = os.path.basename(filepath) if filename in google_image_filenames: logging.info(f"Image already uploaded: '{filename}'") return elif test: logging.info(f"Image NEEDS uploading: '{filename}'") return image_spec_list = [{'filepath': filepath, 'filename': filename}] creds = GoogleService.credentials() try: if not test: self.upload_image_spec_list(image_spec_list, creds) finally: if self.modified: GoogleLibrary.save_library()
def upload_image_spec_list(self, image_spec_list, creds): # Get captions for each image self.get_image_spec_list_captions(image_spec_list) # Chunk the spec list upload to max size media_item_count = len(image_spec_list) chunk_size = 50 chunk_index = 0 while chunk_index < media_item_count: logging.info( f"Batch uploading images byes, chunk index '{chunk_index}'") # Get the list into chunks chunk_image_spec_list = image_spec_list[chunk_index:(chunk_index + chunk_size)] # Build new media item list for batch upload newMediaItems = [] for image_spec in chunk_image_spec_list: # Upload the images bytes to the google server self.upload_image_spec(image_spec, creds) # build newMediaItem = { 'description': image_spec.get('caption'), 'simpleMediaItem': { 'uploadToken': image_spec.get('upload_token'), 'fileName': image_spec.get('filename'), } } newMediaItems.append(newMediaItem) # Batch upload media items now request_body = {'newMediaItems': newMediaItems} logging.info( f"Batch uploading images for chunk index '{chunk_index}'") service = GoogleService.service() upload_response = service.mediaItems().batchCreate( body=request_body).execute() # Save the newly created images in local cache google_cache = GoogleLibrary.cache() google_image_ids = google_cache['image_ids'] google_image_filenames = google_cache['image_filenames'] if upload_response is not None: newMediaItemResults = upload_response.get( 'newMediaItemResults') for newMediaItemResult in newMediaItemResults: status = newMediaItemResult.get('status') message = status.get('message') if status else None if 'Success' == message: mediaItem = newMediaItemResult.get('mediaItem') GoogleLibrary.cache_image(mediaItem, google_image_ids, google_image_filenames) self.modified = True
def main(): gphoto.init() service = GoogleService.service() if not service: logging.error( "GoogleAlbums.cache_albums: GoogleService.service() is not initialized" ) return # Album name used albumName = "2060 API Album" imageid01 = 'ALE2QTBp8OkubJCEMGMr4GTsThO3qMLWTit1_5DRyyQOD4IBUu5LJ8qFGwEb8AFy2yrlNlFTgtKt' imageid02 = 'ALE2QTBGNjlDhWc7Y3gwpGtIKvba849RolzOtcQ8xFgz1dh8J-Jmwa8vX80cYAGxJDjUu9m58gUu' image_ids = [imageid01, imageid02] # Create album request_body = {'album': {'title': albumName}} response_google_album = service.albums().create( body=request_body).execute() album_id = response_google_album['id'] request_body = {'mediaItemIds': image_ids} response = service.albums().batchAddMediaItems( albumId=album_id, body=request_body).execute() print(response)
def main(): """ Test code to se if image caption can updated if the images was uploaded using Google Photos UI. This is not working at this time. You will see the following error: "code": 403, "message: "Request had insufficient authentication scopes" "status": "PERMISSION_DENIED" """ gphoto.init() cache = GoogleImages.load_images() filenames = cache['filenames'] image_name = "20050101_000436_OSWA_D70.jpg" image_idx = filenames[image_name] image = cache['list'][image_idx] # "ALE2QTAJEnDlApTBWwq-U5n0pg6ulXVp5wdAkqwXVj0knHwrKGcyqFoCt5x5CzeXd_1FUD4VEvrkAZzGaqOxiJIcrsuZmHgJYw" image_id = image['id'] request_body = { "description": f"{datetime.now()}: new-media-item-description" } service = GoogleService.service() response = service.mediaItems().patch( id=image_id, body=request_body ).execute() print(response)
def upload_album_names(album_names): gphoto.init() service = GoogleService.service() LocalLibrary.load_library('jpg') for album_name in album_names: Uploader.upload_album_name(service, album_name)
def upload_recursive(self, folder, recursive=True, test=False): logging.info(f"uploading images in folder: ({folder})") # Get only media types in the folder # image spec list holds a list of objects, sample below: # [ # { # 'filepath': ..., # 'filename': ..., # 'upload_token': ... # }, # { # .... next image object .... # } # ] image_spec_list = [] folder_items = os.listdir(folder) filenames = [ f for f in folder_items if os.path.isfile(os.path.join(folder, f)) and self.is_media(f) ] google_cache = GoogleLibrary.cache() google_image_filenames = google_cache.get('image_filenames') for filename in filenames: # If image already in cache then ignore if filename in google_image_filenames: logging.info(f"Image already uploaded: '{filename}'") continue elif test: logging.info(f"Image needs upload: '{filename}'") continue # Build the spec for each file filepath = os.path.join(folder, filename) image_spec = {'filepath': filepath, 'filename': filename} image_spec_list.append(image_spec) if len(image_spec_list) <= 0: logging.info(f"NO IMAGES TO UPLOAD IN FOLDER '{folder}'") else: creds = GoogleService.credentials() self.upload_image_spec_list(image_spec_list, creds) # Traverse sub-folders if recursive is specified if not recursive: return dirnames = [ d for d in folder_items if os.path.isdir(os.path.join(folder, d)) ] for dirname in dirnames: self.upload_recursive(os.path.join(folder, dirname), recursive, test)
def map_recursive(self, root, test): """ High-level algorithm: 1. For each local folder locate the Google album in cache 2. If Google album does not exist then call 'gphotocli album upload <...path_to_album...>' - Add local images to Google Album from the Local album if missing - Remove images from Google album that are not in Local album """ # Argument validation if not os.path.exists(root): logging.error(f"Folder does not exist: ({root})") return # Remove trailing slash slash_char = root[len(root) - 1] if slash_char == '/' or slash_char == '\\': root = root[:len(root)-1] # Get Google API service service = GoogleService.service() # Initialize Google API and load cache. google_cache = GoogleLibrary.cache() google_album_ids = google_cache.get('album_ids') google_album_titles = google_cache.get('album_titles') # Load local library cache local_cache = LocalLibrary.cache('jpg') local_albums = local_cache.get('albums') # Traverse all the sub folders in the cache for local_album in local_albums: local_album_name = local_album['name'] local_album_path = local_album['path'] if not local_album_path.lower().startswith(root.lower()): continue # If album not in Google Cache, ignore and then error out google_album_id = google_album_titles.get(local_album_name) google_album = google_album_ids[google_album_id] if google_album_id is not None else None if google_album is None: logging.error(f"Ignoring album not in Google Cache: '{google_album.get('title')}'") continue # Do mapping for each Local/Google album self.map_album(local_album, google_album, test)
def upload_recursive(self, root, test): # Argument validation if not os.path.exists(root): logging.error(f"Folder does not exist: ({root})") return # Remove trailing slash slash_char = root[len(root) - 1] if slash_char == '/' or slash_char == '\\': root = root[:len(root) - 1] # Get Google API service service = GoogleService.service() # Initialize Google API and load cache. google_cache = GoogleLibrary.cache() google_album_ids = google_cache.get('album_ids') google_album_titles = google_cache.get('album_titles') # Traverse all the sub folders in the cache local_cache = LocalLibrary.cache('jpg') local_albums = local_cache.get('albums') for local_album in local_albums: local_album_name = local_album['name'] local_album_path = local_album['path'] if not local_album_path.lower().startswith(root.lower()): continue # Check if album already in Google Cache google_album_id = google_album_titles.get(local_album_name) google_album = google_album_ids[ google_album_id] if google_album_id is not None else None if google_album is not None: logging.info( f"Album already uploaded: '{google_album.get('title')}'") continue # Do the actual creating of Google album album_response = self.create_shareable_album( service=service, album_name=local_album_name, test=test) if album_response: self.modified = True
def cache_images(): # Initialize images fields of the cache cache = GoogleLibrary.cache() google_image_ids = {} google_image_filenames = {} cache['image_ids'] = google_image_ids cache['image_filenames'] = google_image_filenames service = GoogleService.service() if not service: logging.error("GoogleLibrary.cache_images: GoogleService.service() is not initialized") return # Get the first page of mediaItems pageSize=100 response = service.mediaItems().list( pageSize=pageSize ).execute() mediaItems = response.get('mediaItems') nextPageToken = response.get('nextPageToken') for mediaItem in mediaItems: GoogleLibrary.cache_image(mediaItem, google_image_ids, google_image_filenames) # Loop through rest of the pages of mediaItems while nextPageToken: response = service.mediaItems().list( pageSize=pageSize, pageToken=nextPageToken ).execute() mediaItems = response.get('mediaItems') nextPageToken = response.get('nextPageToken') if mediaItems is not None: for mediaItem in mediaItems: GoogleLibrary.cache_image(mediaItem, google_image_ids, google_image_filenames) summary = cache.get('summary') summary['image_count'] = len(google_image_ids)
def __init__(self): LocalLibrary.load_library('jpg') GoogleLibrary.load_library() GoogleService.init() self.modified = False
def cache_album_images(): cache = GoogleLibrary.cache() # Service initialization service = GoogleService.service() if not service: logging.error("cache_album_images: GoogleService.service() is not initialized") return # Hold local vars for google images/albums cache google_image_ids = cache['image_ids'] google_image_filenames = cache['image_filenames'] google_album_ids = cache['album_ids'] google_album_titles = cache['album_titles'] # Initialize album_image and image_album caches album_images_cache = {} image_albums_cache = {} cache['album_images'] = album_images_cache cache['image_albums'] = image_albums_cache # Loop through each Google Album already cached # --------------------------------------------- for google_album_id, google_album in google_album_ids.items(): google_album_title = google_album.get('title') # logging.info(f"GAI: Processing album '{google_album_title}', '{google_album_id}'") # get first set of images for this album request_body = { 'albumId': google_album_id, 'pageSize': 100 } response = service.mediaItems().search(body=request_body).execute() mediaItems = response.get('mediaItems') nextPageToken = response.get('nextPageToken') # If there are no images in the album then move on to the next one if not mediaItems: continue for mediaItem in mediaItems: GoogleLibrary.cache_album_image_reln(mediaItem, google_album, google_album_ids, google_album_titles, google_image_ids, google_image_filenames, album_images_cache, image_albums_cache) # Loop through rest of the pages of mediaItems # ------------------------------------------------ while nextPageToken: request_body['pageToken'] = nextPageToken response = service.mediaItems().search(body=request_body).execute() mediaItems = response.get('mediaItems') nextPageToken = response.get('nextPageToken') for mediaItem in mediaItems: GoogleLibrary.cache_album_image_reln(mediaItem, google_album, google_album_ids, google_album_titles, google_image_ids, google_image_filenames, album_images_cache, image_albums_cache)
def cache_albums(): # Initialize album fields of the cache cache = GoogleLibrary.cache() google_album_ids = {} google_album_titles = {} cache['album_ids'] = google_album_ids cache['album_titles'] = google_album_titles service = GoogleService.service() if not service: logging.error("GoogleLibrary.cache_albums: GoogleService.service() is not initialized") return # Get unshared albums, first page pageSize=50 response = service.albums().list( pageSize=pageSize, excludeNonAppCreatedData=False ).execute() response_albums = response.get('albums') nextPageToken = response.get('nextPageToken') if response_albums: for album in response_albums: GoogleLibrary.cache_album(album, google_album_ids, google_album_titles, shared=False) # Loop through rest of the pages of unshared albums while nextPageToken: response = service.albums().list( pageSize=pageSize, excludeNonAppCreatedData=False, pageToken=nextPageToken ).execute() response_albums = response.get('albums') nextPageToken = response.get('nextPageToken') if response_albums: for album in response_albums: GoogleLibrary.cache_album(album, google_album_ids, google_album_titles, shared=False) # Get SHARED albums, first page response = service.sharedAlbums().list( pageSize=pageSize ).execute() response_albums = response.get('sharedAlbums') nextPageToken = response.get('nextPageToken') for album in response_albums: GoogleLibrary.cache_album(album, google_album_ids, google_album_titles, shared=True) # Loop through rest of the pages of albums while nextPageToken: response = service.sharedAlbums().list( pageSize=pageSize, pageToken=nextPageToken ).execute() response_albums = response.get('sharedAlbums') nextPageToken = response.get('nextPageToken') for album in response_albums: GoogleLibrary.cache_album(album, google_album_ids, google_album_titles, shared=True) summary = cache.get('summary') summary['album_count'] = len(google_album_ids)
def init(): AppData.init() LogMgr.init(AppData.APPDATA_NAME, LogMgr.DEFAULT_LOGNAME) GoogleService.init()