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 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