1 |
|
2 | var inherits = require('util').inherits;
|
3 | var EventEmitter = require('events').EventEmitter;
|
4 |
|
5 | var debug = require('debug')('loopback:component:push:provider:apns');
|
6 | var apn = require('apn');
|
7 |
|
8 | function ApnsProvider(pushSettings) {
|
9 | pushSettings = pushSettings || {};
|
10 | var settings = pushSettings.apns || {};
|
11 | var pushOptions = settings.pushOptions || {};
|
12 | var feedbackOptions = settings.feedbackOptions || {};
|
13 |
|
14 |
|
15 | if(settings.certData) {
|
16 | pushOptions.certData = pushOptions.certData || settings.certData;
|
17 | feedbackOptions.certData = feedbackOptions.certData || settings.certData;
|
18 | }
|
19 | if(settings.keyData) {
|
20 | pushOptions.keyData = pushOptions.keyData || settings.keyData;
|
21 | feedbackOptions.keyData = feedbackOptions.keyData || settings.keyData;
|
22 | }
|
23 |
|
24 |
|
25 | if(settings.production) {
|
26 |
|
27 | pushOptions.gateway = 'gateway.push.apple.com';
|
28 | feedbackOptions.gateway = 'feedback.push.apple.com';
|
29 | if(pushOptions.port !== undefined) {
|
30 | pushOptions.port = 2195;
|
31 | }
|
32 | if(feedbackOptions.port !== undefined) {
|
33 | feedbackOptions.port = 2196;
|
34 | }
|
35 |
|
36 | } else {
|
37 |
|
38 | pushOptions.gateway = pushOptions.gateway || 'gateway.sandbox.push.apple.com';
|
39 | feedbackOptions.gateway = feedbackOptions.gateway || 'feedback.sandbox.push.apple.com';
|
40 | }
|
41 |
|
42 |
|
43 | this._pushOptions = pushOptions;
|
44 | this._feedbackOptions = feedbackOptions;
|
45 |
|
46 | this._setupPushConnection(pushOptions);
|
47 | this._setupFeedback(feedbackOptions);
|
48 | }
|
49 |
|
50 | inherits(ApnsProvider, EventEmitter);
|
51 |
|
52 | exports = module.exports = ApnsProvider;
|
53 |
|
54 | ApnsProvider.prototype._setupPushConnection = function(options) {
|
55 | var self = this;
|
56 | if(options && !options.port){
|
57 | delete options.port;
|
58 | }
|
59 | var connection = new apn.Connection(options);
|
60 |
|
61 | function errorHandler(err) {
|
62 | debug('Cannot initialize APNS connection. %s', err.stack);
|
63 | self.emit('error', err);
|
64 | }
|
65 |
|
66 | connection.on('error', errorHandler);
|
67 | connection.on('socketError', errorHandler);
|
68 |
|
69 | connection.on('transmissionError', function(code, notification, recipient) {
|
70 | var err = new Error('Cannot send APNS notification: ' + code);
|
71 | self.emit(err, notification, recipient);
|
72 | });
|
73 |
|
74 | this._connection = connection;
|
75 | };
|
76 |
|
77 | ApnsProvider.prototype._setupFeedback = function(options) {
|
78 | if (!options) {
|
79 | debug('Feedback channel is not enabled in the application settings.');
|
80 | return;
|
81 | }
|
82 |
|
83 | var self = this;
|
84 | this._feedback = new apn.Feedback(options);
|
85 | this._feedback.on('feedback', function (devices) {
|
86 | debug('Devices gone:', devices);
|
87 | self.emit('devicesGone', devices);
|
88 | });
|
89 | };
|
90 |
|
91 | ApnsProvider.prototype.pushNotification = function(notification, deviceToken) {
|
92 |
|
93 |
|
94 | var note = new apn.Notification();
|
95 | note.expiry = notification.getTimeToLiveInSecondsFromNow() || note.expiry;
|
96 | note.badge = notification.badge;
|
97 | note.sound = notification.sound;
|
98 | note.alert = notification.alert;
|
99 | note.category = notification.category;
|
100 | note.payload = {};
|
101 |
|
102 | Object.keys(notification).forEach(function (key) {
|
103 | note.payload[key] = notification[key];
|
104 | });
|
105 |
|
106 | debug('Pushing notification to %j:', deviceToken, note);
|
107 | this._connection.pushNotification(note, deviceToken);
|
108 | };
|