audiobookshelf/server/managers/NotificationManager.js

119 lines
4.9 KiB
JavaScript
Raw Normal View History

const axios = require('axios')
2022-09-21 01:08:41 +02:00
const Logger = require("../Logger")
const SocketAuthority = require('../SocketAuthority')
2023-07-05 01:14:44 +02:00
const Database = require('../Database')
2022-09-23 01:12:48 +02:00
const { notificationData } = require('../utils/notifications')
2022-09-21 01:08:41 +02:00
class NotificationManager {
2023-07-05 01:14:44 +02:00
constructor() {
this.sendingNotification = false
this.notificationQueue = []
}
2022-09-23 01:12:48 +02:00
getData() {
return notificationData
}
onPodcastEpisodeDownloaded(libraryItem, episode) {
2023-07-05 01:14:44 +02:00
if (!Database.notificationSettings.isUseable) return
Logger.debug(`[NotificationManager] onPodcastEpisodeDownloaded: Episode "${episode.title}" for podcast ${libraryItem.media.metadata.title}`)
2023-07-05 01:14:44 +02:00
const library = Database.libraries.find(lib => lib.id === libraryItem.libraryId)
const eventData = {
libraryItemId: libraryItem.id,
libraryId: libraryItem.libraryId,
libraryName: library ? library.name : 'Unknown',
mediaTags: (libraryItem.media.tags || []).join(', '),
podcastTitle: libraryItem.media.metadata.title,
podcastAuthor: libraryItem.media.metadata.author || '',
podcastDescription: libraryItem.media.metadata.description || '',
podcastGenres: (libraryItem.media.metadata.genres || []).join(', '),
episodeId: episode.id,
episodeTitle: episode.title,
episodeSubtitle: episode.subtitle || '',
episodeDescription: episode.description || ''
}
this.triggerNotification('onPodcastEpisodeDownloaded', eventData)
}
onTest() {
this.triggerNotification('onTest')
}
async triggerNotification(eventName, eventData, intentionallyFail = false) {
2023-07-05 01:14:44 +02:00
if (!Database.notificationSettings.isUseable) return
// Will queue the notification if sendingNotification and queue is not full
if (!this.checkTriggerNotification(eventName, eventData)) return
2023-07-05 01:14:44 +02:00
const notifications = Database.notificationSettings.getActiveNotificationsForEvent(eventName)
for (const notification of notifications) {
Logger.debug(`[NotificationManager] triggerNotification: Sending ${eventName} notification ${notification.id}`)
const success = intentionallyFail ? false : await this.sendNotification(notification, eventData)
notification.updateNotificationFired(success)
if (!success) { // Failed notification
2023-07-05 01:14:44 +02:00
if (notification.numConsecutiveFailedAttempts >= Database.notificationSettings.maxFailedAttempts) {
Logger.error(`[NotificationManager] triggerNotification: ${notification.eventName}/${notification.id} reached max failed attempts`)
notification.enabled = false
} else {
Logger.error(`[NotificationManager] triggerNotification: ${notification.eventName}/${notification.id} ${notification.numConsecutiveFailedAttempts} failed attempts`)
}
}
}
2023-07-05 01:14:44 +02:00
await Database.updateSetting(Database.notificationSettings)
SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON())
this.notificationFinished()
}
// Return TRUE if notification should be triggered now
checkTriggerNotification(eventName, eventData) {
if (this.sendingNotification) {
2023-07-05 01:14:44 +02:00
if (this.notificationQueue.length >= Database.notificationSettings.maxNotificationQueue) {
Logger.warn(`[NotificationManager] Notification queue is full - ignoring event ${eventName}`)
} else {
Logger.debug(`[NotificationManager] Queueing notification ${eventName} (Queue size: ${this.notificationQueue.length})`)
this.notificationQueue.push({ eventName, eventData })
}
return false
}
this.sendingNotification = true
return true
}
notificationFinished() {
// Delay between events then run next notification in queue
setTimeout(() => {
this.sendingNotification = false
if (this.notificationQueue.length) { // Send next notification in queue
const nextNotificationEvent = this.notificationQueue.shift()
this.triggerNotification(nextNotificationEvent.eventName, nextNotificationEvent.eventData)
}
2023-07-05 01:14:44 +02:00
}, Database.notificationSettings.notificationDelay)
}
sendTestNotification(notification) {
const eventData = notificationData.events.find(e => e.name === notification.eventName)
if (!eventData) {
Logger.error(`[NotificationManager] sendTestNotification: Event not found ${notification.eventName}`)
return false
}
return this.sendNotification(notification, eventData.testData)
}
sendNotification(notification, eventData) {
const payload = notification.getApprisePayload(eventData)
2023-07-05 01:14:44 +02:00
return axios.post(Database.notificationSettings.appriseApiUrl, payload, { timeout: 6000 }).then((response) => {
Logger.debug(`[NotificationManager] sendNotification: ${notification.eventName}/${notification.id} response=`, response.data)
return true
}).catch((error) => {
Logger.error(`[NotificationManager] sendNotification: ${notification.eventName}/${notification.id} error=`, error)
return false
})
2022-09-21 01:08:41 +02:00
}
}
2023-02-15 00:00:34 +01:00
module.exports = NotificationManager