Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

people.connections.list not returning contacts using Python Client Library

I'm trying to programmatically access the list of contacts on my own personal Google Account using the Python Client Library

This is a script that will run on a server without user input, so I have it set up to use credentials from a Service Account I set up. My Google API console setup looks like this.

enter image description here

I'm using the following basic script, pulled from the examples provided in the API docs -

import json
from httplib2 import Http

from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build

# Only need read-only access
scopes = ['https://www.googleapis.com/auth/contacts.readonly']

# JSON file downloaded from Google API Console when creating the service account
credentials = ServiceAccountCredentials.from_json_keyfile_name(
    'keep-in-touch-5d3ebc885d4c.json', scopes)

# Build the API Service
service = build('people', 'v1', credentials=credentials)

# Query for the results
results = service.people().connections().list(resourceName='people/me').execute()

# The result set is a dictionary and should contain the key 'connections'
connections = results.get('connections', [])

print connections  #=> [] - empty!

When I hit the API it returns a result set without any 'connections' key. Specifically it returns -

>>> results
{u'nextSyncToken': u'CNP66PXjKhIBMRj-EioECAAQAQ'}

Is there something pertaining to my setup or code that's incorrect? Is there a way to see the response HTTP status code or get any further detail about what it's trying to do?

Thanks!

Side note: When I try it using the "Try it!" feature in the API docs, it correctly returns my contacts. Although I doubt that uses the client library and instead relies on user authorization via OAuth

like image 460
user2490003 Avatar asked Jul 31 '16 02:07

user2490003


2 Answers

The personFields mask is required. Specify one or more valid paths. Valid paths are documented at https://developers.google.com/people/api/rest/v1/people.connections/list/.

Additionally, use fields mask to specify which fields are included in a partial response.

Instead of:

results = service.people().connections().list(resourceName='people/me').execute() 

... try:

results = service.people().connections().list(resourceName='people/me',personFields='names,emailAddresses',fields='connections,totalItems,nextSyncToken').execute() 
like image 115
B. McMahon Avatar answered Oct 07 '22 18:10

B. McMahon


Here is a working demo. I just tested it right now. Python 3.5.2

google-api-python-client==1.6.4
httplib2==0.10.3
oauth2client==4.1.2

You can save it to demo.py and then just run it. I left the create_contact function in case you might want to use it and have one more example on the API usage.

CLIENT_ID and CLIENT_SECRET are environment variables so I don't accidentally share that in code.

"""Google API stuff."""

import httplib2
import json
import os

from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow


CLIENT_ID = os.environ['CLIENT_ID']
CLIENT_SECRET = os.environ['CLIENT_SECRET']
SCOPE = 'https://www.googleapis.com/auth/contacts'
USER_AGENT = 'JugDemoStackOverflow/v0.1'

def make_flow():
    """Make flow."""
    flow = OAuth2WebServerFlow(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        scope=SCOPE,
        user_agent=USER_AGENT,
    )
    return flow


def get_people():
    """Return a people_service."""
    flow = make_flow()
    storage = Storage('info.dat')
    credentials = storage.get()
    if credentials is None or credentials.invalid:
        credentials = run_flow(flow, storage)

    http = httplib2.Http()
    http = credentials.authorize(http)
    people_service = build(serviceName='people', version='v1', http=http)
    return people_service


def create_contact(people, user):
    """Create a Google Contact."""
    request = people.createContact(
        body={
            'names': [{'givenName': user.name}],
            'phoneNumbers': [
                {'canonicalForm': user.phone, 'value': user.phone}],
        }
    )
    return request.execute()


def demo():
    """Demonstrate getting contacts from Google People."""
    people_service = get_people()
    people = people_service.people()
    connections = people.connections().list(
        resourceName='people/me',
        personFields='names,emailAddresses,phoneNumbers',
        pageSize=2000,
    )
    result = connections.execute()
    s = json.dumps(result)
    # with open('contacts.json', 'w') as f:
    #     f.write(s)
    return s


if __name__ == '__main__':
    print(demo())
like image 32
Jugurtha Hadjar Avatar answered Oct 07 '22 17:10

Jugurtha Hadjar