-
Notifications
You must be signed in to change notification settings - Fork 6
Circle Sync
- A Problem Needing a Solution
- Future-proofing the Design
- Using the Google+ Domains API
- Try It Yourself
- Possible Extensions
One of the most common questions I get asked about Google+ is “can I create a Circle that will automatically track the members of my team/project?” and the answer has always been “no.” Until now, that is. The Google+ Domains API provides access to a number of things, but for my purposes, the facilities to manage Circles meant that I was going to be able to start answering “yes” to that question.
To perform this task, we first need a way to match up a Circle we wish to maintain with a list of people who need to be in that Circle. I decided to start off using a simple text file containing a list of email addresses as this would allow me to concentrate on how I was going to use the API to do what I needed. Since someone might want to manage multiple Circles this way, I figured that a control file would be useful that contained the mapping from Circle name to the name of the file that contained the list of email addresses.
Here at Ocado, we have Active Directory security groups for our teams and projects to control access to a number of our systems (I’m sure that many companies do the same), so a final version of this application would sync with a list of email addresses looked up from an AD group rather than a flat file. With that in mind, I made sure this version of the application was modular in it’s data source so that you can easily plug in an interface to your source. I only provide simple file based processing here so that this example can concentrate on the use of the Google+ API. I’ll come back to how to plug another data source in after describing how the application currently works.
It was obvious that the best approach for this type of application was a command line tool. This would mean that any user who needed this functionality could run it, either manually, or, preferably, set it to run automatically at suitable intervals (depending on how often their Circles would change). Once configured, they’d be able to forget about it.
Now that I had a plan, I needed to check which parts of the API I needed and what authentication scopes this would require. Clearly, I needed to be able to create Circles and to add and remove members from them. I also realised that I was going to have to be able to look up people’s Google+ profiles based on their email address. This was because I wanted the configuration to use email addresses for user convenience, and I would need to be able to tell if they were already in the Circle (to add them if they were not, and to remove those who were no longer in my list) which I can only do using Google+ profile IDs. The required scopes were simply:
https://www.googleapis.com/auth/plus.mehttps://www.googleapis.com/auth/plus.circles.write
Google provide a useful example command line application that shows how to use the basics of the Google+ APIs (plus-cmdline-sample) and I shamelessly copied the code for authenticating from that. It also showed me how easy it was to use the API. Basically, Google APIs all tend to follow the same sort of pattern: you create a Get, List, Insert, etc object of the appropriate type, set your specific parameters to identify the information you want and then “execute” it. This, invariably, returns a “feed” which you can then loop through. If the feed contains a “nextPageToken” item, then there is more data available and, to obtain the next lot, you just add the token to your original request and re-execute it. Simple!
In order to run the application, you first need to register it for your own use. This can be done by going to the Google API console: https://code.google.com/apis/console/
Create an application, go to “Services” and make sure that “Google+ API” and “Google+ Domains API” are switched on. Next, in “API Access”, generate a client ID. Download this as JSON and replace the file client_secrets.json in the application project with your version.
The default configuration file is circle-sync.conf, though you can specify an alternate filename as an argument when you run it. Each line in this file must be the name of your list of email addresses and the name of your Circle separated by a colon (don’t include any extra spaces). I used a colon as the separator as it seemed unlikely to be used in one of the names. If you need to use a different separator, then look in the Config class. The name of the list should correspond to the filename containing the list and that file should contain one email address per line (again, with no spaces).
The application then converts each email address to a Google+ profile ID by doing a get of the People feed using their email address:
Person person = plus.people().get(email).execute();
and stores this along with the Circle name. We then get a list of the user’s Circles:
CircleFeed circleFeed = plus.circles().list("me").execute();
For each Circle we are trying to sync, we check to see if the Circle already exists. If it doesn’t, we create it:
Circle circle = new Circle();
circle.setDisplayName(newCircleName);
plus.circles().insert("me", circle).execute();
and if it does, then we get the list of people in the Circle:
PeopleFeed peopleFeed = plus.people().listByCircle(circleId).execute();
Now, we can match the two lists we have: those we want to be in the Circle and those already in it. For those who are missing, we add them:
Plus.Circles.AddPeople addPeople = plus.circles().addPeople(circleId);
addPeople.setUserId(peopleToAdd);
addPeople.setCircleId(circleId);
addPeople.execute();
and for those who are in the Circle and shouldn’t be, we remove them:
Plus.Circles.RemovePeople remove = plus.circles().removePeople(circleId);
remove.setUserId(peopleToRemove);
remove.setCircleId(circleId);
remove.execute();
That’s all there is to it! The application is written in Java and uses Maven to build. To make running easier, I have used the Appassembler plugin for Maven. Building the application is, therefore, simply a matter of running:
mvn package appassembler:assemble
This will create target/appassembler which contains the application and all frameworks used (in the repo folder) and a script to run the application for both Windows and Unix/Mac systems (in the bin folder).
I’ve already mentioned that I’ve designed this application so that it is very easy to add an alternate source location. All that needs to be done is to create a new implementation of the SourceLoader interface and implement the method getMembersForGroup() that takes the source name (which will, for me, be an AD group name), performs the lookup and returns the email addresses. The main CircleSync class can then be updated to use this new data source.
If you have multiple locations where you might need to obtain your lists from, then you could add an option in the main configuration file to specify the data source, which will determine which SourceLoader implementation to use for that Circle.
The source has now been updated with code to interface with an LDAP server (such as Active Directory) and the default build configuration will now expect to try and sync with an LDAP group. See the README file for details of how to configure this.