131 lines
3.5 KiB
JavaScript
131 lines
3.5 KiB
JavaScript
class NotificationFacade
|
|
{
|
|
static create = container => new this(container.Logger, container.DateTimeProvider, container.TransportProvider,
|
|
container.SubjectParser, container.NotificationRepository, container.Config);
|
|
|
|
|
|
constructor(logger, dateTimeProvider, transportProvider, subjectParser, notificationRepository, config)
|
|
{
|
|
this.logger = logger;
|
|
this.dateTimeProvider = dateTimeProvider;
|
|
this.transportProvider = transportProvider;
|
|
this.subjectParser = subjectParser;
|
|
this.notificationRepository = notificationRepository;
|
|
|
|
this.contacts = config.contacts.filter(contact =>
|
|
{
|
|
if (transportProvider.byType(contact.type) === null)
|
|
{
|
|
logger.error(`Unknown transport type '${contact.type}' for contact '${contact.description}', skipping contact`)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
this.publicUrl = config.publicUrl;
|
|
this.reminders = config.reminders;
|
|
}
|
|
|
|
|
|
async postNotification(subject, message, priority)
|
|
{
|
|
var parsedSubject = this.subjectParser.parse(subject);
|
|
|
|
const token = await this.notificationRepository.storeNotification(parsedSubject.id, parsedSubject.title);
|
|
if (token === null)
|
|
return;
|
|
|
|
this._sendNotification({
|
|
id: parsedSubject.id,
|
|
token: token,
|
|
title: parsedSubject.title,
|
|
message: message,
|
|
priority: priority,
|
|
sound: parsedSubject.sound,
|
|
timestamp: this.dateTimeProvider.unixTimestamp(),
|
|
url: new URL('/#/n/' + token, this.publicUrl).href
|
|
});
|
|
}
|
|
|
|
|
|
async resetNotification(token)
|
|
{
|
|
await this.notificationRepository.resetNotification(token);
|
|
}
|
|
|
|
|
|
|
|
getLatchedNotifications(token)
|
|
{
|
|
const notifications = this.notificationRepository.getLatchedNotifications(token);
|
|
|
|
return notifications !== null
|
|
? {
|
|
reminders: {
|
|
enabled: this.reminders.enabled,
|
|
interval: this.reminders.interval
|
|
},
|
|
notifications: notifications
|
|
}
|
|
: null;
|
|
}
|
|
|
|
|
|
async setReminders(token, enabled)
|
|
{
|
|
await this.notificationRepository.setReminders(token, enabled);
|
|
}
|
|
|
|
|
|
_sendNotification(notification)
|
|
{
|
|
this.contacts.forEach(contact =>
|
|
{
|
|
const transport = this.transportProvider.byType(contact.type);
|
|
this._retryableSend(transport, contact, notification);
|
|
});
|
|
}
|
|
|
|
|
|
_delay(ms)
|
|
{
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
|
|
async _retryableSend(transport, contact, notification)
|
|
{
|
|
let attempt = 1;
|
|
const retryInterval = contact.retryIntervalSeconds || 0;
|
|
const maxAttempts = contact.maxAttempts || 1;
|
|
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
this.logger.info(`Sending notification '${notification.id}' with token '${notification.token}' to '${contact.description}' (attempt ${attempt})`);
|
|
await transport.send(contact, notification);
|
|
|
|
this.logger.info(`Notification '${notification.id}' succesfully sent to '${contact.description}'`);
|
|
return;
|
|
}
|
|
catch (err)
|
|
{
|
|
if (attempt >= maxAttempts)
|
|
{
|
|
this.logger.info(`Error while sending notification '${notification.id}' to '${contact.description}', max attempts reached: ${err}`);
|
|
return;
|
|
}
|
|
|
|
this.logger.info(`Error while sending notification '${notification.id}' to '${contact.description}', retrying in ${retryInterval} seconds: ${err}`);
|
|
await this._delay(retryInterval * 1000);
|
|
|
|
attempt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
module.exports = NotificationFacade; |