210 lines
5.4 KiB
JavaScript
210 lines
5.4 KiB
JavaScript
"use strict";
|
|
// ParsePushAdapter is the default implementation of
|
|
// PushAdapter, it uses GCM for android push and APNS
|
|
// for ios push.
|
|
|
|
import { utils } from 'parse-server-push-adapter';
|
|
import ParsePushAdapter from 'parse-server-push-adapter';
|
|
|
|
const Parse = require('parse/node').Parse;
|
|
var deepcopy = require('deepcopy');
|
|
import PushAdapter from './PushAdapter';
|
|
|
|
export class OneSignalPushAdapter extends PushAdapter {
|
|
|
|
constructor(pushConfig = {}) {
|
|
super(pushConfig);
|
|
this.https = require('https');
|
|
|
|
this.validPushTypes = ['ios', 'android'];
|
|
this.senderMap = {};
|
|
this.OneSignalConfig = {};
|
|
const { oneSignalAppId, oneSignalApiKey } = pushConfig;
|
|
if (!oneSignalAppId || !oneSignalApiKey) {
|
|
throw "Trying to initialize OneSignalPushAdapter without oneSignalAppId or oneSignalApiKey";
|
|
}
|
|
this.OneSignalConfig['appId'] = pushConfig['oneSignalAppId'];
|
|
this.OneSignalConfig['apiKey'] = pushConfig['oneSignalApiKey'];
|
|
|
|
this.senderMap['ios'] = this.sendToAPNS.bind(this);
|
|
this.senderMap['android'] = this.sendToGCM.bind(this);
|
|
}
|
|
|
|
send(data, installations) {
|
|
let deviceMap = utils.classifyInstallations(installations, this.validPushTypes);
|
|
|
|
let sendPromises = [];
|
|
for (let pushType in deviceMap) {
|
|
let sender = this.senderMap[pushType];
|
|
if (!sender) {
|
|
console.log('Can not find sender for push type %s, %j', pushType, data);
|
|
continue;
|
|
}
|
|
let devices = deviceMap[pushType];
|
|
|
|
if(devices.length > 0) {
|
|
sendPromises.push(sender(data, devices));
|
|
}
|
|
}
|
|
return Parse.Promise.when(sendPromises);
|
|
}
|
|
|
|
static classifyInstallations(installations, validTypes) {
|
|
return utils.classifyInstallations(installations, validTypes)
|
|
}
|
|
|
|
getValidPushTypes() {
|
|
return this.validPushTypes;
|
|
}
|
|
|
|
sendToAPNS(data,tokens) {
|
|
|
|
data= deepcopy(data['data']);
|
|
|
|
var post = {};
|
|
if(data['badge']) {
|
|
if(data['badge'] == "Increment") {
|
|
post['ios_badgeType'] = 'Increase';
|
|
post['ios_badgeCount'] = 1;
|
|
} else {
|
|
post['ios_badgeType'] = 'SetTo';
|
|
post['ios_badgeCount'] = data['badge'];
|
|
}
|
|
delete data['badge'];
|
|
}
|
|
if(data['alert']) {
|
|
post['contents'] = {en: data['alert']};
|
|
delete data['alert'];
|
|
}
|
|
if(data['sound']) {
|
|
post['ios_sound'] = data['sound'];
|
|
delete data['sound'];
|
|
}
|
|
if(data['content-available'] == 1) {
|
|
post['content_available'] = true;
|
|
delete data['content-available'];
|
|
}
|
|
post['data'] = data;
|
|
|
|
let promise = new Parse.Promise();
|
|
|
|
var chunk = 2000 // OneSignal can process 2000 devices at a time
|
|
var tokenlength=tokens.length;
|
|
var offset = 0
|
|
// handle onesignal response. Start next batch if there's not an error.
|
|
let handleResponse = function(wasSuccessful) {
|
|
if (!wasSuccessful) {
|
|
return promise.reject("OneSignal Error");
|
|
}
|
|
|
|
if(offset >= tokenlength) {
|
|
promise.resolve()
|
|
} else {
|
|
this.sendNext();
|
|
}
|
|
}.bind(this)
|
|
|
|
this.sendNext = function() {
|
|
post['include_ios_tokens'] = [];
|
|
tokens.slice(offset,offset+chunk).forEach(function(i) {
|
|
post['include_ios_tokens'].push(i['deviceToken'])
|
|
})
|
|
offset+=chunk;
|
|
this.sendToOneSignal(post, handleResponse);
|
|
}.bind(this)
|
|
|
|
this.sendNext()
|
|
|
|
return promise;
|
|
}
|
|
|
|
sendToGCM(data,tokens) {
|
|
data= deepcopy(data['data']);
|
|
|
|
var post = {};
|
|
|
|
if(data['alert']) {
|
|
post['contents'] = {en: data['alert']};
|
|
delete data['alert'];
|
|
}
|
|
if(data['title']) {
|
|
post['title'] = {en: data['title']};
|
|
delete data['title'];
|
|
}
|
|
if(data['uri']) {
|
|
post['url'] = data['uri'];
|
|
}
|
|
|
|
post['data'] = data;
|
|
|
|
let promise = new Parse.Promise();
|
|
|
|
var chunk = 2000 // OneSignal can process 2000 devices at a time
|
|
var tokenlength=tokens.length;
|
|
var offset = 0
|
|
// handle onesignal response. Start next batch if there's not an error.
|
|
let handleResponse = function(wasSuccessful) {
|
|
if (!wasSuccessful) {
|
|
return promise.reject("OneSIgnal Error");
|
|
}
|
|
|
|
if(offset >= tokenlength) {
|
|
promise.resolve()
|
|
} else {
|
|
this.sendNext();
|
|
}
|
|
}.bind(this);
|
|
|
|
this.sendNext = function() {
|
|
post['include_android_reg_ids'] = [];
|
|
tokens.slice(offset,offset+chunk).forEach(function(i) {
|
|
post['include_android_reg_ids'].push(i['deviceToken'])
|
|
})
|
|
offset+=chunk;
|
|
this.sendToOneSignal(post, handleResponse);
|
|
}.bind(this)
|
|
|
|
|
|
this.sendNext();
|
|
return promise;
|
|
}
|
|
|
|
sendToOneSignal(data, cb) {
|
|
let headers = {
|
|
"Content-Type": "application/json",
|
|
"Authorization": "Basic "+this.OneSignalConfig['apiKey']
|
|
};
|
|
let options = {
|
|
host: "onesignal.com",
|
|
port: 443,
|
|
path: "/api/v1/notifications",
|
|
method: "POST",
|
|
headers: headers
|
|
};
|
|
data['app_id'] = this.OneSignalConfig['appId'];
|
|
|
|
let request = this.https.request(options, function(res) {
|
|
if(res.statusCode < 299) {
|
|
cb(true);
|
|
} else {
|
|
console.log('OneSignal Error');
|
|
res.on('data', function(chunk) {
|
|
console.log(chunk.toString())
|
|
});
|
|
cb(false)
|
|
}
|
|
});
|
|
request.on('error', function(e) {
|
|
console.log("Error connecting to OneSignal")
|
|
console.log(e);
|
|
cb(false);
|
|
});
|
|
request.write(JSON.stringify(data))
|
|
request.end();
|
|
}
|
|
}
|
|
|
|
|
|
export default OneSignalPushAdapter;
|
|
module.exports = OneSignalPushAdapter;
|