Permalink
Browse files

First (pre-)release version, login works, only shows list of runs, no…

… export yet.
  • Loading branch information...
1 parent dbdaf2b commit 5aceb9c897183fe1fa1f2811f522e388adc5cc56 @eagereyes committed Jul 9, 2012
Showing with 177 additions and 77 deletions.
  1. +7 −0 ReadMe.md
  2. +11 −9 app.js
  3. +2 −3 package.json
  4. +6 −6 routes.js
  5. +4 −0 static/css/style.css
  6. +77 −7 user.js
  7. +20 −0 views/export.jade
  8. +20 −26 views/index.jade
  9. +27 −24 views/layout.jade
  10. +3 −2 views/{login-redirect.jade → redirect.jade}
View
@@ -0,0 +1,7 @@
+# Dependencies
+
+* [express](http://expressjs.com/)
+* [jade](http://jade-lang.com/)
+* [connect-memcached](https://github.com/balor/connect-memcached)
+* [queue-async](https://github.com/mbostock/queue)
+* [mysql](https://github.com/felixge/node-mysql)
View
@@ -4,7 +4,7 @@
*/
var express = require('express')
- , jog = require('jog')
+ , queue = require('queue-async')
, mysql = require('mysql')
, user = require('./user.js')
, run = require('./run.js')
@@ -15,8 +15,6 @@ var MemcachedStore = require('connect-memcached')(express);
var dbClient = mysql.createClient(dbConf);
-var log = jog(new jog.FileStore('status.log'));
-
var app = module.exports = express.createServer();
var PORT = 5555;
@@ -48,15 +46,19 @@ app.configure('production', function(){
app.get('/', routes.index);
-app.get('/index-login', routes.index_login);
-
-app.get('/nike-login', function(req, res){
- req.session.userID = user.newUser(dbClient, req.session.userID || -1,
- req.query.nuid, req.query.oauth_token, req.query.access_token).userID;
-// res.end(JSON.stringify(req.query)+'\n'+JSON.stringify(req.session));
+app.get('/nike-login', function(req, res) {
+ req.session.userID = user.login(dbClient, req.query.nuid, req.query.oauth_token, req.query.access_token);
routes.redirectLogin(req, res);
});
+app.get('/export', function(req, res) {
+ if (req.session.userID == undefined) {
+ res.render('redirect', { title: 'Redirecting ...', redirectURL: 'http://eagerfeet.org/'})
+ } else {
+ user.getActivities(req.session.userID, res);
+ }
+});
+
user.loadUsers(dbClient);
app.listen(PORT, function(){
View
@@ -4,10 +4,9 @@
, "private": true
, "dependencies": {
"express": ">= 2.5.9"
- , "jade": ">= 0.0.1"
+ , "jade": ">= 0.26.0"
, "mysql": ">= 0.9.6"
- , "jog": ">= 0.3.0"
, "connect-memcached": ">= 0.0.3"
- , "node-runkeeper": ">= 0.1.4"
+ , "queue-async": ">= 0.0.2"
}
}
View
@@ -4,13 +4,13 @@
*/
exports.index = function(req, res){
- res.render('index', { title: 'eagerfeet 2', login: false, userID: req.session.userID || 'nobody' })
-};
-
-exports.index_login = function(req, res){
- res.render('index', { title: 'eagerfeet 2', login: true, userID: req.session.userID || 'nobody' })
+ if (req.session.userID != undefined) {
+ res.render('redirect', { title: 'Redirecting ...', redirectURL: 'http://eagerfeet.org/export'})
+ } else {
+ res.render('index', { title: 'eagerfeet'})
+ }
};
exports.redirectLogin = function(req, res) {
- res.render('login-redirect', { title: 'Login successful', redirectURL: 'http://eagerfeet.org/index-login' })
+ res.render('redirect', { title: 'Login successful!', redirectURL: 'http://eagerfeet.org/export'})
}
@@ -9,4 +9,8 @@ div.logo {
div.nike-login {
padding-top: 10px;
+}
+
+li.run {
+ margin-top: .5em;
}
View
@@ -3,6 +3,37 @@ var users = {};
var maxUserID = 1000;
+var https = require('https');
+
+function serverRequest(path, params, resultFunc) {
+
+ var queryString = '';
+ var numParams = 0;
+
+ for (var key in params) {
+ if (params.hasOwnProperty(key)) {
+ queryString += ((numParams == 0) ? '?' : '&');
+ queryString += key+'='+params[key];
+ numParams += 1;
+ }
+ }
+
+ var options = {
+ host: 'api.nike.com',
+ path: path + queryString
+ };
+
+ https.get(options, function(response) {
+ var body = '';
+ response.on('data', function(chunk) {
+ body += chunk;
+ });
+ response.on('end', function() {
+ resultFunc(body);
+ });
+ });
+}
+
exports.loadUsers = function(dbClient) {
dbClient.query('select * from Users', function(err, results, fields) {
if (err) {
@@ -17,14 +48,53 @@ exports.loadUsers = function(dbClient) {
});
}
-exports.newUser = function(dbClient, userID, nikeUID, nikeOAuthToken, nikeAccessToken) {
- if (userID < 0) {
- userID = maxUserID;
+exports.login = function(dbClient, nikeUID, nikeOAuthToken, nikeAccessToken) {
+ var user = null;
+ for (var userID in users) {
+ if (users[userID].nikeUID == nikeUID) {
+ user = users[userID];
+ }
+ }
+ if (user == null) {
+ userID = maxUserID+1;
maxUserID += 1;
+ var user = {userID: userID, nikeAccessToken: nikeAccessToken, nikeOAuthToken: nikeOAuthToken, nikeUID: nikeUID};
+ dbClient.query('insert into Users (userID, nikeUID, nikeOAuthToken, nikeAccessToken) values (?,?,?,?);',
+ [userID, nikeUID, nikeOAuthToken, nikeAccessToken]);
+ users[userID] = user;
}
- var user = {userID: userID};
- dbClient.query('replace into Users values (?,?,?,?);', [user.userID, nikeUID, nikeOAuthToken, nikeAccessToken]);
- users[userID] = user;
- return user;
+ return user.userID;
}
+function getUser(userID) {
+ return users[userID];
+}
+
+exports.getUser = getUser;
+
+function pad(num) {
+ return (num < 10) ? ('0' + num) : ('' + num);
+}
+
+exports.getActivities = function(userID, res) {
+ var user = getUser(userID);
+ serverRequest('/partner/sport/run/activities', {access_token: user.nikeAccessToken, start: 0, end: 100}, function(data) {
+ var activities = JSON.parse(data).activities;
+ activities.reverse();
+ activities.forEach(function(run) {
+ var seconds = run.activity.metrics.totalDuration/1000;
+ if (seconds < 60 * 60) {
+ var minutes = Math.floor(seconds/60);
+ seconds -= minutes*60;
+ run.time = pad(minutes)+':'+pad(seconds);
+ } else {
+ var hours = Math.floor(seconds/3600);
+ seconds -= hours*3600;
+ var minutes = Math.floor(seconds/60);
+ seconds -= minutes*60;
+ run.time = pad(hours)+':'+pad(minutes)+':'+pad(seconds);
+ }
+ });
+ res.render('export', {activities: activities});
+ });
+}
View
@@ -0,0 +1,20 @@
+extends layout
+
+block append main
+ div.row
+ div.span8
+ h1 Export
+
+ p A list of your runs on Nike+ (only shows the 100 most recent for now):
+ div#runs
+ ul
+ each run in activities
+ li.run #{run.activity.name},
+ - var miles = (run.activity.metrics.totalDistance/1.609344).toFixed(2)
+ - var kms = run.activity.metrics.totalDistance.toFixed(2)
+ | #{miles} mi / #{kms} km in #{run.time}, #{run.activity.metrics.totalCalories} calories
+ if run.activity.metrics.averageHeartRate > 0
+ i.icon-heart
+// p Checking for new runs ...
+// div#progressbar.progress.progress-striped.active
+// div.bar(style="width: 100%;")
View
@@ -1,28 +1,22 @@
extends layout
-block append content
- div.container
- div.row
- div.logo.span12
- img(src='/img/header.png', width='820', height='110')
- div.row
- div.span8
- h1 Welcome to #{title}!
- if (login)
- if (userID != 'nobody')
- p User #{userID}
- div.nike-login
- script(id="nikeoauth",
- data-clientid="54dff1e61f4ac4a56c98ad57ef3ed377",
- data-userid="#{userID}",
- src="https://www.nike.com/profile/assets/oauth/js/nikeoauth.min.js")
- div#runs
- else
- p This site is currently being rewritten from scratch to work with Nike's new authenticaton scheme and to make it easier to add more features later. Please
- a(href='http://blog.eagerfeet.org/')
- | check out the blog
- | or
- a(href='http://twitter.com/eagerfeet')
- | follow me on twitter
- | for updates.
- p The login issues are largely solved, but I am struggling with some other parts of the site's backend right now (and lack of time). I will post on the blog and on Twitter when the new site is ready for you to test. Please bear with me a few more days, the site will be back soon.
+block append main
+ div.row
+ div.logo.span12
+ img(src='/img/header.png', width='820', height='110')
+ div.row
+ div.span8
+ h1 Welcome to eagerfeet, Limited Preview Edition!
+ p Please use the button below to log in using your Nike+ credentials. Once logged in, you will see a list of your most recent runs. You will not be able to actually export those runs at this point, but you will be in a few days.
+ p For more details and updates,
+ a(href='http://blog.eagerfeet.org/')
+ | check out the blog
+ | or
+ a(href='http://twitter.com/eagerfeet')
+ | follow me on twitter
+ | .
+ div.nike-login
+ script(id="nikeoauth",
+ data-clientid="54dff1e61f4ac4a56c98ad57ef3ed377",
+ data-userid="nobody",
+ src="https://www.nike.com/profile/assets/oauth/js/nikeoauth.min.js")
View
@@ -1,12 +1,12 @@
-!!! html
+doctype html
html(lang="en")
head
meta(charset='utf-8')
- title= title
- block head
+ title eagerfeet
+ link(rel='stylesheet', href='/css/bootstrap-2.0.4.min.css')
+ link(rel='stylesheet', href='/css/style.css')
+ block header
meta(name='viewport', content='width=device-width, initial-scale=1.0')
- link(rel='stylesheet', href='/css/bootstrap-2.0.4.min.css')
- link(rel='stylesheet', href='/css/style.css')
//- Le HTML5 shim, for IE6-8 support of HTML5 elements
//if lt IE 9
script(src='http://html5shim.googlecode.com/svn/trunk/html5.js')
@@ -28,22 +28,25 @@ html(lang="en")
a(href='/') Home
li
a(href='http://blog.eagerfeet.org/') blog
- //- Tracking code, please remove if you use this somewhere else!
- script(src='http://static.getclicky.com/js', type='text/javascript')
- script(type='text/javascript') try{ clicky.init(66409777); }catch(e){}
- noscript
- p
- img(alt='Clicky', width='1', height='1', src="http://in.getclicky.com/66409777ns.gif')
- script(type='text/javascript')
- | var _gauges = _gauges || [];
- | (function() {
- | var t = document.createElement('script');
- | t.type = 'text/javascript';
- | t.async = true;
- | t.id = 'gauges-tracker';
- | t.setAttribute('data-site-id', '4ef430c8613f5d6715000004');
- | t.src = '//secure.gaug.es/track.js';
- | var s = document.getElementsByTagName('script')[0];
- | s.parentNode.insertBefore(t, s);
- | })();
- //- End of tracking code
+ div.container
+ block main
+
+ //- Tracking code, please remove if you use this somewhere else!
+ script(src='http://static.getclicky.com/js', type='text/javascript')
+ script(type='text/javascript') try{ clicky.init(66409777); }catch(e){}
+ noscript
+ p
+ img(alt='Clicky', width='1', height='1', src="http://in.getclicky.com/66409777ns.gif')
+ script(type='text/javascript').
+ var _gauges = _gauges || [];
+ (function() {
+ var t = document.createElement('script');
+ t.type = 'text/javascript';
+ t.async = true;
+ t.id = 'gauges-tracker';
+ t.setAttribute('data-site-id', '4ef430c8613f5d6715000004');
+ t.src = '//secure.gaug.es/track.js';
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(t, s);
+ })();
+ //- End of tracking code
@@ -1,7 +1,8 @@
extends layout
-block head
+block header
meta(http-equiv='Refresh', content='0; url=#{redirectURL}')
block content
- h1 Login successful, hooray!
+ div.container
+ h1 #{title}

0 comments on commit 5aceb9c

Please sign in to comment.