Skip to content

Commit

Permalink
Add runkeeper tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
SamyPesse committed Oct 17, 2013
1 parent c6497a0 commit 14af5e6
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 9 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ FACEBOOK_CLIENTSECRET
# Callback url is {HOST}/auth/twitter/callback
TWITTER_CLIENTID
TWITTER_CLIENTSECRET
# Runkeeper oAuth
# Callback url is {HOST}/auth/runkeeper/callback
RUNKEEPER_CLIENTID
RUNKEEPER_CLIENTSECRET
```

#### Create your application and deploy it
Expand Down Expand Up @@ -121,10 +126,11 @@ Here is a list of trackers, I already built:
* GitHub: track coding activity on GitHub
* Facebook: track relations on Facebook (using Realtime API)
* Twitter: track twitter activity (tweets, mentions, ...)
* Runkeeper: track running activity

And more to come:

* Runkeeper: track running activity
* Fitbit
* Hardware:
* Track the temperature in a room (using tessel.io)

Expand Down
1 change: 1 addition & 0 deletions bin/reportr.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var modulesSection = {
"./tracker.foursquare",
"./tracker.twitter",
"./tracker.github",
"./tracker.runkeeper",
"./tracker.ping",

"./model.user",
Expand Down
Binary file added client/resources/images/models/runkeeper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/resources/images/trackers/runkeeper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 8 additions & 3 deletions lib/config/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ function setup(options, imports, register) {
'clientSecret': process.env.FOURSQUARE_CLIENTSECRET
},
'github': {
'interval': 6*60*60,
'clientId': process.env.GITHUB_CLIENTID,
'clientSecret': process.env.GITHUB_CLIENTSECRET
'interval': 6*60*60,
'clientId': process.env.GITHUB_CLIENTID,
'clientSecret': process.env.GITHUB_CLIENTSECRET
},
'runkeeper': {
'interval': 6*60*60,
'clientId': process.env.RUNKEEPER_CLIENTID,
'clientSecret': process.env.RUNKEEPER_CLIENTSECRET
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/logger/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ function setup(options, imports, register) {

var error = _.partial(print, 'error');
var log = _.partial(print, 'log');
var exception = _.wrap(error, function(func, logSection, err) {
var exception = _.wrap(error, function(func, logSection, err, kill) {
func(logSection, "Error ", err.message);
console.error(err.stack);

// Kill process
process.exit(1);
if (kill != false) process.exit(1);
});

register(null, {
Expand Down
113 changes: 113 additions & 0 deletions lib/tracker.runkeeper/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
var _ = require("underscore");
var moment = require('moment');
var RunKeeperStrategy = require('passport-runkeeper').Strategy
var runkeeper = require('node-runkeeper');

function setup(options, imports, register) {
var logger = imports.logger.namespace("tracker.runkeeper");
var trackers = imports.trackers;
var tasks = imports.tasks;

var tracker = trackers.register({
'id': "runkeeper",
'name': "Runkeeper",
'description': "Track your running activity from Runkeeper.",

'initConfig': function() {
_.defaults(this.config, {
'interval': 60*60
});
},

'initWeb': function() {
this.oauth(RunKeeperStrategy);
},

'initWorker': function() {
var that = this;

tasks.addTrackerTask(this, function(user) {
var userConfig = user.getTrackerSettings(that.id);
if (userConfig == null || userConfig.accessToken == null) return;

var client = new runkeeper.HealthGraph({
'client_id': that.config.clientId,
'client_secret': that.config.clientSecret
});
client.accessToken = userConfig.accessToken;
that.trackFitnessActivities(client, user, userConfig);
}, this.config.interval);
},

// Track user tweets
trackFitnessActivities: function(client, user, userConfig) {
var that = this;
var modelsDefined = [];

client.fitnessActivityFeed(client.accessToken, function(output) {
var data = {};

try {
data = JSON.parse(output);
} catch (err) {
logger.exception(err, false);
return;
}


if (!data.items) {
logger.error("Invalid runkeeper fitness data", data);
return;
}
_.each(data.items, function(activity) {
if (!activity.type
|| !activity.start_time
|| !activity.duration
|| !activity.total_distance
|| !activity.total_calories) {
logger.error("Invalid runkeeper activity", activity);
return;
}

var eventName = "activity"+activity.type;
var timestamp = moment(activity.start_time).unix() * 1000;

// Define model
if (!_.contains(modelsDefined, eventName)) {
modelsDefined.push(eventName);
user.setModel({
'eventNamespace': that.id,
'eventName': eventName,

'name': activity.type,
'icon': '$runkeeper',
'description': "Fitness activity "+activity.type+"."
});
}

// Add event
user.track({
'eventId': timestamp,
'namespace': that.id,
'name': eventName,
'properties': {
'duration': activity.duration,
'distance': activity.total_distance,
'calories': activity.total_calories,
'startTime': activity.start_time
},
'timestamp': timestamp
});
});
});
}
});


register(null, {
'tracker.runkeeper': tracker
});
};

// Exports
module.exports = setup;
16 changes: 16 additions & 0 deletions lib/tracker.runkeeper/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "tracker.runkeeper",
"version": "0.0.1",

"main": "./main.js",
"private": true,

"plugin": {
"consumes": [
"logger", "trackers", "tasks"
],
"provides": [
"tracker.runkeeper"
]
}
}
2 changes: 1 addition & 1 deletion lib/web.main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"consumes": [
"config", "logger", "database", "User", "notifications", "api", "trackers",
"tracker.chrome", "tracker.facebook", "tracker.foursquare",
"tracker.twitter", "tracker.github", "tracker.ping"
"tracker.twitter", "tracker.github", "tracker.runkeeper", "tracker.ping"
]
}
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@
"facebook-client": "1.6.1",

"passport-twitter": "1.0.2",
"twit": "1.1.11"
"twit": "1.1.11",

"passport-runkeeper": "0.1.2",
"node-runkeeper": "0.1.4"
},
"bin": {
"reportr": "./bin/reportr.js"
Expand Down
2 changes: 1 addition & 1 deletion public/static/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -25527,7 +25527,7 @@ Logger, Requests, Urls, Storage, Cache, Template, Resources, Deferred, Queue, I1
}
}
});
define('hr/args',[],function() { return {"map":{"apiKey":"AIzaSyAAeM47baWKdmKoqWeIuK5bQCxtur6mWm0"},"revision":1381999800489,"baseUrl":"/"}; });
define('hr/args',[],function() { return {"map":{"apiKey":"AIzaSyAAeM47baWKdmKoqWeIuK5bQCxtur6mWm0"},"revision":1382011516649,"baseUrl":"/"}; });
//! moment.js
//! version : 2.2.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
Expand Down
Binary file added public/static/images/models/runkeeper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/static/images/trackers/runkeeper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 14af5e6

Please sign in to comment.