diff --git a/docs/objects/Notification.yaml b/docs/objects/Notification.yaml index 50299ec8be..05c7d93764 100644 --- a/docs/objects/Notification.yaml +++ b/docs/objects/Notification.yaml @@ -22,7 +22,7 @@ components: notificationEventName: type: string description: The name of the event the notification will fire on. - enum: ['onPodcastEpisodeDownloaded', 'onBackupCompleted', 'onBackupFailed', 'onTest'] + enum: ['onItemsAdded', 'onPodcastEpisodeDownloaded', 'onBackupCompleted', 'onBackupFailed', 'onTest'] urls: type: array items: diff --git a/docs/openapi.json b/docs/openapi.json index 48f30ecfb0..bab29e157d 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -3225,6 +3225,7 @@ "type": "string", "description": "The name of the event the notification will fire on.", "enum": [ + "onItemsAdded", "onPodcastEpisodeDownloaded", "onBackupCompleted", "onBackupFailed", diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js index c48e878c2c..c12976af98 100644 --- a/server/managers/NotificationManager.js +++ b/server/managers/NotificationManager.js @@ -14,6 +14,32 @@ class NotificationManager { return notificationData } + async onItemsAdded(LibraryItems) { + if (!Database.notificationSettings.isUseable) return + + if (!Database.notificationSettings.getHasActiveNotificationsForEvent('onItemsAdded')) { + Logger.debug(`[NotificationManager] onItemsAdded: No active notifications`) + return + } + + for (const item of LibraryItems) { + Logger.debug(`[NotificationManager] onItemsAdded: Item "${item.media.metadata.title}"`) + const library = await Database.libraryModel.findByPk(item.libraryId) + const eventData = { + libraryItemId: item.id, + libraryId: item.libraryId, + libraryName: library?.name || 'Unknown', + tags: (item.media.tags || []).join(', ') || 'None', + title: item.media.metadata.title, + authors: (item.media.metadata.authors.map(a => a.name) || []).join(', ') || '', + description: item.media.metadata.description || '', + genres: (item.media.metadata.genres || []).join(', ') || 'None', + publishedYear: item.media.metadata.publishedYear || '', + } + this.triggerNotification('onItemsAdded', eventData) + } + } + async onPodcastEpisodeDownloaded(libraryItem, episode) { if (!Database.notificationSettings.isUseable) return diff --git a/server/scanner/LibraryScanner.js b/server/scanner/LibraryScanner.js index bd0bb310f5..78ec422f27 100644 --- a/server/scanner/LibraryScanner.js +++ b/server/scanner/LibraryScanner.js @@ -14,6 +14,7 @@ const LibraryItemScanner = require('./LibraryItemScanner') const LibraryScan = require('./LibraryScan') const LibraryItemScanData = require('./LibraryItemScanData') const Task = require('../objects/Task') +const NotificationManager = require('../managers/NotificationManager') class LibraryScanner { constructor() { @@ -284,6 +285,7 @@ class LibraryScanner { 'items_added', newOldLibraryItems.map((li) => li.toJSONExpanded()) ) + NotificationManager.onItemsAdded(newOldLibraryItems) newOldLibraryItems = [] } @@ -296,6 +298,7 @@ class LibraryScanner { 'items_added', newOldLibraryItems.map((li) => li.toJSONExpanded()) ) + NotificationManager.onItemsAdded(newOldLibraryItems) } } @@ -647,6 +650,7 @@ class LibraryScanner { if (newLibraryItem) { const oldNewLibraryItem = Database.libraryItemModel.getOldLibraryItem(newLibraryItem) SocketAuthority.emitter('item_added', oldNewLibraryItem.toJSONExpanded()) + NotificationManager.onItemsAdded([oldNewLibraryItem]) } itemGroupingResults[itemDir] = newLibraryItem ? ScanResult.ADDED : ScanResult.NOTHING } diff --git a/server/utils/notifications.js b/server/utils/notifications.js index 96e8ddf8cd..a8e0e58661 100644 --- a/server/utils/notifications.js +++ b/server/utils/notifications.js @@ -2,6 +2,28 @@ const { version } = require('../../package.json') module.exports.notificationData = { events: [ + { + name: 'onItemsAdded', + requiresLibrary: true, + libraryMediaType: 'item', + description: 'Triggered when an item is added to the library', + variables: ['libraryItemId', 'libraryId', 'libraryName', 'tags', 'title', 'authors', 'description', 'genres', 'publishedYear'], + defaults: { + title: 'New Book!', + body: '{{title}} has been added to {{libraryName}} library.' + }, + testData: { + libraryItemId: 'li_notification_test', + libraryId: 'lib_test', + libraryName: 'My Library', + tags: 'TestTag1, TestTag2', + title: 'ABS Test Book', + authors: 'Author1, Author2', + description: 'Description of the Abs Test Book belongs here.', + genres: 'TestGenre1, TestGenre2', + publishedYear: '2020' + } + }, { name: 'onPodcastEpisodeDownloaded', requiresLibrary: true,