{"action":"created","comment":{"url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/comments/88814571","pull_request_review_id":9375606,"id":88814571,"diff_hunk":"@@ -0,0 +1,108 @@\n+var nconf = require('nconf');\n+var pushNotify = require('push-notify');\n+var Bluebird = require('bluebird');\n+var gcmLib = require('node-gcm'); // works with FCM notifications too\n+var AWS = require('aws-sdk');\n+\n+const FCM_API_KEY = nconf.get('PUSH_CONFIGS:FCM_SERVER_API_KEY');\n+\n+const fcmSender = FCM_API_KEY ? new gcmLib.Sender(FCM_API_KEY) : undefined;\n+\n+let apn;\n+\n+// Load APN certificate and key from S3\n+const APN_ENABLED = nconf.get('PUSH_CONFIGS:APN_ENABLED') === 'true';\n+\n+\n+if (APN_ENABLED) {\n+  if(nconf.get('NODE_ENV') === 'production') {\n+    const S3_BUCKET = nconf.get('S3:bucket');\n+    const S3 = new AWS.S3({\n+      accessKeyId: nconf.get('S3:accessKeyId'),\n+      secretAccessKey: nconf.get('S3:secretAccessKey'),\n+    });\n+    Bluebird.all([\n+      S3.getObject({\n+        Bucket: S3_BUCKET,\n+        Key: 'apple_apn/cert.pem',\n+      }).promise(),\n+      S3.getObject({\n+        Bucket: S3_BUCKET,\n+        Key: 'apple_apn/key.pem',\n+      }).promise(),\n+    ])\n+      .then(([certObj, keyObj]) => {\n+        let cert = certObj.Body.toString();\n+        let key = keyObj.Body.toString();\n+        configureApn(cert, key);\n+      });\n+  } else {\n+    configureApn('../cert.pem', '../key.pem');\n+  }\n+}\n+\n+function configureApn(cert, key) {\n+  apn = pushNotify.apn({\n+    key,\n+    cert,\n+  });\n+\n+  apn.on('error', err => logger.error('APN error', err));\n+  apn.on('transmissionError', (errorCode, notification, device) => {\n+    logger.error('APN transmissionError', errorCode, notification, device);\n+  });\n+}\n+\n+function sendNotifications(users, details = {}) {","path":"libs/pushNotifications.js","position":56,"original_position":56,"commit_id":"65975ee25c0665929551e863d58165dcae5fdd0f","original_commit_id":"65975ee25c0665929551e863d58165dcae5fdd0f","user":{"login":"paglias","id":589911,"avatar_url":"https://avatars.githubusercontent.com/u/589911?v=3","gravatar_id":"","url":"https://api.github.com/users/paglias","html_url":"https://github.com/paglias","followers_url":"https://api.github.com/users/paglias/followers","following_url":"https://api.github.com/users/paglias/following{/other_user}","gists_url":"https://api.github.com/users/paglias/gists{/gist_id}","starred_url":"https://api.github.com/users/paglias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paglias/subscriptions","organizations_url":"https://api.github.com/users/paglias/orgs","repos_url":"https://api.github.com/users/paglias/repos","events_url":"https://api.github.com/users/paglias/events{/privacy}","received_events_url":"https://api.github.com/users/paglias/received_events","type":"User","site_admin":false},"body":"You're using a lot of ES6 features, but this codebase is plain node 4 and I'm not sure everything is supported (arrow functions, default parameters, let/const without \"use strict\"...","created_at":"2016-11-20T23:08:05Z","updated_at":"2016-11-20T23:08:10Z","html_url":"https://github.com/HabitRPG/habitrpg-email-server/pull/8#discussion_r88814571","pull_request_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8","_links":{"self":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/comments/88814571"},"html":{"href":"https://github.com/HabitRPG/habitrpg-email-server/pull/8#discussion_r88814571"},"pull_request":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8"}}},"pull_request":{"url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8","id":94528196,"html_url":"https://github.com/HabitRPG/habitrpg-email-server/pull/8","diff_url":"https://github.com/HabitRPG/habitrpg-email-server/pull/8.diff","patch_url":"https://github.com/HabitRPG/habitrpg-email-server/pull/8.patch","issue_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/8","number":8,"state":"open","locked":false,"title":"Add Push notifications","user":{"login":"vIiRuS","id":298062,"avatar_url":"https://avatars.githubusercontent.com/u/298062?v=3","gravatar_id":"","url":"https://api.github.com/users/vIiRuS","html_url":"https://github.com/vIiRuS","followers_url":"https://api.github.com/users/vIiRuS/followers","following_url":"https://api.github.com/users/vIiRuS/following{/other_user}","gists_url":"https://api.github.com/users/vIiRuS/gists{/gist_id}","starred_url":"https://api.github.com/users/vIiRuS/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vIiRuS/subscriptions","organizations_url":"https://api.github.com/users/vIiRuS/orgs","repos_url":"https://api.github.com/users/vIiRuS/repos","events_url":"https://api.github.com/users/vIiRuS/events{/privacy}","received_events_url":"https://api.github.com/users/vIiRuS/received_events","type":"User","site_admin":false},"body":"This is still a WIP version, that is there for feedback.\r\n\r\nWhat's still missing:\r\n\r\n- For some reason the worker errors, when the push notifications are sent. Unfortunately there is no error message\r\n- user objects are not updated yet to indicate which message they received.","created_at":"2016-11-20T19:02:55Z","updated_at":"2016-11-20T23:08:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2e95f87656312638582e47730af958ada72368a4","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8/commits","review_comments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8/comments","review_comment_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/comments{/number}","comments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/8/comments","statuses_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/statuses/65975ee25c0665929551e863d58165dcae5fdd0f","head":{"label":"HabitRPG:pushNotifications","ref":"pushNotifications","sha":"65975ee25c0665929551e863d58165dcae5fdd0f","user":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"repo":{"id":32275396,"name":"habitrpg-email-server","full_name":"HabitRPG/habitrpg-email-server","owner":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/HabitRPG/habitrpg-email-server","description":"The server from which all HabitRPG's emails are sent","fork":false,"url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server","forks_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/forks","keys_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/teams","hooks_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/hooks","issue_events_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/events{/number}","events_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/events","assignees_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/assignees{/user}","branches_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/branches{/branch}","tags_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/tags","blobs_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/statuses/{sha}","languages_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/languages","stargazers_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/stargazers","contributors_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/contributors","subscribers_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/subscribers","subscription_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/subscription","commits_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/contents/{+path}","compare_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/merges","archive_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/downloads","issues_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues{/number}","pulls_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls{/number}","milestones_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/milestones{/number}","notifications_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/labels{/name}","releases_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/releases{/id}","deployments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/deployments","created_at":"2015-03-15T17:59:00Z","updated_at":"2016-11-08T20:54:51Z","pushed_at":"2016-11-20T19:02:55Z","git_url":"git://github.com/HabitRPG/habitrpg-email-server.git","ssh_url":"git@github.com:HabitRPG/habitrpg-email-server.git","clone_url":"https://github.com/HabitRPG/habitrpg-email-server.git","svn_url":"https://github.com/HabitRPG/habitrpg-email-server","homepage":null,"size":144,"stargazers_count":3,"watchers_count":3,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":3,"default_branch":"master"}},"base":{"label":"HabitRPG:master","ref":"master","sha":"4b3a3f8089eb37f97fa7a12f6c2a883640792ed8","user":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"repo":{"id":32275396,"name":"habitrpg-email-server","full_name":"HabitRPG/habitrpg-email-server","owner":{"login":"HabitRPG","id":3834775,"avatar_url":"https://avatars.githubusercontent.com/u/3834775?v=3","gravatar_id":"","url":"https://api.github.com/users/HabitRPG","html_url":"https://github.com/HabitRPG","followers_url":"https://api.github.com/users/HabitRPG/followers","following_url":"https://api.github.com/users/HabitRPG/following{/other_user}","gists_url":"https://api.github.com/users/HabitRPG/gists{/gist_id}","starred_url":"https://api.github.com/users/HabitRPG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HabitRPG/subscriptions","organizations_url":"https://api.github.com/users/HabitRPG/orgs","repos_url":"https://api.github.com/users/HabitRPG/repos","events_url":"https://api.github.com/users/HabitRPG/events{/privacy}","received_events_url":"https://api.github.com/users/HabitRPG/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/HabitRPG/habitrpg-email-server","description":"The server from which all HabitRPG's emails are sent","fork":false,"url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server","forks_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/forks","keys_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/teams","hooks_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/hooks","issue_events_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/events{/number}","events_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/events","assignees_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/assignees{/user}","branches_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/branches{/branch}","tags_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/tags","blobs_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/statuses/{sha}","languages_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/languages","stargazers_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/stargazers","contributors_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/contributors","subscribers_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/subscribers","subscription_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/subscription","commits_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/contents/{+path}","compare_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/merges","archive_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/downloads","issues_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues{/number}","pulls_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls{/number}","milestones_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/milestones{/number}","notifications_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/labels{/name}","releases_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/releases{/id}","deployments_url":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/deployments","created_at":"2015-03-15T17:59:00Z","updated_at":"2016-11-08T20:54:51Z","pushed_at":"2016-11-20T19:02:55Z","git_url":"git://github.com/HabitRPG/habitrpg-email-server.git","ssh_url":"git@github.com:HabitRPG/habitrpg-email-server.git","clone_url":"https://github.com/HabitRPG/habitrpg-email-server.git","svn_url":"https://github.com/HabitRPG/habitrpg-email-server","homepage":null,"size":144,"stargazers_count":3,"watchers_count":3,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":3,"forks":5,"open_issues":3,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8"},"html":{"href":"https://github.com/HabitRPG/habitrpg-email-server/pull/8"},"issue":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/8"},"comments":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/HabitRPG/habitrpg-email-server/statuses/65975ee25c0665929551e863d58165dcae5fdd0f"}}}}
{"actor":{"display_login":"paglias"}}