From 04ba9491826fbc2e23b332adb797b7b5ebd3c32f Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Thu, 15 May 2025 20:51:57 +0200 Subject: [PATCH 1/6] first draft --- server/SocketAuthority.js | 20 +++++++ server/managers/NotificationManager.js | 31 ++++++++++- server/utils/notifications.js | 73 ++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index 050e7e2f..f2d634b2 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -2,6 +2,7 @@ const SocketIO = require('socket.io') const Logger = require('./Logger') const Database = require('./Database') const Auth = require('./Auth') +const NotificationManager = require('./managers/NotificationManager') /** * @typedef SocketClient @@ -15,11 +16,25 @@ class SocketAuthority { constructor() { this.Server = null this.socketIoServers = [] + this.emittedNotifications = new Set(['item_created', 'item_updated']); /** @type {Object.} */ this.clients = {} } + /** + * Fires a notification if enabled and the event is whitelisted + * @param {string} event - The event name fired. Needs to be whitelisted in this.emitted_notifications + * @param {any} payload - The payload to send with the event. For user-specific events, this includes the userId + */ + _fireNotification(event, payload) { + // Should be O(1) so no real performance hit + if (!this.emittedNotifications.has(event)) return + Logger.debug(`[SocketAuthority] fireNotification - ${event}`) + + NotificationManager.fireNotificationFromSocket(event, payload) + } + /** * returns an array of User.toJSONForPublic with `connections` for the # of socket connections * a user can have many socket connections @@ -53,6 +68,7 @@ class SocketAuthority { * @param {Function} [filter] optional filter function to only send event to specific users */ emitter(evt, data, filter = null) { + void this._fireNotification(evt, data) for (const socketId in this.clients) { if (this.clients[socketId].user) { if (filter && !filter(this.clients[socketId].user)) continue @@ -64,6 +80,7 @@ class SocketAuthority { // Emits event to all clients for a specific user clientEmitter(userId, evt, data) { + void this._fireNotification(evt, data) const clients = this.getClientsForUser(userId) if (!clients.length) { return Logger.debug(`[SocketAuthority] clientEmitter - no clients found for user ${userId}`) @@ -77,6 +94,7 @@ class SocketAuthority { // Emits event to all admin user clients adminEmitter(evt, data) { + void this._fireNotification(evt, data); for (const socketId in this.clients) { if (this.clients[socketId].user?.isAdminOrUp) { this.clients[socketId].socket.emit(evt, data) @@ -92,6 +110,7 @@ class SocketAuthority { * @param {import('./models/LibraryItem')} libraryItem */ libraryItemEmitter(evt, libraryItem) { + void this._fireNotification(evt, libraryItem) for (const socketId in this.clients) { if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) { this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded()) @@ -107,6 +126,7 @@ class SocketAuthority { * @param {import('./models/LibraryItem')[]} libraryItems */ libraryItemsEmitter(evt, libraryItems) { + void this._fireNotification(evt, libraryItems) for (const socketId in this.clients) { if (this.clients[socketId].user) { const libraryItemsAccessibleToUser = libraryItems.filter((li) => this.clients[socketId].user.checkCanAccessLibraryItem(li)) diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js index 8edcf428..fec77c4a 100644 --- a/server/managers/NotificationManager.js +++ b/server/managers/NotificationManager.js @@ -90,6 +90,14 @@ class NotificationManager { this.triggerNotification('onBackupFailed', eventData) } + /** + * @param + */ + async onItemUpdated(libraryItem) { + console.log('onItemUpdated', libraryItem) + this.triggerNotification('onItemUpdated', libraryItem) + } + onTest() { this.triggerNotification('onTest') } @@ -124,7 +132,7 @@ class NotificationManager { } await Database.updateSetting(Database.notificationSettings) - SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON()) + //SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON()) this.notificationFinished() } @@ -184,5 +192,26 @@ class NotificationManager { return false }) } + + fireNotificationFromSocket(eventName, eventData) { + if (!Database.notificationSettings.isUseable) return + + const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); + const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}`; + + if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) { + // No logging to prevent console spam + Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`) + return + } + + Logger.debug(`[NotificationManager] fireNotificationFromSocket: ${eventKey} event fired`) + + switch (eventKey) { + case 'onItemUpdated': + void this.onItemUpdated(eventData) + break + } + } } module.exports = new NotificationManager() diff --git a/server/utils/notifications.js b/server/utils/notifications.js index 7a3e1198..8295a503 100644 --- a/server/utils/notifications.js +++ b/server/utils/notifications.js @@ -1,4 +1,61 @@ const { version } = require('../../package.json') +const LibraryItem = require('../models/LibraryItem') + +const libraryItemVariables = [ + 'id', + 'ino', + 'path', + 'relPath', + 'mediaId', + 'mediaType', + 'isFile', + 'isMissing', + 'isInvalid', + 'mtime', + 'ctime', + 'birthtime', + 'size', + 'lastScan', + 'lastScanVersion', + 'libraryFiles', + 'extraData', + 'title', + 'titleIgnorePrefix', + 'authorNamesFirstLast', + 'authorNamesLastFirst', + 'createdAt', + 'updatedAt', + 'libraryId', + 'libraryFolderId', +] + +const libraryItemTestData = { + id: '123e4567-e89b-12d3-a456-426614174000', + ino: '9876543', + path: '/audiobooks/Frank Herbert/Dune', + relPath: 'Frank Herbert/Dune', + mediaId: 'abcdef12-3456-7890-abcd-ef1234567890', + mediaType: 'book', + isFile: true, + isMissing: false, + isInvalid: false, + mtime: new Date('2023-11-15T10:20:30.400Z'), + ctime: new Date('2023-11-15T10:20:30.400Z'), + birthtime: new Date('2023-11-15T10:20:30.390Z'), + size: 987654321, + lastScan: new Date('2024-01-10T08:15:00.000Z'), + lastScanVersion: '3.2.0', + title: 'Dune', + titleIgnorePrefix: 'Dune', + authorNamesFirstLast: 'Frank Herbert', + authorNamesLastFirst: 'Herbert, Frank', + createdAt: new Date('2023-11-15T10:21:00.000Z'), + updatedAt: new Date('2024-05-15T18:30:36.940Z'), + libraryId: 'fedcba98-7654-3210-fedc-ba9876543210', + libraryFolderId: '11223344-5566-7788-99aa-bbccddeeff00' +}; + + module.exports.notificationData = { events: [ @@ -60,6 +117,22 @@ module.exports.notificationData = { errorMsg: 'Example error message' } }, + // Sockets - Silently crying because not using typescript + + { + name: 'onItemUpdated', + requiresLibrary: true, + description: 'Triggered when an item is updated', + descriptionKey: 'NotificationOnItemUpdatedDescription', + variables: libraryItemVariables, + defaults: { + title: 'Item Updated: {{title}}', + body: 'Item {{title}} has been updated.\n\nPath: {{path}}\nSize: {{size}} bytes\nLast Scan: {{lastScan}}\nLibrary ID: {{libraryId}}\nLibrary Folder ID: {{libraryFolderId}}' + }, + testData: libraryItemTestData + }, + + // Test { name: 'onTest', requiresLibrary: false, From 9e28ee036f9718793a64ecd5aca9722ec61e2574 Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Sat, 17 May 2025 17:55:18 +0200 Subject: [PATCH 2/6] more notifications --- server/SocketAuthority.js | 6 +- server/managers/NotificationManager.js | 20 ++----- server/objects/Notification.js | 4 +- server/utils/notifications.js | 82 +++++++++++++++++++------- server/utils/objectUtils.js | 26 ++++++++ 5 files changed, 99 insertions(+), 39 deletions(-) create mode 100644 server/utils/objectUtils.js diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index f2d634b2..6d13d42e 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -3,6 +3,7 @@ const Logger = require('./Logger') const Database = require('./Database') const Auth = require('./Auth') const NotificationManager = require('./managers/NotificationManager') +const { flattenAny } = require('./utils/objectUtils') /** * @typedef SocketClient @@ -16,7 +17,7 @@ class SocketAuthority { constructor() { this.Server = null this.socketIoServers = [] - this.emittedNotifications = new Set(['item_created', 'item_updated']); + this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online']); /** @type {Object.} */ this.clients = {} @@ -110,7 +111,7 @@ class SocketAuthority { * @param {import('./models/LibraryItem')} libraryItem */ libraryItemEmitter(evt, libraryItem) { - void this._fireNotification(evt, libraryItem) + void this._fireNotification(evt, flattenAny(libraryItem.toOldJSONMinified())) for (const socketId in this.clients) { if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) { this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded()) @@ -126,7 +127,6 @@ class SocketAuthority { * @param {import('./models/LibraryItem')[]} libraryItems */ libraryItemsEmitter(evt, libraryItems) { - void this._fireNotification(evt, libraryItems) for (const socketId in this.clients) { if (this.clients[socketId].user) { const libraryItemsAccessibleToUser = libraryItems.filter((li) => this.clients[socketId].user.checkCanAccessLibraryItem(li)) diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js index fec77c4a..4ccdde19 100644 --- a/server/managers/NotificationManager.js +++ b/server/managers/NotificationManager.js @@ -90,14 +90,6 @@ class NotificationManager { this.triggerNotification('onBackupFailed', eventData) } - /** - * @param - */ - async onItemUpdated(libraryItem) { - console.log('onItemUpdated', libraryItem) - this.triggerNotification('onItemUpdated', libraryItem) - } - onTest() { this.triggerNotification('onTest') } @@ -132,7 +124,8 @@ class NotificationManager { } await Database.updateSetting(Database.notificationSettings) - //SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON()) + // Currently results in circular dependency TODO: Fix this + // SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON()) this.notificationFinished() } @@ -199,6 +192,9 @@ class NotificationManager { const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}`; + console.log(eventData) + console.log(Object.keys(eventData)) + if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) { // No logging to prevent console spam Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`) @@ -207,11 +203,7 @@ class NotificationManager { Logger.debug(`[NotificationManager] fireNotificationFromSocket: ${eventKey} event fired`) - switch (eventKey) { - case 'onItemUpdated': - void this.onItemUpdated(eventData) - break - } + void this.triggerNotification(eventKey, eventData) } } module.exports = new NotificationManager() diff --git a/server/objects/Notification.js b/server/objects/Notification.js index d075e101..8d97697c 100644 --- a/server/objects/Notification.js +++ b/server/objects/Notification.js @@ -102,7 +102,7 @@ class Notification { } replaceVariablesInTemplate(templateText, data) { - const ptrn = /{{ ?([a-zA-Z]+) ?}}/mg + const ptrn = /{{ ?([a-zA-Z.]+) ?}}/mg var match var updatedTemplate = templateText @@ -130,4 +130,4 @@ class Notification { } } } -module.exports = Notification \ No newline at end of file +module.exports = Notification diff --git a/server/utils/notifications.js b/server/utils/notifications.js index 8295a503..dccd43b6 100644 --- a/server/utils/notifications.js +++ b/server/utils/notifications.js @@ -4,29 +4,48 @@ const LibraryItem = require('../models/LibraryItem') const libraryItemVariables = [ 'id', 'ino', + 'oldLibraryItemId', + 'libraryId', + 'folderId', 'path', 'relPath', - 'mediaId', - 'mediaType', 'isFile', + 'mtimeMs', + 'ctimeMs', + 'birthtimeMs', + 'addedAt', + 'updatedAt', 'isMissing', 'isInvalid', - 'mtime', - 'ctime', - 'birthtime', - 'size', - 'lastScan', - 'lastScanVersion', - 'libraryFiles', - 'extraData', - 'title', - 'titleIgnorePrefix', - 'authorNamesFirstLast', - 'authorNamesLastFirst', - 'createdAt', - 'updatedAt', - 'libraryId', - 'libraryFolderId', + 'mediaType', + 'media.id', + 'media.metadata.title', + 'media.metadata.titleIgnorePrefix', + 'media.metadata.subtitle', + 'media.metadata.authorName', + 'media.metadata.authorNameLF', + 'media.metadata.narratorName', + 'media.metadata.seriesName', + 'media.metadata.genres', + 'media.metadata.publishedYear', + 'media.metadata.publishedDate', + 'media.metadata.publisher', + 'media.metadata.description', + 'media.metadata.isbn', + 'media.metadata.asin', + 'media.metadata.language', + 'media.metadata.explicit', + 'media.metadata.abridged', + 'media.coverPath', + 'media.tags', + 'media.numTracks', + 'media.numAudioFiles', + 'media.numChapters', + 'media.duration', + 'media.size', + 'media.ebookFormat', + 'numFiles', + 'size' ] const libraryItemTestData = { @@ -119,6 +138,18 @@ module.exports.notificationData = { }, // Sockets - Silently crying because not using typescript + { + name: 'onItemAdded', + requiresLibrary: true, + description: 'Triggered when an item is added', + descriptionKey: 'NotificationOnItemAddedDescription', + variables: libraryItemVariables, + defaults: { + title: 'Item Added: {{media.metadata.title}}', + body: 'Item {{media.metadata.title}} has been added.\n\nPath: {{path}}\nSize: {{size}} bytes\nLibrary ID: {{libraryId}}' + }, + testData: libraryItemTestData + }, { name: 'onItemUpdated', requiresLibrary: true, @@ -126,11 +157,22 @@ module.exports.notificationData = { descriptionKey: 'NotificationOnItemUpdatedDescription', variables: libraryItemVariables, defaults: { - title: 'Item Updated: {{title}}', - body: 'Item {{title}} has been updated.\n\nPath: {{path}}\nSize: {{size}} bytes\nLast Scan: {{lastScan}}\nLibrary ID: {{libraryId}}\nLibrary Folder ID: {{libraryFolderId}}' + title: 'Item Updated: {{media.metadata.title}}', + body: 'Item {{media.metadata.title}} has been added.\n\nPath: {{path}}\nSize: {{size}} bytes\nLibrary ID: {{libraryId}}' }, testData: libraryItemTestData }, + { + name: 'onUserOnline', + requiresLibrary: false, + description: 'Triggered when a user comes online', + descriptionKey: 'NotificationOnUserOnlineDescription', + variables: [ 'id', 'username', 'type', 'session', 'lastSeen', 'createdAt'], + defaults: { + title: 'User Online: {{username}}', + body: 'User {{username}} (ID: {{id}}) is now online.' + }, + }, // Test { diff --git a/server/utils/objectUtils.js b/server/utils/objectUtils.js new file mode 100644 index 00000000..6ac3133e --- /dev/null +++ b/server/utils/objectUtils.js @@ -0,0 +1,26 @@ +function flattenAny(obj, prefix = '', result = {}) { + const entries = + obj instanceof Map + ? obj.entries() + : Object.entries(obj); + + for (const [key, value] of entries) { + const newKey = prefix ? `${prefix}.${key}` : `${key}`; + if ( + value instanceof Map || + (typeof value === 'object' && + value !== null && + !Array.isArray(value)) + ) { + flattenAny(value, newKey, result); + } else { + result[newKey] = value; + } + } + return result; +} + + +module.exports = { + flattenAny +} From 7b62b6be86bebb5175d623479740f3b70476fc4c Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Sat, 17 May 2025 18:02:23 +0200 Subject: [PATCH 3/6] task notifications --- server/SocketAuthority.js | 8 +++--- server/utils/notifications.js | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index 6d13d42e..46ee66f6 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -17,7 +17,7 @@ class SocketAuthority { constructor() { this.Server = null this.socketIoServers = [] - this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online']); + this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online', 'task_started', 'task_finished']); /** @type {Object.} */ this.clients = {} @@ -69,7 +69,7 @@ class SocketAuthority { * @param {Function} [filter] optional filter function to only send event to specific users */ emitter(evt, data, filter = null) { - void this._fireNotification(evt, data) + void this._fireNotification(evt, flattenAny(data)) for (const socketId in this.clients) { if (this.clients[socketId].user) { if (filter && !filter(this.clients[socketId].user)) continue @@ -81,7 +81,7 @@ class SocketAuthority { // Emits event to all clients for a specific user clientEmitter(userId, evt, data) { - void this._fireNotification(evt, data) + void this._fireNotification(evt, flattenAny(data)) const clients = this.getClientsForUser(userId) if (!clients.length) { return Logger.debug(`[SocketAuthority] clientEmitter - no clients found for user ${userId}`) @@ -95,7 +95,7 @@ class SocketAuthority { // Emits event to all admin user clients adminEmitter(evt, data) { - void this._fireNotification(evt, data); + void this._fireNotification(evt, flattenAny(data)); for (const socketId in this.clients) { if (this.clients[socketId].user?.isAdminOrUp) { this.clients[socketId].socket.emit(evt, data) diff --git a/server/utils/notifications.js b/server/utils/notifications.js index dccd43b6..82976711 100644 --- a/server/utils/notifications.js +++ b/server/utils/notifications.js @@ -173,6 +173,57 @@ module.exports.notificationData = { body: 'User {{username}} (ID: {{id}}) is now online.' }, }, + { + name: 'onTaskStarted', + requiresLibrary: false, + description: 'Triggered when a task starts', + descriptionKey: 'NotificationOnTaskStartedDescription', + variables: [ + 'id', 'action', + 'data.libraryId', 'data.libraryName', + 'title', 'titleKey', + 'titleSubs', 'description', + 'descriptionKey', 'descriptionSubs', + 'error', 'errorKey', + 'errorSubs', 'showSuccess', + 'isFailed', 'isFinished', + 'startedAt', 'finishedAt' + ], + defaults: { + title: 'Task Started: {{title}}', + body: 'Task {{title}} has started.\n\nAction: {{action}}\nLibrary ID: {{data.libraryId}}\nLibrary Name: {{data.libraryName}}' + }, + }, + { + name: 'onTaskFinished', + requiresLibrary: false, + description: 'Triggered when a task finishes', + descriptionKey: 'NotificationOnTaskFinishesDescription', + variables: [ + 'id', + 'action', + 'data.libraryId', + 'data.libraryName', + 'title', + 'titleKey', + 'titleSubs', + 'description', + 'descriptionKey', + 'descriptionSubs', + 'error', + 'errorKey', + 'errorSubs', + 'showSuccess', + 'isFailed', + 'isFinished', + 'startedAt', + 'finishedAt' + ], + defaults: { + title: 'Task Started: {{title}}', + body: 'Task {{title}} has started.\n\nAction: {{action}}\nLibrary ID: {{data.libraryId}}\nLibrary Name: {{data.libraryName}}' + }, + }, // Test { From 39f59e518957acd8ff1e0b4583b3bc24f5581d4a Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Sat, 17 May 2025 18:03:55 +0200 Subject: [PATCH 4/6] moved flatten after O(1) --- server/SocketAuthority.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index 46ee66f6..4df3fe61 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -33,7 +33,7 @@ class SocketAuthority { if (!this.emittedNotifications.has(event)) return Logger.debug(`[SocketAuthority] fireNotification - ${event}`) - NotificationManager.fireNotificationFromSocket(event, payload) + NotificationManager.fireNotificationFromSocket(event, flattenAny(payload)) } /** @@ -69,7 +69,7 @@ class SocketAuthority { * @param {Function} [filter] optional filter function to only send event to specific users */ emitter(evt, data, filter = null) { - void this._fireNotification(evt, flattenAny(data)) + void this._fireNotification(evt, data) for (const socketId in this.clients) { if (this.clients[socketId].user) { if (filter && !filter(this.clients[socketId].user)) continue @@ -81,7 +81,7 @@ class SocketAuthority { // Emits event to all clients for a specific user clientEmitter(userId, evt, data) { - void this._fireNotification(evt, flattenAny(data)) + void this._fireNotification(evt, data) const clients = this.getClientsForUser(userId) if (!clients.length) { return Logger.debug(`[SocketAuthority] clientEmitter - no clients found for user ${userId}`) @@ -95,7 +95,7 @@ class SocketAuthority { // Emits event to all admin user clients adminEmitter(evt, data) { - void this._fireNotification(evt, flattenAny(data)); + void this._fireNotification(evt, data); for (const socketId in this.clients) { if (this.clients[socketId].user?.isAdminOrUp) { this.clients[socketId].socket.emit(evt, data) @@ -111,7 +111,7 @@ class SocketAuthority { * @param {import('./models/LibraryItem')} libraryItem */ libraryItemEmitter(evt, libraryItem) { - void this._fireNotification(evt, flattenAny(libraryItem.toOldJSONMinified())) + void this._fireNotification(evt, libraryItem.toOldJSONMinified()) for (const socketId in this.clients) { if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) { this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded()) From dc41ccc3770f08e0eb91245ca97720f2c51af188 Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Sat, 17 May 2025 18:08:05 +0200 Subject: [PATCH 5/6] prettier --- server/SocketAuthority.js | 4 +-- server/managers/NotificationManager.js | 7 ++-- server/utils/notifications.js | 45 ++++---------------------- 3 files changed, 11 insertions(+), 45 deletions(-) diff --git a/server/SocketAuthority.js b/server/SocketAuthority.js index 4df3fe61..fbc0f9a5 100644 --- a/server/SocketAuthority.js +++ b/server/SocketAuthority.js @@ -17,7 +17,7 @@ class SocketAuthority { constructor() { this.Server = null this.socketIoServers = [] - this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online', 'task_started', 'task_finished']); + this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online', 'task_started', 'task_finished']) /** @type {Object.} */ this.clients = {} @@ -95,7 +95,7 @@ class SocketAuthority { // Emits event to all admin user clients adminEmitter(evt, data) { - void this._fireNotification(evt, data); + void this._fireNotification(evt, data) for (const socketId in this.clients) { if (this.clients[socketId].user?.isAdminOrUp) { this.clients[socketId].socket.emit(evt, data) diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js index 4ccdde19..deb80e71 100644 --- a/server/managers/NotificationManager.js +++ b/server/managers/NotificationManager.js @@ -189,11 +189,8 @@ class NotificationManager { fireNotificationFromSocket(eventName, eventData) { if (!Database.notificationSettings.isUseable) return - const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); - const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}`; - - console.log(eventData) - console.log(Object.keys(eventData)) + const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()) + const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}` if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) { // No logging to prevent console spam diff --git a/server/utils/notifications.js b/server/utils/notifications.js index 82976711..fca52b71 100644 --- a/server/utils/notifications.js +++ b/server/utils/notifications.js @@ -72,9 +72,7 @@ const libraryItemTestData = { updatedAt: new Date('2024-05-15T18:30:36.940Z'), libraryId: 'fedcba98-7654-3210-fedc-ba9876543210', libraryFolderId: '11223344-5566-7788-99aa-bbccddeeff00' -}; - - +} module.exports.notificationData = { events: [ @@ -167,62 +165,33 @@ module.exports.notificationData = { requiresLibrary: false, description: 'Triggered when a user comes online', descriptionKey: 'NotificationOnUserOnlineDescription', - variables: [ 'id', 'username', 'type', 'session', 'lastSeen', 'createdAt'], + variables: ['id', 'username', 'type', 'session', 'lastSeen', 'createdAt'], defaults: { title: 'User Online: {{username}}', body: 'User {{username}} (ID: {{id}}) is now online.' - }, + } }, { name: 'onTaskStarted', requiresLibrary: false, description: 'Triggered when a task starts', descriptionKey: 'NotificationOnTaskStartedDescription', - variables: [ - 'id', 'action', - 'data.libraryId', 'data.libraryName', - 'title', 'titleKey', - 'titleSubs', 'description', - 'descriptionKey', 'descriptionSubs', - 'error', 'errorKey', - 'errorSubs', 'showSuccess', - 'isFailed', 'isFinished', - 'startedAt', 'finishedAt' - ], + variables: ['id', 'action', 'data.libraryId', 'data.libraryName', 'title', 'titleKey', 'titleSubs', 'description', 'descriptionKey', 'descriptionSubs', 'error', 'errorKey', 'errorSubs', 'showSuccess', 'isFailed', 'isFinished', 'startedAt', 'finishedAt'], defaults: { title: 'Task Started: {{title}}', body: 'Task {{title}} has started.\n\nAction: {{action}}\nLibrary ID: {{data.libraryId}}\nLibrary Name: {{data.libraryName}}' - }, + } }, { name: 'onTaskFinished', requiresLibrary: false, description: 'Triggered when a task finishes', descriptionKey: 'NotificationOnTaskFinishesDescription', - variables: [ - 'id', - 'action', - 'data.libraryId', - 'data.libraryName', - 'title', - 'titleKey', - 'titleSubs', - 'description', - 'descriptionKey', - 'descriptionSubs', - 'error', - 'errorKey', - 'errorSubs', - 'showSuccess', - 'isFailed', - 'isFinished', - 'startedAt', - 'finishedAt' - ], + variables: ['id', 'action', 'data.libraryId', 'data.libraryName', 'title', 'titleKey', 'titleSubs', 'description', 'descriptionKey', 'descriptionSubs', 'error', 'errorKey', 'errorSubs', 'showSuccess', 'isFailed', 'isFinished', 'startedAt', 'finishedAt'], defaults: { title: 'Task Started: {{title}}', body: 'Task {{title}} has started.\n\nAction: {{action}}\nLibrary ID: {{data.libraryId}}\nLibrary Name: {{data.libraryName}}' - }, + } }, // Test From 64fa48981eb5009938c53f0692940173580d5875 Mon Sep 17 00:00:00 2001 From: Vito0912 <86927734+Vito0912@users.noreply.github.com> Date: Sat, 17 May 2025 18:20:15 +0200 Subject: [PATCH 6/6] fixed Unit-Test and added void for to async methods --- server/managers/NotificationManager.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/managers/NotificationManager.js b/server/managers/NotificationManager.js index deb80e71..bec73a9a 100644 --- a/server/managers/NotificationManager.js +++ b/server/managers/NotificationManager.js @@ -43,7 +43,7 @@ class NotificationManager { episodeSubtitle: episode.subtitle || '', episodeDescription: episode.description || '' } - this.triggerNotification('onPodcastEpisodeDownloaded', eventData) + void this.triggerNotification('onPodcastEpisodeDownloaded', eventData) } /** @@ -68,7 +68,7 @@ class NotificationManager { backupCount: totalBackupCount || 'Invalid', removedOldest: removedOldest || 'false' } - this.triggerNotification('onBackupCompleted', eventData) + void this.triggerNotification('onBackupCompleted', eventData) } /** @@ -87,11 +87,11 @@ class NotificationManager { const eventData = { errorMsg: errorMsg || 'Backup failed' } - this.triggerNotification('onBackupFailed', eventData) + void this.triggerNotification('onBackupFailed', eventData) } onTest() { - this.triggerNotification('onTest') + void this.triggerNotification('onTest') } /** @@ -157,7 +157,7 @@ class NotificationManager { if (this.notificationQueue.length) { // Send next notification in queue const nextNotificationEvent = this.notificationQueue.shift() - this.triggerNotification(nextNotificationEvent.eventName, nextNotificationEvent.eventData) + void this.triggerNotification(nextNotificationEvent.eventName, nextNotificationEvent.eventData) } }, Database.notificationSettings.notificationDelay) } @@ -187,14 +187,14 @@ class NotificationManager { } fireNotificationFromSocket(eventName, eventData) { - if (!Database.notificationSettings.isUseable) return + if (!Database.notificationSettings || !Database.notificationSettings.isUseable) return const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()) const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}` if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) { // No logging to prevent console spam - Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`) + //Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`) return }