Using the People API with Apps Script

The BigQuiz app uses the People API to identify who is using it so that it can keep track of game and category scores. I could have used the Gplus api - which has an Apps Script advanced service, but I get the feeling that the People API is going to supersede the G+ API for this kind of usage. Apps Script doesn't have an advanced service for the people API, but it's JSON API is very easy to use. 

You can play with the BigQuiz app here.

The Result

I want to have this displayed on the App bar

and I also need an id against which to record the user's scores in Firebase, both of which are available from the People API.


Authorization

I could have accessed the people API from the client side using gapi, but I prefer to keep all my client secrets and API access on the server and also to manage all the authorization in one place (since I'll be accessing other APIS too), so I'll just access the API from the server. The App is running as the user accessing the App, so I need to follow the guidelines in Using OAuth2 when published as 'user accessing the webapp'. This means I have a one off Goa setup that looks like this, to generate an authorization and manage the token needed for the People API scope. The fileId is the Drive file id of the credentials downloaded from the developers console for my project, where I have enabled the People API. This can be deleted if you want after running once.
  cGoa.GoaApp.setPackage (PropertiesService.getScriptProperties() , 
    cGoa.GoaApp.createPackageFromFile (DriveApp , {
      packageName: 'jeopardy_demo',
      fileId:'0BxxxxxxxxxxxyYzQ',
      scopes : cGoa.GoaApp.scopesGoogleExpand ([
        'userinfo.profile',
        'user.emails.read'
      ]),
      service:'google'
  }));

Using the API

This is part of the BigQuiz Tracking namespace. getPlayer will fetch and get the primary values for the id, email, name and so on for the logged on user. Goa is used to retrieve an access token behind the scenes.
 ns.base = 'https://people.googleapis.com/v1/';

 /**
  * get player
  * @param {string} [id] if missing, gets the current players id 
  * @return {string} the playerid
  */
  ns.getPlayer = function (id) {
    var result  = ns.fetch ('people/' + 
      (id || 'me') + 
      '?fields=emailAddresses%2Cnames(displayName%2CfamilyName%2CgivenName%2Cmetadata)%2Cphotos');
    
    // create minimalized person
    function findPrimary (objects) {
      return objects && objects.length ? objects.filter (function(d) {
        return d.metadata.primary;
      })[0] : {};
    }
    
    return {
      photoUrl:findPrimary(result.photos).url,
      firstName:findPrimary(result.names).givenName,
      displayName:findPrimary(result.names).displayName,
      email:findPrimary(result.emailAddresses).value,
      id:findPrimary(result.emailAddresses).metadata.source.id
    }
  };
  


  /**
   * do the fetch
   * @param {string} url (not including the base)
   * @param {object} options not including the token
   * @return {object} the result
   */
  ns.fetch = function (url, options) {
    var options = options || {};
    options.headers = options.headers || {};
    options.headers.authorization = "Bearer " + ns.getToken();
    var result = cUseful.Utils.expBackoff ( function () {
      return UrlFetchApp.fetch ( ns.base + url, options);
    });
    return JSON.parse(result.getContentText());
  };
  ns.getGoa = function () {
    return cGoa.make (
      Demo.PACKAGE_APP.name, 
      Demo.PACKAGE_APP.props
    );
  };
  
  ns.getToken = function () {
    var goa = ns.getGoa();
    if (!goa.hasToken()) {
      throw 'there is no token available - did you do a consent dialog?';
    }
    return goa.getToken();
  };


Rendering the photo


It's nice to get the photo returned from the API in a circular frame.  The way to do it is with a rounded thick border, the same color as the App bar background


Set up the picture size in the app settings.
    player: {
      photoSize:50
    }

add an img element to hold the picture
<img id="playerphoto" class="picture-frame">

create some css to frame it
.picture-frame {
    width:62px;
    border:6px solid #2196F3;
    border-radius: 100px;
    -webkit-border-radius: 100px;
    -moz-border-radius: 100px;
}




For more like this, see Google Apps Scripts snippets. Why not join our forumfollow the blog or follow me on twitter to ensure you get updates when they are available. 





Comments