@@ -8,6 +8,7 @@ import { randomString } from './PushAdapterUtils';
8
8
9
9
const LOG_PREFIX = 'parse-server-push-adapter FCM' ;
10
10
const FCMRegistrationTokensMax = 500 ;
11
+ const FCMTimeToLiveMax = 4 * 7 * 24 * 60 * 60 ; // FCM allows a max of 4 weeks
11
12
12
13
export default function FCM ( args ) {
13
14
if ( typeof args !== 'object' || ! args . firebaseServiceAccount ) {
@@ -40,7 +41,6 @@ FCM.prototype.send = function(data, devices) {
40
41
return ;
41
42
}
42
43
43
-
44
44
// We can only have 500 recepients per send, so we need to slice devices to
45
45
// chunk if necessary
46
46
const slices = sliceDevices ( devices , FCM . FCMRegistrationTokensMax ) ;
@@ -60,7 +60,7 @@ FCM.prototype.send = function(data, devices) {
60
60
const length = deviceTokens . length ;
61
61
log . info ( LOG_PREFIX , `sending push to ${ length } devices` ) ;
62
62
63
- return this . sender . sendEachForMulticast ( fcmPayload . payload . data )
63
+ return this . sender . sendEachForMulticast ( fcmPayload . data )
64
64
. then ( ( response ) => {
65
65
const promises = [ ] ;
66
66
const failedTokens = [ ] ;
@@ -101,21 +101,59 @@ FCM.prototype.send = function(data, devices) {
101
101
* Generate the fcm payload from the data we get from api request.
102
102
* @param {Object } requestData The request body
103
103
* @param {String } pushId A random string
104
- * @param {Number } timeStamp A number whose format is the Unix Epoch
104
+ * @param {Number } timeStamp A number in milliseconds since the Unix Epoch
105
105
* @returns {Object } A payload for FCM
106
106
*/
107
107
function generateFCMPayload ( requestData , pushId , timeStamp , deviceTokens ) {
108
108
delete requestData [ 'where' ] ;
109
- requestData . tokens = deviceTokens ;
110
- const payload = { }
111
109
112
- payload . payload = {
113
- data : requestData ,
114
- push_id : pushId ,
115
- time : new Date ( timeStamp ) . toISOString ( )
110
+ const payloadToUse = {
111
+ data : { } ,
112
+ push_id : pushId ,
113
+ time : new Date ( timeStamp ) . toISOString ( )
114
+ } ;
115
+
116
+ // Use rawPayload instead of the GCM implementation if it exists
117
+ if ( requestData . hasOwnProperty ( 'rawPayload' ) ) {
118
+ payloadToUse . data = {
119
+ ...requestData . rawPayload ,
120
+ tokens : deviceTokens
121
+ } ;
122
+ } else {
123
+ // Android payload according to GCM implementation
124
+ const androidPayload = {
125
+ android : {
126
+ priority : 'high'
127
+ } ,
128
+ tokens : deviceTokens
129
+ } ;
130
+
131
+ if ( requestData . hasOwnProperty ( 'notification' ) ) {
132
+ androidPayload . notification = requestData . notification ;
133
+ }
134
+
135
+ if ( requestData . hasOwnProperty ( 'data' ) ) {
136
+ androidPayload . data = requestData . data ;
137
+ }
138
+
139
+ if ( requestData [ 'expiration_time' ] ) {
140
+ const expirationTime = requestData [ 'expiration_time' ] ;
141
+ // Convert to seconds
142
+ let timeToLive = Math . floor ( ( expirationTime - timeStamp ) / 1000 ) ;
143
+ if ( timeToLive < 0 ) {
144
+ timeToLive = 0 ;
145
+ }
146
+ if ( timeToLive >= FCMTimeToLiveMax ) {
147
+ timeToLive = FCMTimeToLiveMax ;
148
+ }
149
+
150
+ androidPayload . android . ttl = timeToLive ;
151
+ }
152
+
153
+ payloadToUse . data = androidPayload ;
116
154
}
117
155
118
- return payload ;
156
+ return payloadToUse ;
119
157
}
120
158
121
159
/**
@@ -132,7 +170,6 @@ function sliceDevices(devices, chunkSize) {
132
170
return chunkDevices ;
133
171
}
134
172
135
-
136
173
/**
137
174
* Creates an errorPromise for return.
138
175
*
0 commit comments