Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump from upstream #214

Closed
wants to merge 11 commits into from
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ tmp
test/logs
coverage
.sonar
lib
release.sh
.nyc_output
74 changes: 74 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use strict";

module.exports = {
DEFAULT_TTL: 28 * 86400,
GCM_MAX_TTL: 2419200,
// 4 weeks in seconds (https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json)
APN_METHOD: 'apn',
GCM_METHOD: 'gcm',
ADM_METHOD: 'adm',
WNS_METHOD: 'wns',
WEB_METHOD: 'webPush',
UNKNOWN_METHOD: 'unknown',
DEFAULT_SETTINGS: {
gcm: {
id: null // PUT YOUR GCM SERVER API KEY,
},
apn: {
// See options at https://github.com/node-apn/node-apn/blob/master/doc/provider.markdown
token: null,
// {
// key: '',
// keyId: '',
// teamId: '',
// },
cert: 'cert.pem',
key: 'key.pem',
ca: null,
pfx: null,
passphrase: null,
production: process.env.NODE_ENV === 'production',
voip: false,
address: null,
port: 443,
rejectUnauthorized: true,
connectionRetryLimit: 10,
cacheLength: 1000,
connectionTimeout: 3600000,
autoAdjustCache: true,
maxConnections: 1,
minConnections: 1,
connectTimeout: 10000,
buffersNotifications: true,
fastMode: false,
disableNagle: false,
disableEPIPEFix: false
},
adm: {
client_id: null,
// PUT YOUR ADM CLIENT ID,
client_secret: null // PUT YOUR ADM CLIENT SECRET,
},
wns: {
client_id: null,
// PUT YOUR WNS CLIENT ID,
client_secret: null,
// PUT YOUR WNS CLIENT SECRET,
accessToken: null,
headers: null,
notificationMethod: 'sendTileSquareBlock'
},
web: {
vapidDetails: {
subject: "< 'mailto' Address or URL >",
publicKey: '< URL Safe Base64 Encoded Public Key >',
privateKey: '< URL Safe Base64 Encoded Private Key >'
}
// gcmAPIKey: '< GCM API Key >',
// TTL: 2419200
// headers: { }
// contentEncoding: '< Encoding type, e.g.: aesgcm or aes128gcm >'
},
isAlwaysUseFCM: false
}
};
3 changes: 3 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"use strict";

module.exports = require('./push-notifications');
184 changes: 184 additions & 0 deletions lib/push-notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
"use strict";

var _sendGCM = _interopRequireDefault(require("./sendGCM"));
var _sendAPN = _interopRequireDefault(require("./sendAPN"));
var _sendADM = _interopRequireDefault(require("./sendADM"));
var _sendWNS = _interopRequireDefault(require("./sendWNS"));
var _sendWeb = _interopRequireDefault(require("./sendWeb"));
var _constants = require("./constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* eslint-disable import/no-import-module-exports */
class PN {
constructor(options) {
this.setOptions(options);
}
setOptions(opts) {
this.settings = _objectSpread(_objectSpread({}, _constants.DEFAULT_SETTINGS), opts);
if (this.apn) {
this.apn.shutdown();
}
this.apn = new _sendAPN.default(this.settings.apn);
}
sendWith(method, regIds, data, cb) {
return method(regIds, data, this.settings).then(results => {
(cb || (noop => noop))(null, results);
return results;
}).catch(error => {
(cb || (noop => noop))(error);
return Promise.reject(error);
});
}
getPushMethodByRegId(regId) {
if (typeof regId === 'object' && (!regId.type || !regId.id)) {
return {
regId,
pushMethod: _constants.WEB_METHOD
};
}
if (typeof regId === 'object' && regId.id && regId.type) {
return {
regId: regId.id,
pushMethod: this.settings.isAlwaysUseFCM ? _constants.GCM_METHOD : regId.type
};
}

// TODO: deprecated, remove of all cases below in v3.0
// and review test cases
if (this.settings.isAlwaysUseFCM) {
return {
regId,
pushMethod: _constants.GCM_METHOD
};
}
if (regId.substring(0, 4) === 'http') {
return {
regId,
pushMethod: _constants.WNS_METHOD
};
}
if (/^(amzn[0-9]*.adm)/i.test(regId)) {
return {
regId,
pushMethod: _constants.ADM_METHOD
};
}
if ((regId.length === 64 || regId.length === 160) && /^[a-fA-F0-9]+$/.test(regId)) {
return {
regId,
pushMethod: _constants.APN_METHOD
};
}
if (regId.length > 64) {
return {
regId,
pushMethod: _constants.GCM_METHOD
};
}
return {
regId,
pushMethod: _constants.UNKNOWN_METHOD
};
}
send(_regIds, data, callback) {
const promises = [];
const regIdsGCM = [];
const regIdsAPN = [];
const regIdsWNS = [];
const regIdsADM = [];
const regIdsWebPush = [];
const regIdsUnk = [];
const regIds = Array.isArray(_regIds || []) ? _regIds || [] : [_regIds];

// Classify each pushId for corresponding device
regIds.forEach(regIdOriginal => {
const _this$getPushMethodBy = this.getPushMethodByRegId(regIdOriginal),
regId = _this$getPushMethodBy.regId,
pushMethod = _this$getPushMethodBy.pushMethod;
if (pushMethod === _constants.WEB_METHOD) {
regIdsWebPush.push(regId);
} else if (pushMethod === _constants.GCM_METHOD) {
regIdsGCM.push(regId);
} else if (pushMethod === _constants.WNS_METHOD) {
regIdsWNS.push(regId);
} else if (pushMethod === _constants.ADM_METHOD) {
regIdsADM.push(regId);
} else if (pushMethod === _constants.APN_METHOD) {
regIdsAPN.push(regId);
} else {
regIdsUnk.push(regId);
}
});
try {
// Android GCM
if (regIdsGCM.length > 0) {
promises.push(this.sendWith(_sendGCM.default, regIdsGCM, data));
}

// iOS APN
if (regIdsAPN.length > 0) {
promises.push(this.sendWith(this.apn.sendAPN.bind(this.apn), regIdsAPN, data));
}

// Microsoft WNS
if (regIdsWNS.length > 0) {
promises.push(this.sendWith(_sendWNS.default, regIdsWNS, data));
}

// Amazon ADM
if (regIdsADM.length > 0) {
promises.push(this.sendWith(_sendADM.default, regIdsADM, data));
}

// Web Push
if (regIdsWebPush.length > 0) {
promises.push(this.sendWith(_sendWeb.default, regIdsWebPush, data));
}
} catch (err) {
promises.push(Promise.reject(err));
}

// Unknown
if (regIdsUnk.length > 0) {
const results = {
method: 'unknown',
success: 0,
failure: regIdsUnk.length,
message: []
};
regIdsUnk.forEach(regId => {
results.message.push({
regId,
error: new Error('Unknown registration id')
});
});
promises.push(Promise.resolve(results));
}

// No regIds detected
if (promises.length === 0) {
promises.push(Promise.resolve({
method: 'none',
success: 0,
failure: 0,
message: []
}));
}
return Promise.all(promises).then(results => {
const cb = callback || (noop => noop);
cb(null, results);
return results;
}).catch(err => {
const cb = callback || (noop => noop);
cb(err);
return Promise.reject(err);
});
}
}
module.exports = PN;
module.exports.WEB = _constants.WEB_METHOD;
module.exports.WNS = _constants.WNS_METHOD;
module.exports.ADM = _constants.ADM_METHOD;
module.exports.GCM = _constants.GCM_METHOD;
module.exports.APN = _constants.APN_METHOD;
50 changes: 50 additions & 0 deletions lib/sendADM.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use strict";

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const adm = require('node-adm');
const _require = require('./constants'),
ADM_METHOD = _require.ADM_METHOD;
const sendADM = (regIds, _data, settings) => {
const resumed = {
method: ADM_METHOD,
success: 0,
failure: 0,
message: []
};
const promises = [];
const admSender = new adm.Sender(settings.adm);
const data = _objectSpread({}, _data);
const consolidationKey = data.consolidationKey,
expiry = data.expiry,
timeToLive = data.timeToLive,
custom = data.custom;
delete data.consolidationKey;
delete data.expiry;
delete data.timeToLive;
delete data.custom;
const message = {
expiresAfter: expiry - Math.floor(Date.now() / 1000) || timeToLive || 28 * 86400,
consolidationKey,
data: _objectSpread(_objectSpread({}, data), custom)
};
regIds.forEach(regId => {
promises.push(new Promise(resolve => {
admSender.send(message, regId, (err, response) => {
const errorMsg = err instanceof Error ? err.message : response.error;
const error = err || (response.error ? new Error(response.error) : null);
resumed.success += error ? 0 : 1;
resumed.failure += error ? 1 : 0;
resumed.message.push({
regId,
error,
errorMsg
});
resolve();
});
}));
});
return Promise.all(promises).then(() => resumed);
};
module.exports = sendADM;
Loading
Loading