diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..7f53f52 --- /dev/null +++ b/config/config.json @@ -0,0 +1,21 @@ +{ + "fitbit": { + "timeout": 10000, + "creds": { + "clientID": "227QC6", + "clientSecret": "aad7cf451c8851762310e54f63d97604" + }, + "uris": { + "authorizationUri": "https://www.fitbit.com", + "authorizationPath": "/oauth2/authorize", + "tokenUri": "https://api.fitbit.com", + "tokenPath": "/oauth2/token" + }, + "authorization_uri": { + "redirect_uri": "http://localhost:9000/fitbit_auth_callback/", + "response_type": "code", + "scope": "activity nutrition profile settings sleep social weight heartrate", + "state": "3(#0/!~" + } + } +} diff --git a/lib/jade/today.jade b/lib/jade/today.jade index a407986..7f0281b 100644 --- a/lib/jade/today.jade +++ b/lib/jade/today.jade @@ -35,6 +35,9 @@ html(lang="en") h2 Calendar each line in data.cal.entries p !{line.combined} + .fitbit + h2 Fitbit + p Yesterday you walked #{data.fitbit.summary.steps} steps and moved #{data.fitbit.summary.distances[0].distance} km. .swedish h2 Word of the day p(style="font-weight:900;")= data.swedish.xml.words.word @@ -55,5 +58,4 @@ html(lang="en") each line in data.tv.entries p !{line.combined} - - \ No newline at end of file + diff --git a/lib/rr_bot.js b/lib/rr_bot.js new file mode 100644 index 0000000..4271f3e --- /dev/null +++ b/lib/rr_bot.js @@ -0,0 +1,187 @@ +/* + Index pages: + https://teamrock.com/radio/show/the-school-of-rock + https://teamrock.com/radio/show/the-metal-hammer-magazine-show# + https://teamrock.com/radio/show/the-classic-rock-magazine-show + */ + +var request = require('request'); +var cheerio = require('cheerio'); +var STRING = require('string'); +var logger = require('log4js').getLogger(); +var Events = require('events'); +var jsonfile = require('jsonfile'); +var fs = require('fs'); +var cron = require('node-cron'); + +//var root = 'http://teamrock.com'; + +var root = 'http://localhost:9000'; +var wantedType = ['audio/mpeg']; + +var eventHandler = new Events(); + +var rssJsonFile = __dirname + '/' + 'rr-rss.json'; + +module.exports = { + rssJsonFile : __dirname + '/' + 'rr-rss.json', + rssJson:{}, + getPage: function(indexfile) { + logger.debug('getPage'); + var url = root + indexfile; + logger.debug(url); + logger.info(indexfile); + + return new Promise(function(resolve, reject) { + 'use strict'; +var rssBlob = {}; + + request(url, function(err, resp, body) { + if (err) { + // Logger.error(err); + return reject(err); + // Throw err; + } + + var $ = cheerio.load(body); + var audioblock = $('AUDIO'); + + audioblock.find('SOURCE').each(function(div) { + + var s = $(this).attr('type'); + + if (wantedType.indexOf(s) !== -1) { + var f = $(this).attr('src'); + var suffix = f.substr(f.lastIndexOf('.') + 1, f.length); + + if (suffix === 'mp3') { + rssBlob.file = f; + } + } + + }); + + var sectionHead = $('H2.section-title').text(); + + logger.debug(sectionHead); + + return resolve(rssBlob); + }, function(error, response, body) { + if (response.statusCode !== 200) { + logger.error(response.statusCode); + logger.error(body); + return reject(error); + } + }); + }); + + }, getIndexPage: function() { + + var url, self = this; + + url = 'http://localhost:9000/the-school-of-rock'; + + return new Promise(function(resolve, reject) { + 'use strict'; + + request(url, function(err, resp, body) { + if (err) { + // Logger.error(err); + return reject(err); + // Throw err; + } + + var $ = cheerio.load(body); + var playlistBody = $('div.my-playlist'); + + var queue = []; + + playlistBody.find('a.my-playlist-item').each(function(div) { + + var s = $(this).attr('href'); + if (self.rssJson.masterindex.indexOf(s) === -1) { + queue.push(s); + } + + }); + + return resolve(queue); + }, function(error, response, body) { + if (response.statusCode !== 200) { + logger.error(response.statusCode); + logger.error(body); + return reject(error); + } + }); + }); + + }, + doUpdateEntry: function(d) { + logger.debug('Updatefile:', d); +}, +doUpdateQueue: function(queue) { + 'use strict'; + logger.info('Update queue'); + logger.debug(queue); + for(var t=0;t { + module.exports.doUpdateQueue(q); +}; + +var doUpdateEntry = (q) => { + module.exports.getPage(q); +}; + +eventHandler.on('updateQueue', doUpdateQueue); +eventHandler.on('updateEntry', doUpdateEntry); + +module.exports.loadMainIndex(); + + + + + +setTimeout(function() { + module.exports.getIndexPage() + .then((d)=> { + logger.warn(d); + eventHandler.emit('updateQueue', d); + }) + .catch((e) => { + logger.error(e); + }); + +}, 5000); diff --git a/lib/today.js b/lib/today.js index 8a41ef7..1954742 100644 --- a/lib/today.js +++ b/lib/today.js @@ -1,10 +1,9 @@ /** * Created by marti on 30/01/2016. */ -var http = require('http'), request = require('request'), cheerio = require('cheerio'), util = require('util'), UltraSES = require( - 'ultrases'), cron = require('node-cron'); -var jade = require('jade'), _ = require('lodash'), dateFormat = require('dateformat'); -var jsonfile = require('jsonfile'), fs = require('fs'), STRING = require('string'); +var http = require('http'), request = require('request'), cheerio = require('cheerio'), util = require('util'), cron = require('node-cron'); +var dateFormat = require('dateformat'); +var jsonfile = require('jsonfile'), fs = require('fs'); var nano = require('nano')('http://localhost:5984'); var log4js = require('log4js'); var logger = log4js.getLogger(); @@ -13,22 +12,15 @@ var swedishWord = require('./today/swedishword'); var weather = require('./today/weather'); var trains = require('./today/trains'); var history = require('./today/history'); +var mdMailer = require('./today/mailer'); +var mdFitbit = require('./today/fitbit'); var db_name = 'silvrgit'; var dbCouch = nano.use(db_name); var todayCache = { last: 0, data: { - trains: {last: 0, data: []}, weather: {}, history: [], today: '', tv: {entries: []}, cal: {entries: []}, swedish: {} + trains: {last: 0, data: []}, weather: {}, history: [], today: '', tv: {entries: []}, cal: {entries: []}, swedish: {}, fitbit:{} }, expire: ((60 * 1000) * 60) }; -var mailer = new UltraSES({ - aws: { - accessKeyId: 'AKIAJWJS75F7WNCGK64A', - secretAccessKey: '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', - region: 'eu-west-1' - }, defaults: { - from: 'Martin Donnelly ' - } -}); var file = __dirname + '/' + 'newdata.json'; var htmlfile = __dirname + '/' + 'today.html'; function saveData() { @@ -46,10 +38,12 @@ function saveToDB(data) { } }); } + function nth(d) { if (d > 3 && d < 21) {return 'th';} // Thanks kennebec if (d % 10 === 1) {return 'st';} else if (d % 10 === 2) {return 'nd';} else if (d % 10 === 3) {return 'rd';} else {return 'th';} } + function dayNumber() { var now = new Date(); var start = new Date(now.getFullYear(), 0, 0); @@ -57,10 +51,12 @@ function dayNumber() { var oneDay = 1000 * 60 * 60 * 24; return Math.floor(diff / oneDay); } + function breakDay() { var now = new Date(); return {year: now.getFullYear(), month: parseInt(now.getMonth()) + 1, day: now.getDate()} } + /** * @return {number} */ @@ -72,6 +68,7 @@ function DayDiff(CurrentDate) { DayCount = Math.round(DayCount); return (DayCount); } + Array.prototype.indexOfOld = Array.prototype.indexOf; Array.prototype.indexOf = function(e, fn) { if (!fn) { @@ -86,6 +83,7 @@ Array.prototype.indexOf = function(e, fn) { return this.map(fn).indexOfOld(e); } }; + module.exports = { getClock: function(req, res) { // Console.log(todayCache); @@ -124,7 +122,6 @@ module.exports = { }); }, preLoadToday: function() { module.exports.getTodayDate(); - var self = this; todayCache.data.cal.entries = []; weather.newDoGetWeather() .then((d)=> { @@ -203,48 +200,25 @@ module.exports = { 'use strict'; console.error(e); }); + + mdFitbit.getYesterdayFitbit() + .then((d) => { + todayCache.data.fitbit = d; + }) + .catch((e)=> { + 'use strict'; + console.error(e); + }); + todayCache.date = breakDay(); - // word of the day http://wotd.transparent.com/rss/swedish-widget.xml?t=1455840000000 - // time stamp } }; -function sendEmailV1() { - var now = new Date(); - var email = { - to: 'martind2000@gmail.com', subject: 'Today - ' + dateFormat(now, 'dddd, mmmm dS, yyyy') - }; - var template = { - file: __dirname + '/' + 'jade/today.jade', locals: todayCache - }; - logger.debug(__dirname); - logger.debug(__dirname.substr(__dirname.lastIndexOf('/'), __dirname.length)); - // If (__dirname.substr(__dirname.lastIndexOf('/'),__dirname.length)) - mailer.sendTemplate(email, template, function(err) { - if (err) throw err; - logger.info('compiled template email sent'); - }); - // SaveData(); - var fn = jade.compileFile(template.file); - // Console.log(fn(todayCache)); - // Fs.writeFileSync(htmlfile, fn(todayCache)); -} -function sendEmail() { - logger.log('Simple email'); - var now = new Date(); - var email = { - to: 'martind2000@gmail.com', subject: 'Today - ' + dateFormat(now, 'dddd, mmmm dS, yyyy') - }; - /* Mailer.sendText(email, 'Look at this fantastic email body!', function (err) { - if (err) throw err; - console.log('email sent!'); - }); - */ - saveData(); -} + setTimeout(function() { module.exports.preLoadToday(); }, 5000); setTimeout(function() { +// mdMailer.sendEmailV1(todayCache, __dirname); saveToDB(todayCache); }, 45000); cron.schedule('45 6 * * *', function() { @@ -256,7 +230,7 @@ cron.schedule('0 */1 * * *', function() { return -1; }); cron.schedule('0 7 * * *', function() { - sendEmailV1(); + mdMailer.sendEmailV1(); saveToDB(todayCache); // Console.log('tick'); return -1; diff --git a/lib/today/fitbit.js b/lib/today/fitbit.js new file mode 100644 index 0000000..ef91be0 --- /dev/null +++ b/lib/today/fitbit.js @@ -0,0 +1,59 @@ +var jsonfile = require('jsonfile'); +var config = require('../../config/config.json'); +var Fitbit = require('fitbit-oauth2'); +var dateFormat = require('dateformat'); + +var logger = require('log4js').getLogger(); + +require('sugar-date'); + +var fitbit = new Fitbit(config.fitbit); +var tokenFile = '../fb-token.json'; + +module.exports = { + + getYesterdayFitbit: function() { + return new Promise(function(resolve, reject) { + var yesterday = Date.create('yesterday').format('{yyyy}-{MM}-{dd}'); + var url = 'https://api.fitbit.com/1/user/-/activities/date/' + yesterday +'.json'; + +logger.info('Getting fitbit for: ', yesterday); + logger.debug(url); + fitbit.request({ + uri: url, + method: 'GET' + }, function( err, body, token ) { + if ( err ) { + return reject(err); + } + var profile = JSON.parse( body ); + // if token is not null, a refesh has happened and we need to persist the new token + if ( token ) + jsonfile.writeFile(tokenFile, token, function( err ) { + if ( err ) { + return reject(err); + } + return resolve(profile); + }); + else + { + return resolve(profile); + } + }); + + }); + } +}; + +jsonfile.readFile(tokenFile, function(err, obj) { + if (err) { + logger.error(err); + + } + else { + logger.info('Fitbit token loaded...'); + fitbit.setToken(obj); + + } +}); + diff --git a/lib/today/mailer.js b/lib/today/mailer.js new file mode 100644 index 0000000..873d848 --- /dev/null +++ b/lib/today/mailer.js @@ -0,0 +1,37 @@ +/** + * + * User: Martin Donnelly + * Date: 2016-04-08 + * Time: 16:35 + * + */ +var jade = require('jade'), UltraSES = require('ultrases'), dateFormat = require('dateformat'); + +var logger = require('log4js').getLogger(); + +var mailer = new UltraSES({ + aws: { + accessKeyId: 'AKIAJWJS75F7WNCGK64A', + secretAccessKey: '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', + region: 'eu-west-1' + }, defaults: { + from: 'Martin Donnelly ' + } +}); + +module.exports = { + + sendEmailV1: function(todayCache, newpath) { + var now = new Date(); + var email = { + to: 'martind2000@gmail.com', subject: 'Today - ' + dateFormat(now, 'dddd, mmmm dS, yyyy') + }; + var template = { + file: newpath + '/' + 'jade/today.jade', locals: todayCache + }; + mailer.sendTemplate(email, template, function(err) { + if (err) throw err; + logger.info('compiled template email sent'); + }); + } +}; diff --git a/package.json b/package.json index baf7d7b..a0bb468 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "cheerio": "^0.20.0", "dateformat": "^1.0.12", "ejs": "^2.3.4", + "fitbit-oauth2": "0.0.1", "forecast.io": "0.0.9", "htmlparser": "^1.7.7", "jade": "^1.11.0", @@ -15,6 +16,7 @@ "nano": "^6.2.0", "request": "^2.67.0", "simple-weather": "^1.2.2", + "sugar-date": "^1.5.1", "wordsoap": "^0.2.0", "xmljson": "^0.2.0", "xmltojson": "^1.1.0" @@ -31,6 +33,7 @@ "logger": "0.0.1", "method-override": "^2.3.5", "morgan": "^1.7.0", + "nano": "^6.2.0", "node-cron": "^1.0.0", "scrape": "^0.2.3", "string": "^3.3.1", diff --git a/single.js b/single.js index 9ea2c14..2b1a031 100644 --- a/single.js +++ b/single.js @@ -1,41 +1,39 @@ -var express = require('express'), path = require('path'), http = require('http') - ; +var express = require('express'), path = require('path'), http = require('http'), morgan = require( + 'morgan'), cookieParser = require('cookie-parser'), session = require( + 'express-session'), methodoverride = require('method-override'), bodyparser = require( + 'body-parser'), errorhandler = require('errorhandler'); + +var logger = require('log4js').getLogger(); var app = express(); GLOBAL.lastcheck = 0; -var btcCache = {}, fxCache = {} , trainCache = {}; -app.configure(function () { - app.set('port', process.env.PORT || 4545); - app.set('view engine', 'ejs'); - app.use(express.logger('dev')); - app.use(express.cookieParser()); - app.use(express.session({secret: '1234567890QWERTY'})); - /* 'default', 'short', 'tiny', 'dev' */ - app.use(express.methodOverride()); +//app.configure(function () { +app.set('port', process.env.PORT || 9000); +app.set('view engine', 'ejs'); +app.use(morgan('dev')); +app.use(cookieParser('your secret here')); +app.use(session({ + secret: '1234567890QWERTY', resave: false, saveUninitialized: false +})); +/* 'default', 'short', 'tiny', 'dev' */ +app.use(methodoverride()); - app.use(express.bodyParser()); +app.use(bodyparser.urlencoded({extended: false})); - app.use(function (req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "X-Requested-With"); - next(); - }); - app.use(app.router); - app.use(express.static(path.join(__dirname, 'app'))); - app.use(express.errorHandler({dumpExceptions: true, showStack: true})); +// parse application/json +app.use(bodyparser.json()); - app.get('/temp', function (req, res) { - res.render('pages/temp'); - }); - - app.get('/weight', function (req, res) { - res.render('pages/weight'); - }); +app.use(function(req, res, next) { + res.header("Access-Control-Allow-Origin", "*"); + res.header("Access-Control-Allow-Headers", "X-Requested-With"); + next(); }); +// app.use(app.router); +app.use(express.static(path.join(__dirname, 'app'))); -/** - * create the server - */ -http.createServer(app).listen(app.get('port'), function () { - console.log("Express server listening on port " + app.get('port')); +app.use(errorhandler({dumpExceptions: true, showStack: true})); + +http.createServer(app).listen(app.get('port'), function() { + logger.warn("Simple Express server listening on port " + app.get('port')); + //console.log("Express server listening on port " + app.get('port')); }); diff --git a/web-server.js b/web-server.js index 6f54f9c..012d550 100644 --- a/web-server.js +++ b/web-server.js @@ -5,11 +5,16 @@ var express = require('express'), path = require('path'), http = require('http') morgan = require('morgan'), cookieParser = require('cookie-parser'),session = require('express-session') methodoverride = require('method-override'), bodyparser = require('body-parser'), errorhandler = require('errorhandler'); +var jsonfile = require('jsonfile'); //train = require('lib/train') /* ,submit = require('./routes/mongo/submit') */ ; +var fs = require('fs'); +var config = require('./config/config.json'); +var Fitbit = require('fitbit-oauth2'); + var polys = require('./lib/poly.js'); var logger = require('log4js').getLogger(); @@ -104,6 +109,66 @@ app.route('/poly').get(polys); res.render('pages/temp'); }); + + +var tfile = 'fb-token.json'; +var persist = { + read: function( filename, cb ) { + fs.readFile( filename, { encoding: 'utf8', flag: 'r' }, function( err, data ) { + if ( err ) return cb( err ); + try { + var token = JSON.parse( data ); + cb( null, token ); + } catch( err ) { + cb( err ); + } + }); + }, + write: function( filename, token, cb ) { + console.log( 'persisting new token:', JSON.stringify( token ) ); + fs.writeFile( filename, JSON.stringify( token ), cb ); + } +}; + +// Instanciate a fitbit client. See example config below. +// +var fitbit = new Fitbit( config.fitbit ); + +// In a browser, http://localhost:4000/fitbit to authorize a user for the first time. +// +app.get('/fitbit', function (req, res) { + res.redirect( fitbit.authorizeURL() ); +}); + +// Callback service parsing the authorization token and asking for the access token. This +// endpoint is refered to in config.fitbit.authorization_uri.redirect_uri. See example +// config below. +// +app.get('/fitbit_auth_callback', function (req, res, next) { + var code = req.query.code; + fitbit.fetchToken( code, function( err, token ) { + if ( err ) return next( err ); + + // persist the token + jsonfile.writeFile( tfile, token, function( err ) { + if ( err ) return next( err ); + res.redirect( '/fb-profile' ); + }); + }); +}); + +jsonfile.readFile('./fb-token.json', function(err, obj) { + if (err) { + logger.error(err) + + } + else { + fitbit.setToken(obj); + + } + }); + + //}); /**