2018-06-25 22:17:49 +00:00
|
|
|
/* global _: false */
|
|
|
|
/* global Backbone: false */
|
|
|
|
/* global i18n: false */
|
|
|
|
/* global moment: false */
|
|
|
|
/* global Whisper: false */
|
|
|
|
|
|
|
|
// eslint-disable-next-line func-names
|
2018-04-27 21:25:04 +00:00
|
|
|
(function() {
|
|
|
|
'use strict';
|
2018-06-25 22:17:49 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
window.Whisper = window.Whisper || {};
|
2017-02-21 23:32:40 +00:00
|
|
|
|
2018-07-25 22:02:27 +00:00
|
|
|
async function destroyExpiredMessages() {
|
2018-08-03 04:12:27 +00:00
|
|
|
try {
|
2018-08-07 19:33:56 +00:00
|
|
|
window.log.info('destroyExpiredMessages: Loading messages...');
|
2018-08-03 04:12:27 +00:00
|
|
|
const messages = await window.Signal.Data.getExpiredMessages({
|
|
|
|
MessageCollection: Whisper.MessageCollection,
|
|
|
|
});
|
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
messages.map(async message => {
|
|
|
|
window.log.info('Message expired', {
|
|
|
|
sentAt: message.get('sent_at'),
|
|
|
|
});
|
|
|
|
|
|
|
|
// We delete after the trigger to allow the conversation time to process
|
|
|
|
// the expiration before the message is removed from the database.
|
|
|
|
await window.Signal.Data.removeMessage(message.id, {
|
|
|
|
Message: Whisper.Message,
|
|
|
|
});
|
|
|
|
|
|
|
|
const conversation = message.getConversation();
|
|
|
|
if (conversation) {
|
|
|
|
conversation.trigger('expired', message);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
} catch (error) {
|
|
|
|
window.log.error(
|
|
|
|
'destroyExpiredMessages: Error deleting expired messages',
|
|
|
|
error && error.stack ? error.stack : error
|
|
|
|
);
|
|
|
|
}
|
2018-07-25 22:02:27 +00:00
|
|
|
|
2018-08-07 19:33:56 +00:00
|
|
|
window.log.info('destroyExpiredMessages: complete');
|
2018-07-25 22:02:27 +00:00
|
|
|
checkExpiringMessages();
|
2018-04-27 21:25:04 +00:00
|
|
|
}
|
2017-02-21 23:32:40 +00:00
|
|
|
|
2018-06-25 22:17:49 +00:00
|
|
|
let timeout;
|
2018-07-25 22:02:27 +00:00
|
|
|
async function checkExpiringMessages() {
|
2018-04-27 21:25:04 +00:00
|
|
|
// Look up the next expiring message and set a timer to destroy it
|
2018-07-25 22:02:27 +00:00
|
|
|
const messages = await window.Signal.Data.getNextExpiringMessage({
|
|
|
|
MessageCollection: Whisper.MessageCollection,
|
|
|
|
});
|
2017-02-21 23:32:40 +00:00
|
|
|
|
2018-07-25 22:02:27 +00:00
|
|
|
const next = messages.at(0);
|
|
|
|
if (!next) {
|
|
|
|
return;
|
|
|
|
}
|
2017-08-10 18:16:20 +00:00
|
|
|
|
2018-07-25 22:02:27 +00:00
|
|
|
const expiresAt = next.get('expires_at');
|
2018-08-03 04:12:27 +00:00
|
|
|
Whisper.ExpiringMessagesListener.nextExpiration = expiresAt;
|
2018-07-25 22:02:27 +00:00
|
|
|
window.log.info('next message expires', new Date(expiresAt).toISOString());
|
2017-02-21 23:32:40 +00:00
|
|
|
|
2018-07-25 22:02:27 +00:00
|
|
|
let wait = expiresAt - Date.now();
|
2017-08-10 18:16:20 +00:00
|
|
|
|
2018-07-25 22:02:27 +00:00
|
|
|
// In the past
|
|
|
|
if (wait < 0) {
|
|
|
|
wait = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Too far in the future, since it's limited to a 32-bit value
|
|
|
|
if (wait > 2147483647) {
|
|
|
|
wait = 2147483647;
|
|
|
|
}
|
|
|
|
|
|
|
|
clearTimeout(timeout);
|
|
|
|
timeout = setTimeout(destroyExpiredMessages, wait);
|
2018-04-27 21:25:04 +00:00
|
|
|
}
|
2018-06-25 22:17:49 +00:00
|
|
|
const throttledCheckExpiringMessages = _.throttle(
|
|
|
|
checkExpiringMessages,
|
|
|
|
1000
|
|
|
|
);
|
2017-02-21 23:32:40 +00:00
|
|
|
|
2018-04-27 21:25:04 +00:00
|
|
|
Whisper.ExpiringMessagesListener = {
|
2018-08-03 04:12:27 +00:00
|
|
|
nextExpiration: null,
|
2018-06-25 22:17:49 +00:00
|
|
|
init(events) {
|
2018-04-27 21:25:04 +00:00
|
|
|
checkExpiringMessages();
|
|
|
|
events.on('timetravel', throttledCheckExpiringMessages);
|
|
|
|
},
|
|
|
|
update: throttledCheckExpiringMessages,
|
|
|
|
};
|
2016-09-28 23:47:57 +00:00
|
|
|
|
2018-06-25 22:17:49 +00:00
|
|
|
const TimerOption = Backbone.Model.extend({
|
|
|
|
getName() {
|
2018-04-27 21:25:04 +00:00
|
|
|
return (
|
|
|
|
i18n(['timerOption', this.get('time'), this.get('unit')].join('_')) ||
|
|
|
|
moment.duration(this.get('time'), this.get('unit')).humanize()
|
|
|
|
);
|
|
|
|
},
|
2018-06-25 22:17:49 +00:00
|
|
|
getAbbreviated() {
|
2018-04-27 21:25:04 +00:00
|
|
|
return i18n(
|
|
|
|
['timerOption', this.get('time'), this.get('unit'), 'abbreviated'].join(
|
|
|
|
'_'
|
|
|
|
)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({
|
|
|
|
model: TimerOption,
|
2018-06-25 22:17:49 +00:00
|
|
|
getName(seconds = 0) {
|
|
|
|
const o = this.findWhere({ seconds });
|
2018-04-27 21:25:04 +00:00
|
|
|
if (o) {
|
|
|
|
return o.getName();
|
|
|
|
}
|
2018-06-25 22:17:49 +00:00
|
|
|
return [seconds, 'seconds'].join(' ');
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
2018-06-25 22:17:49 +00:00
|
|
|
getAbbreviated(seconds = 0) {
|
|
|
|
const o = this.findWhere({ seconds });
|
2018-04-27 21:25:04 +00:00
|
|
|
if (o) {
|
|
|
|
return o.getAbbreviated();
|
|
|
|
}
|
2018-06-25 22:17:49 +00:00
|
|
|
return [seconds, 's'].join('');
|
2018-04-27 21:25:04 +00:00
|
|
|
},
|
|
|
|
}))(
|
|
|
|
[
|
|
|
|
[0, 'seconds'],
|
|
|
|
[5, 'seconds'],
|
|
|
|
[10, 'seconds'],
|
|
|
|
[30, 'seconds'],
|
|
|
|
[1, 'minute'],
|
|
|
|
[5, 'minutes'],
|
|
|
|
[30, 'minutes'],
|
|
|
|
[1, 'hour'],
|
|
|
|
[6, 'hours'],
|
|
|
|
[12, 'hours'],
|
|
|
|
[1, 'day'],
|
|
|
|
[1, 'week'],
|
2018-06-25 22:17:49 +00:00
|
|
|
].map(o => {
|
|
|
|
const duration = moment.duration(o[0], o[1]); // 5, 'seconds'
|
2016-09-28 23:47:57 +00:00
|
|
|
return {
|
|
|
|
time: o[0],
|
|
|
|
unit: o[1],
|
2018-04-27 21:25:04 +00:00
|
|
|
seconds: duration.asSeconds(),
|
2016-09-28 23:47:57 +00:00
|
|
|
};
|
2018-04-27 21:25:04 +00:00
|
|
|
})
|
|
|
|
);
|
2016-09-21 00:19:51 +00:00
|
|
|
})();
|