-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Usage example: Create Google Calendar entries from your daily Strava Training Plan
This usage example was written by @Chaosspeeder.
Ok, this sound silly and maybe it is, but I want to use my (poor) coding skills to automate things as far as possible and I also want to participate at a marathon this year. Oh and by the way, I am not the youngest person on earth anymore :-)
For preparation for my marathon I started a training plan on Strava, a platform for fitness enthusiasts. Strava send me a daily instruction for my training via email. But I want the instructions as a google calendar entry, where I organize all things through a day. So I started dealing with Huginn, to gain experience in automating things.
I created in Huginn a workflow like this:
And combined the needed agents in one scenario:
I use the IMAP Folder agent to check gmail several times a day for a new mail from Strava:
{
"expected_update_period_in_days": "1",
"host": "imap.gmail.com",
"ssl": true,
"username": "{% credential google_username %}",
"password": "{% credential google_password %}",
"folders": [
"INBOX"
],
"conditions": {
"subject": "Strava Trainingsplan - Woche \\d+ Tag \\d+"
}
}
This agent generates an event payload with the important data of the fetched mail: subject and body.
Now the things become somewhat nasty. The needed information about the training is buried in the body of the mail. I have to extract the information via regular expressions and must create a message structure, which is consumable from the Google Calendar Api
My first idea failed. I want to use the Trigger Agent to extract and reformat data. Unfortunately, the needed date was formatted as long german text and the Google Calendar Publisher Agent needs a date formatted in RFC 3339. I would have needed some very special liquid filter functions to achieve this way.
But Huginn has a nice JavaScript agent, a swiss knife for all more complex requirements.
The JavaScript looks like this:
function ISODateString(d){
function pad(n){return n<10 ? '0'+n : n}
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'}
var monthArray = [ "Januar", "Februar", "März", "April", "Mai",
"Juni", "Juli", "August", "September", "Oktober",
"November", "Dezember" ]
Agent.receive = function() {
var events = this.incomingEvents();
for(var i = 0; i < events.length; i++) {
var body = events[i].payload['body']
var summary = events[i].payload['subject']
var germanDate = body.match(/\w+, (\d+). (\w+) (\d+)/)
var day = germanDate[1]
var month = monthArray.indexOf(germanDate[2])
var year = germanDate[3]
var startDate = new Date(year, month, day, 18, 0, 0, 0)
var endDate = new Date(year, month, day, 21, 0, 0, 0)
this.createEvent(
{ 'message':
{ 'summary': summary,
'visibility': 'default',
'description': body,
'start': {
'dateTime': ISODateString(startDate)
},
'end': {
'dateTime': ISODateString(endDate)
}
}
}
);
}
}
This code fetches the data out of the body of the email and create a data structure consumable from the Google Calendar Publisher Agent. By the way, I love the log statement in JavaScript. This made debugging the script very comfortable.
I have to admit. The Google Calendar Publisher Agent is a tiny shell about the Google Calendar Api. You have to create a message structure with an agent (usually trigger agent) and the Google Publisher send it with your api token to the google interface:
Unfortunately, this Agent doesn't support liquid, so I couldn't separate my credentials from the logic:
I needed a long time, to get the following configuration working. Gently hint: Please authorize the google service email account for modifying your calendar.
{
"expected_update_period_in_days": "10",
"calendar_id": "joe@gmail.com",
"google": {
"key_file": "/home/huginn/Huginn-en453454343.p12",
"key_secret": "notasecret",
"service_account_email": "hugin-443@huginn-43434.iam.gserviceaccount.com"
}
}