Meet my new personal assistants, Google Cloud Platform and AWS

Using Google Cloud Platform and AWS, I am building my own digital personal assistant. You’ll probably laugh at what the first task is my PA will be tackling!

This is going to sound ridiculous. In fact, as I’ve told people about what I’m doing over the last few weeks I start by informing them that I fully expect them to laugh, and that it’s okay. I fully expect you to laugh, too. Because, well, it really is funny. So let’s rip this bandaid off so I can get down to the details of what this idea is really about.

I’m automating setting up my hair appointments.

It’s ok. I’ll wait for you to finish laughing.

Now that you’ve had a good chuckle, let’s talk about how I’m doing this. There are a few things I have to first explain.

How it Began

To begin, I use an app across my various Apple-verse devices called OmniFocus. Some of you may have heard of it. It’s from OmniGroup. Essentially it’s a to-do list/task manager system. Wanted to better leverage the application and improve my time management I found my way to David Allen’s Getting Things Done. If you are even the least interested in personal productivity and have not read Allen’s book, I would encourage you to go buy a copy right now. It will revolutionize your life.

Allen is a strong advocate of a paper-based system. I take a different tact here. Early on I wanted to have a way to capture all of the actions I needed to do, and have that filing system available no matter where I was. Digital was a must. I quickly realized that I could instrument a few little hacks to improve upon this. I setup both Siri and Alexa to add Actions to my OmniFocus inbox. Then I wrote a Gmail filter that lets me move emails I want to follow up on into OmniFocus so I can track them. I also wrote a second filter that gives my wife the ability to email me a to-do task that likewise ends up in my app. All-in-all they made for some fun tinkering.

But I was certain I could do more. A lot more.

A few weeks ago I got a newsletter from Ramit Sethi. He’s built a business around helping others discover the value in themselves, and then helping them to build their own businesses. In the newsletter he wrote about some of his email “hacks” and “automation.” Even though they were rudimentary, they were enough to get me to thinking: as an initial step to really automating my personal workflow, what was something I could do as an experiment? I was in need of a hair cut, but I wasn’t getting around to making an appointment. Eureka! Why not let the computer do the work for me?!

Here was my challenge, write an application that can automatically run on a somewhat fluid schedule, processing schedule coordination with somewhat unpredictable humans rather than relatively predictable machines.

In my toolbox I had a few things.

OmniFocus

OmniFocus creates an iCal instance for upcoming items with a “due date” attached to them. I can also set these items to repeat at some interval, and that interval only gets triggered when I mark off the current task as complete. There is my variability, just in case I have to delay my haircut for a week or so.

The issue: OmniFocus’s server requires authentication, and that authentication was not documented anywhere. I would have to figure out how to get access to the system if I were to have my own program read the .ics file.

Google Calendar

Google Calendar is relatively straightforward to work with. That one can share calendars with others is extremely helpful. But even more powerful is that there is a series of APIs that a savvy engineer can tinker with to add on custom features. Additionally, event reminders can be delivered in a number of ways, including email, a feature, which you’ll soon see, that helps my service along.

The issue: Google Calendar does not have the means to authenticate against non-Google Calendar accounts behind a password wall. I would need to figure out how to sync my OmniFocus task calendar with Google so I could take advantage of the more advanced features.

Secondary issue: I’ve never worked with Google authorization, so there was a learning curve I needed to surmount.

Gmail

In working with the custom filters, I was awaken to the power of background code that could run against whatever messages came in. Things that are relatively known, such as a subject line beginning with “ToDo” from my wife’s email address could quickly be processed without my interaction. I could leverage an emailed reminder notification for scheduling my hair appointment to trigger a background task. This will check my availability, matched against a scheduling rule, and generate an email to be sent to the stylist. In turn, when the stylist writes back, I will then be able to trigger a second background task that will read the message and parse out the details.

Google Cloud Platform

This is the command center of my application. Now, why GCP instead of AWS? It would be grand if I could tell you about some deep level investigation I made, and how I evaluated each platform based on 237 different criteria. In reality, I started this with a misunderstanding on how Google’s authorization protocols between their Cloud Platform and their product API worked. I’m happy for the mistake, though. I was working with AWS at the office. Had I known about then about what I know now, I probably would have continued down that track. As it is I’ve learned a tremendous amount about the subtle differences between GCP and AWS. A comparison of their various strengths and weaknesses would make for a good future article.

For this task, I have used four main GCP features: Cloud Functions; Cloud Storage; Pub/Sub service; App Engine as a cron job service.

The issue: How do I leverage Cloud Functions, which in my use case is meant as a complete cloud-based background operation for syncing OmniFocus with Google Calendar but still provide a client interface that will allow me to authorize my app to work with Google?

Secondary issue: How do I store the client key data in a location that is accessible by the Function, which operates somewhat differently than a typical server instance?

AWS

One of the early realizations I made was that I didn’t need to be limited in taking advantage of great features offered by other cloud platforms simply because I went with one provider. While Google provides a bulk of the tools I would need, as would AWS had I gone that route, each service has a few things that stand out over the other. In the case of AWS it is Lex. Powered by the Alexa logic, it is a simple way to create a chatbot.

Piecing it Together

To rationalize the development, I’ve parsed out the work into four separate phases.

  1. Sync OmniFocus with Google Calendar on a regular interval
  2. Trigger background task from Calendar event trigger to generate availability list and email it to stylist
  3. Listen for stylist response; process email and compare day/time options to previously submitted availability; select first available, send confirmation to stylist and add event to my calendar
  4. If response does not conform to my previously submitted availability, use chatbot to inform me of options and ask what to do next; process my response and inform the stylist accordingly

Phase 1 – COMPLETE!

I’m writing this post because I’m thrilled to have finally finished Phase 1 late last night. It took a magnitude longer than I had originally expected, mostly because I almost all of my assumptions were rendered incorrect. Here are some highlights:

  • OmniGroup support was great in giving me information about their authentication process. Through this interaction I learned that they used Digest Auth. After a learning curve here – this project has had many firsts for me, including working with authentication – I was able to get it up and running.
  • AWS has an easy to use Schedule Task service as part of their offering. Google Platform was a little obtuse. Instead of going to a simple UI to set it up, I needed to learn how to setup and deploy a Google App Engine instance. That’s now ticking away once every hour.
  • Google Authorization proved the biggest challenge. From not knowing where/how I could access the keys and tokens from within and across Cloud Functions, to how I was going to click the “Allow” button required by Google. I finally overcame this creating a Cloud Function triggered via HTTP. This sends me to the Google auth page, and allows me to paste the token back into my app. I then leverage Cloud Storage as a sudo filesystem to manage the key/token pair across the Cloud Functions I’m running.
  • Finally, creating the Google Calendar events had a minor nuisance. The API documentation is less than clear. I submitted my event to be added, only to see the message “No end date”. Perplexed, because I had an end date and it looked just like the start date, which produced no error, I learned that these bits of data needed to fall under a sub-object header: resources. As I said, a slight inconvenience, but sorted.

This has been a great learning experience. I am thrilled to have gone from not knowing anything about Google Cloud Platform, not having worked with OAuth or any other authentication scheme, and getting introduced to the concept of “serverless” application design.

Stay tuned for further developments! I’ll be regularly updating on my progress.

Got a question, post it in the comments below. I’d love to hear from you!

Leave a comment