@@ -1,16 +1,24 @@
|
||||
import { Parse } from 'parse/node';
|
||||
import RestQuery from '../RestQuery';
|
||||
import RestWrite from '../RestWrite';
|
||||
import { master } from '../Auth';
|
||||
import { pushStatusHandler } from '../StatusHandler';
|
||||
import { Parse } from 'parse/node';
|
||||
import RestQuery from '../RestQuery';
|
||||
import RestWrite from '../RestWrite';
|
||||
import { master } from '../Auth';
|
||||
import { pushStatusHandler } from '../StatusHandler';
|
||||
import { applyDeviceTokenExists } from '../Push/utils';
|
||||
|
||||
export class PushController {
|
||||
|
||||
sendPush(body = {}, where = {}, config, auth, onPushStatusSaved = () => {}, now = new Date()) {
|
||||
sendPush(
|
||||
body = {},
|
||||
where = {},
|
||||
config,
|
||||
auth,
|
||||
onPushStatusSaved = () => {},
|
||||
now = new Date()
|
||||
) {
|
||||
if (!config.hasPushSupport) {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
'Missing push configuration');
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
'Missing push configuration'
|
||||
);
|
||||
}
|
||||
|
||||
// Replace the expiration_time and push_time with a valid Unix epoch milliseconds time
|
||||
@@ -19,13 +27,14 @@ export class PushController {
|
||||
if (body.expiration_time && body.expiration_interval) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
'Both expiration_time and expiration_interval cannot be set');
|
||||
'Both expiration_time and expiration_interval cannot be set'
|
||||
);
|
||||
}
|
||||
|
||||
// Immediate push
|
||||
if (body.expiration_interval && !body.hasOwnProperty('push_time')) {
|
||||
const ttlMs = body.expiration_interval * 1000;
|
||||
body.expiration_time = (new Date(now.valueOf() + ttlMs)).valueOf();
|
||||
body.expiration_time = new Date(now.valueOf() + ttlMs).valueOf();
|
||||
}
|
||||
|
||||
const pushTime = PushController.getPushTime(body);
|
||||
@@ -37,18 +46,22 @@ export class PushController {
|
||||
// pushes to be sent. We probably change this behaviour in the future.
|
||||
let badgeUpdate = () => {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
if (body.data && body.data.badge) {
|
||||
const badge = body.data.badge;
|
||||
let restUpdate = {};
|
||||
if (typeof badge == 'string' && badge.toLowerCase() === 'increment') {
|
||||
restUpdate = { badge: { __op: 'Increment', amount: 1 } }
|
||||
} else if (typeof badge == 'object' && typeof badge.__op == 'string' &&
|
||||
badge.__op.toLowerCase() == 'increment' && Number(badge.amount)) {
|
||||
restUpdate = { badge: { __op: 'Increment', amount: badge.amount } }
|
||||
restUpdate = { badge: { __op: 'Increment', amount: 1 } };
|
||||
} else if (
|
||||
typeof badge == 'object' &&
|
||||
typeof badge.__op == 'string' &&
|
||||
badge.__op.toLowerCase() == 'increment' &&
|
||||
Number(badge.amount)
|
||||
) {
|
||||
restUpdate = { badge: { __op: 'Increment', amount: badge.amount } };
|
||||
} else if (Number(badge)) {
|
||||
restUpdate = { badge: badge }
|
||||
restUpdate = { badge: badge };
|
||||
} else {
|
||||
throw "Invalid value for badge, expected number or 'Increment' or {increment: number}";
|
||||
}
|
||||
@@ -57,44 +70,75 @@ export class PushController {
|
||||
const updateWhere = applyDeviceTokenExists(where);
|
||||
badgeUpdate = () => {
|
||||
// Build a real RestQuery so we can use it in RestWrite
|
||||
const restQuery = new RestQuery(config, master(config), '_Installation', updateWhere);
|
||||
const restQuery = new RestQuery(
|
||||
config,
|
||||
master(config),
|
||||
'_Installation',
|
||||
updateWhere
|
||||
);
|
||||
return restQuery.buildRestWhere().then(() => {
|
||||
const write = new RestWrite(config, master(config), '_Installation', restQuery.restWhere, restUpdate);
|
||||
const write = new RestWrite(
|
||||
config,
|
||||
master(config),
|
||||
'_Installation',
|
||||
restQuery.restWhere,
|
||||
restUpdate
|
||||
);
|
||||
write.runOptions.many = true;
|
||||
return write.execute();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
const pushStatus = pushStatusHandler(config);
|
||||
return Promise.resolve().then(() => {
|
||||
return pushStatus.setInitial(body, where);
|
||||
}).then(() => {
|
||||
onPushStatusSaved(pushStatus.objectId);
|
||||
return badgeUpdate();
|
||||
}).then(() => {
|
||||
// Update audience lastUsed and timesUsed
|
||||
if (body.audience_id) {
|
||||
const audienceId = body.audience_id;
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
return pushStatus.setInitial(body, where);
|
||||
})
|
||||
.then(() => {
|
||||
onPushStatusSaved(pushStatus.objectId);
|
||||
return badgeUpdate();
|
||||
})
|
||||
.then(() => {
|
||||
// Update audience lastUsed and timesUsed
|
||||
if (body.audience_id) {
|
||||
const audienceId = body.audience_id;
|
||||
|
||||
var updateAudience = {
|
||||
lastUsed: { __type: "Date", iso: new Date().toISOString() },
|
||||
timesUsed: { __op: "Increment", "amount": 1 }
|
||||
};
|
||||
const write = new RestWrite(config, master(config), '_Audience', {objectId: audienceId}, updateAudience);
|
||||
write.execute();
|
||||
}
|
||||
// Don't wait for the audience update promise to resolve.
|
||||
return Promise.resolve();
|
||||
}).then(() => {
|
||||
if (body.hasOwnProperty('push_time') && config.hasPushScheduledSupport) {
|
||||
var updateAudience = {
|
||||
lastUsed: { __type: 'Date', iso: new Date().toISOString() },
|
||||
timesUsed: { __op: 'Increment', amount: 1 },
|
||||
};
|
||||
const write = new RestWrite(
|
||||
config,
|
||||
master(config),
|
||||
'_Audience',
|
||||
{ objectId: audienceId },
|
||||
updateAudience
|
||||
);
|
||||
write.execute();
|
||||
}
|
||||
// Don't wait for the audience update promise to resolve.
|
||||
return Promise.resolve();
|
||||
}
|
||||
return config.pushControllerQueue.enqueue(body, where, config, auth, pushStatus);
|
||||
}).catch((err) => {
|
||||
return pushStatus.fail(err).then(() => {
|
||||
throw err;
|
||||
})
|
||||
.then(() => {
|
||||
if (
|
||||
body.hasOwnProperty('push_time') &&
|
||||
config.hasPushScheduledSupport
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return config.pushControllerQueue.enqueue(
|
||||
body,
|
||||
where,
|
||||
config,
|
||||
auth,
|
||||
pushStatus
|
||||
);
|
||||
})
|
||||
.catch(err => {
|
||||
return pushStatus.fail(err).then(() => {
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,13 +158,17 @@ export class PushController {
|
||||
} else if (typeof expirationTimeParam === 'string') {
|
||||
expirationTime = new Date(expirationTimeParam);
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['expiration_time'] + ' is not valid time.');
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['expiration_time'] + ' is not valid time.'
|
||||
);
|
||||
}
|
||||
// Check expirationTime is valid or not, if it is not valid, expirationTime is NaN
|
||||
if (!isFinite(expirationTime)) {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['expiration_time'] + ' is not valid time.');
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['expiration_time'] + ' is not valid time.'
|
||||
);
|
||||
}
|
||||
return expirationTime.valueOf();
|
||||
}
|
||||
@@ -132,9 +180,14 @@ export class PushController {
|
||||
}
|
||||
|
||||
var expirationIntervalParam = body['expiration_interval'];
|
||||
if (typeof expirationIntervalParam !== 'number' || expirationIntervalParam <= 0) {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
`expiration_interval must be a number greater than 0`);
|
||||
if (
|
||||
typeof expirationIntervalParam !== 'number' ||
|
||||
expirationIntervalParam <= 0
|
||||
) {
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
`expiration_interval must be a number greater than 0`
|
||||
);
|
||||
}
|
||||
return expirationIntervalParam;
|
||||
}
|
||||
@@ -159,13 +212,17 @@ export class PushController {
|
||||
isLocalTime = !PushController.pushTimeHasTimezoneComponent(pushTimeParam);
|
||||
date = new Date(pushTimeParam);
|
||||
} else {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['push_time'] + ' is not valid time.');
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['push_time'] + ' is not valid time.'
|
||||
);
|
||||
}
|
||||
// Check pushTime is valid or not, if it is not valid, pushTime is NaN
|
||||
if (!isFinite(date)) {
|
||||
throw new Parse.Error(Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['push_time'] + ' is not valid time.');
|
||||
throw new Parse.Error(
|
||||
Parse.Error.PUSH_MISCONFIGURED,
|
||||
body['push_time'] + ' is not valid time.'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -181,8 +238,10 @@ export class PushController {
|
||||
*/
|
||||
static pushTimeHasTimezoneComponent(pushTimeParam: string): boolean {
|
||||
const offsetPattern = /(.+)([+-])\d\d:\d\d$/;
|
||||
return pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 // 2007-04-05T12:30Z
|
||||
|| offsetPattern.test(pushTimeParam); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00
|
||||
return (
|
||||
pushTimeParam.indexOf('Z') === pushTimeParam.length - 1 || // 2007-04-05T12:30Z
|
||||
offsetPattern.test(pushTimeParam)
|
||||
); // 2007-04-05T12:30.000+02:00, 2007-04-05T12:30.000-02:00
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,8 +250,15 @@ export class PushController {
|
||||
* @param isLocalTime {boolean}
|
||||
* @returns {string}
|
||||
*/
|
||||
static formatPushTime({ date, isLocalTime }: { date: Date, isLocalTime: boolean }) {
|
||||
if (isLocalTime) { // Strip 'Z'
|
||||
static formatPushTime({
|
||||
date,
|
||||
isLocalTime,
|
||||
}: {
|
||||
date: Date,
|
||||
isLocalTime: boolean,
|
||||
}) {
|
||||
if (isLocalTime) {
|
||||
// Strip 'Z'
|
||||
const isoString = date.toISOString();
|
||||
return isoString.substring(0, isoString.indexOf('Z'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user