def delete_service_account_key( iam_client: googleapiclient.discovery.Resource, service_account_key_name: str, ): iam_client.projects().serviceAccounts().keys().delete( name=service_account_key_name, ).execute() logger.info('Deleted key: ' + service_account_key_name)
def upload_thumbnail(video_id: str, service: googleapiclient.discovery.Resource): VIDEO_THUMBNAIL_FILE = os.path.abspath( os.path.join('content', 'images', 'youtube-thumbnail.jpg')) print('> [YouTube Robot] Starting video thumbnail upload...') try: service.thumbnails().set(videoId=video_id, media_body=VIDEO_THUMBNAIL_FILE).execute() print('> [YouTube Robot] The thumbnail was successfully set.') except HttpError as http_error: if http_error.resp.status == 403 and http_error.resp.reason == 'Forbidden': print( '> [YouTube Robot] Error uploading thumbnail: you must have a verified account to upload custom ' 'thumbnails.') else: raise except MediaUploadSizeError: print( '> [YouTube Robot] Error uploading thumbnail: your thumbnail file is larger than 2MB.' ) except Exception as e: print(f'> [YouTube Robot] Error uploading thumbnail: {e}.')
def _delete_objects(self, bucket_name: str, storage_service: googleapiclient.discovery.Resource): """Delete all objects in the given bucket. Needed by clean_up_bucket. Args: bucket_name: Name of the cluster to delete. storage_service: Google client to make api calls. """ request = storage_service.objects().list(bucket=bucket_name) response = request.execute(num_retries=5) if 'items' in response: # This bucket might be empty object_names = [item['name'] for item in response['items']] for object_name in object_names: request = storage_service.objects().delete(bucket=bucket_name, object=object_name) try: request.execute(num_retries=5) except errors.HttpError: # These functions are only used in tests and resource # cleanings. These are not parts of workflows. # In E2E tests, sometimes a the program fail to create an # object, trying to delete it will cause errors to get # thrown here. Error messages here is misleading and hides # the real cause of test failures. pass
def _delete_objects(self, bucket_name: str, storage_service: googleapiclient.discovery.Resource): """Delete all objects in the given bucket. Needed by clean_up_bucket. Args: bucket_name: Name of the cluster to delete. storage_service: Google client to make api calls. """ request = storage_service.objects().list(bucket=bucket_name) response = request.execute() object_names = [item['name'] for item in response['items']] for object_name in object_names: request = storage_service.objects().delete( bucket=bucket_name, object=object_name) request.execute()
def update_photo(self, service: googleapiclient.discovery.Resource, new_photo: str) -> bool: """Updates the photo of the contact with the Gravatar photo. This method updates the photo of the contact with the supplied photo, and records that the photo came from Gravatar (by setting the custom Gravatar Photo field set to True. :param service: the People API service (a Resource) :type service: googleapiclient.discovery.Resource :param new_photo: the new photo as a base-64 encoded string :type new_photo: str :return: `True` on success, `False` on failure :rtype: bool """ LOGGER.debug("Updating photo for %s with res name %s", self.name, self.res_name) try: # Save to the contact that the photo is from Gravatar service.people().updateContact(resourceName=self.res_name, updatePersonFields="userDefined", body={ "etag": self.etag, "userDefined": [{ "key": "Gravatar Photo", "value": "True" }] }).execute() LOGGER.info("Contact updated with custom field Gravatar=True.") # Update the photo service.people().updateContactPhoto(resourceName=self.res_name, body={ "photoBytes": new_photo }).execute() LOGGER.info("Contact photo updated.") return True except Exception as err: print(err) return False
def pages( resource: googleapiclient.discovery.Resource, # e.g. androidmanagement.enterprises().devices() *args, **kwargs): "Given e.g. devices(), iterate over each page of responses." request = None while True: if request is None: # first iteration through "while True" request = resource.list(*args, **kwargs) else: # subsequent iteration through "while True" request = resource.list_next( previous_request=request, previous_response=response) if request: # on last page, list_next() returns None response = request.execute() yield response else: break
def upload_video(content: Content, service: googleapiclient.discovery.Resource) -> str: VIDEO_FILENAME = os.path.abspath(os.path.join('content', 'output.mp4')) VIDEO_TITLE = f'{content.search_prefix} {content.search_term}' VIDEO_DESCRIPTION = '\n\n'.join(sentence.text for sentence in content.sentences) VIDEO_PRIVACY_STATUS = 'public' VIDEO_TAGS = [keyword for keyword in content.sentences[0].keywords] VIDEO_TAGS.insert(0, content.search_term) body = { 'snippet': { 'title': VIDEO_TITLE, 'description': VIDEO_DESCRIPTION, 'tags': VIDEO_TAGS }, 'status': { 'privacyStatus': VIDEO_PRIVACY_STATUS } } print('> [YouTube Robot] Starting video upload...') try: insert_request = service.videos().insert(part=','.join(body.keys()), body=body, media_body=MediaFileUpload( VIDEO_FILENAME, chunksize=-1, resumable=True)) video_id = resumable_upload(insert_request) print('> [YouTube Robot] Video upload done!') return video_id except HttpError as http_error: print( f'> [YouTube Robot] An HTTP error {http_error.resp.status} occurred: \n{http_error.content}.' ) except Exception as e: print(f'> [YouTube Robot] Error: {e}.')
def _create_service_account_key( iam_client: googleapiclient.discovery.Resource, service_account_name: str, ) -> dict: ''' Creates a key for a service account. ''' key_request = iam_client.projects().serviceAccounts().keys().create( name=service_account_name, body={}, ) try: key = key_request.execute() except googleapiclient.errors.HttpError as e: logger.error( 'unable to create key, probably too many (10) active keys?') raise e logger.info('Created key: ' + key['name']) return json.loads(base64.b64decode(key['privateKeyData']))
def get_subscribers(youtube: googleapiclient.discovery.Resource, chids: str): """Get the number of subscribers. Args: youtube (googleapiclient.discovery.Resource): Sesstion instance. chids (str): Youtube channel IDs. Return: chid_subsc_list (list): 2D-list including ["chid", "subscribers"] """ channels_response = youtube.channels().list(part="id,snippet,statistics", id=chids).execute() items = channels_response.get("items", []) chid_subsc_list = [] for item in items: chid = item["id"] subscribers = int(item["statistics"]["subscriberCount"]) chid_subsc_list.append([chid, subscribers]) chid_subsc_list = sorted(chid_subsc_list, key=itemgetter(1), reverse=True) return chid_subsc_list
def list_contacts(service: googleapiclient.discovery.Resource) -> list: """Fetches the user's contacts as a list. This will fetch the user's contacts that have a name and an email address. It will return them as a list of Contact objects. :param service: the People API service (a Resource) :type service: googleapiclient.discovery.Resource :return: a list of Contact objects :rtype: list """ # Fetch the user's contacts (up to 2000) results = service.people().connections().list( resourceName='people/me', pageSize=2000, personFields='names,emailAddresses,photos,UserDefined').execute() connections = results.get('connections', []) LOGGER.info("Contacts retrieved.") contacts = [] for contact in connections: # Get the contact resource name res_name = contact["resourceName"] etag = contact["etag"] # Get the name and email address # If both aren't there then skip the contact emails = [] if "names" in contact and "emailAddresses" in contact: name = contact["names"][0]["displayName"] for email in contact["emailAddresses"]: emails.append(email["value"]) else: LOGGER.info("Contact skipped.") continue # Determine if the contact already has a user-supplied photo # This will stay false there's a photo from their Google profile # photo["default"] is only present if it's true, # so if it's not there then this is not the default has_user_photo = False if "photos" in contact: for photo in contact["photos"]: if photo["metadata"]["source"]["type"] == "CONTACT" and \ "default" not in photo: has_user_photo = True # Determine if that photo was already supplied from Gravatar # This will stay false if has_user_photo is false is_gravatar = False if "userDefined" in contact: for custom in contact["userDefined"]: if custom["key"] == "Gravatar Photo" and \ custom["value"] == "True": is_gravatar = True assert has_user_photo is True or \ (has_user_photo is False and is_gravatar is False) # Save this contact's details contacts.append( Contact(res_name, name, emails, has_user_photo, is_gravatar, etag)) LOGGER.info("New contact saved") LOGGER.debug("New contact called %s with res name %s", name, res_name) return contacts