Personal intranet/start page where I can view the weather, links, fitbit data, and the news.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.4 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. /** express app */
  2. const express = require("express");
  3. /** Manages oauth 2.0 w/ fitbit */
  4. const passport = require('passport');
  5. /** Used to make API calls */
  6. const unirest = require('unirest');
  7. /** express app */
  8. const app = express();
  9. /** pull config file */
  10. const utils = require("./utils.js");
  11. const config = utils.getFileAsJSON("config.json");
  12. app.use(passport.initialize());
  13. app.use(passport.session({
  14. resave: false,
  15. saveUninitialized: true
  16. }));
  17. var FitbitStrategy = require( 'passport-fitbit-oauth2' ).FitbitOAuth2Strategy;
  18. var accessTokenTemp = null;
  19. passport.use(new FitbitStrategy({
  20. clientID: config.clientID,
  21. clientSecret: config.clientSecret,
  22. callbackURL: config.callbackURL
  23. },
  24. function(accessToken, refreshToken, profile, done)
  25. {
  26. console.log(accessToken);
  27. accessTokenTemp = accessToken;
  28. done(null, {
  29. accessToken: accessToken,
  30. refreshToken: refreshToken,
  31. profile: profile
  32. });
  33. }
  34. ));
  35. passport.serializeUser(function(user, done) {
  36. done(null, user);
  37. });
  38. passport.deserializeUser(function(obj, done) {
  39. done(null, obj);
  40. });
  41. passport.authenticate('fitbit', { scope: ['activity','heartrate','location','profile'] });
  42. app.get('/auth/fitbit',
  43. passport.authenticate('fitbit', { scope: ['activity','heartrate','location','profile'] }
  44. ));
  45. app.get( '/auth/fitbit/callback', passport.authenticate( 'fitbit', {
  46. successRedirect: '/',
  47. failureRedirect: '/error'
  48. }));
  49. app.get('/error', (request, result) =>
  50. {
  51. result.write("Error authenticating with Fitbit API");
  52. result.end();
  53. });
  54. const queryAPI = function(result, path)
  55. {
  56. return new Promise((resolve, reject)=>
  57. {
  58. if(accessTokenTemp == null)
  59. {
  60. result.redirect('/auth/fitbit');
  61. resolve(false);
  62. }
  63. unirest.get(path)
  64. .headers({'Accept': 'application/json', 'Content-Type': 'application/json', Authorization: "Bearer " + accessTokenTemp})
  65. .end(function (response)
  66. {
  67. if(response.hasOwnProperty("success") && response.success == false)
  68. {
  69. result.redirect('/auth/fitbit');
  70. resolve(false);
  71. }
  72. resolve(response.body);
  73. });
  74. });
  75. };
  76. app.get('/steps', (request, result)=>
  77. {
  78. queryAPI(result, 'https://api.fitbit.com/1/user/-/activities/tracker/steps/date/today/1m.json').then((data)=>
  79. {
  80. if(data != false)
  81. {
  82. result.writeHead(200, {'Content-Type': 'text/html'});
  83. result.write(JSON.stringify(data));
  84. result.end();
  85. }
  86. else
  87. {
  88. console.log("Validating with API");
  89. }
  90. });
  91. });
  92. app.get('/activities', (request, result)=>
  93. {
  94. queryAPI(result, 'https://api.fitbit.com/1/user/-/activities/date/1M.json').then((data)=>
  95. {
  96. if(data != false)
  97. {
  98. result.writeHead(200, {'Content-Type': 'text/html'});
  99. result.write(JSON.stringify(data));
  100. result.end();
  101. }
  102. else
  103. {
  104. console.log("Validating with API");
  105. }
  106. });
  107. });
  108. app.get('/', (request, result) =>
  109. {
  110. result.write(utils.getFile("index.html"));
  111. result.end();
  112. });
  113. app.listen(config.port, () =>
  114. console.log(`App listening on port ${config.port}!`)
  115. );
  116. app.use(express.static('public'));