예제 #1
0
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)
예제 #2
0
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}.')
예제 #3
0
    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
예제 #4
0
    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()
예제 #5
0
    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
예제 #7
0
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}.')
예제 #8
0
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']))
예제 #9
0
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
예제 #10
0
    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