more notifications

This commit is contained in:
Vito0912 2025-05-17 17:55:18 +02:00
parent 04ba949182
commit 9e28ee036f
No known key found for this signature in database
GPG Key ID: 29A3D509FE70B237
5 changed files with 99 additions and 39 deletions

View File

@ -3,6 +3,7 @@ const Logger = require('./Logger')
const Database = require('./Database') const Database = require('./Database')
const Auth = require('./Auth') const Auth = require('./Auth')
const NotificationManager = require('./managers/NotificationManager') const NotificationManager = require('./managers/NotificationManager')
const { flattenAny } = require('./utils/objectUtils')
/** /**
* @typedef SocketClient * @typedef SocketClient
@ -16,7 +17,7 @@ class SocketAuthority {
constructor() { constructor() {
this.Server = null this.Server = null
this.socketIoServers = [] this.socketIoServers = []
this.emittedNotifications = new Set(['item_created', 'item_updated']); this.emittedNotifications = new Set(['item_added', 'item_updated', 'user_online']);
/** @type {Object.<string, SocketClient>} */ /** @type {Object.<string, SocketClient>} */
this.clients = {} this.clients = {}
@ -110,7 +111,7 @@ class SocketAuthority {
* @param {import('./models/LibraryItem')} libraryItem * @param {import('./models/LibraryItem')} libraryItem
*/ */
libraryItemEmitter(evt, libraryItem) { libraryItemEmitter(evt, libraryItem) {
void this._fireNotification(evt, libraryItem) void this._fireNotification(evt, flattenAny(libraryItem.toOldJSONMinified()))
for (const socketId in this.clients) { for (const socketId in this.clients) {
if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) { if (this.clients[socketId].user?.checkCanAccessLibraryItem(libraryItem)) {
this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded()) this.clients[socketId].socket.emit(evt, libraryItem.toOldJSONExpanded())
@ -126,7 +127,6 @@ class SocketAuthority {
* @param {import('./models/LibraryItem')[]} libraryItems * @param {import('./models/LibraryItem')[]} libraryItems
*/ */
libraryItemsEmitter(evt, libraryItems) { libraryItemsEmitter(evt, libraryItems) {
void this._fireNotification(evt, libraryItems)
for (const socketId in this.clients) { for (const socketId in this.clients) {
if (this.clients[socketId].user) { if (this.clients[socketId].user) {
const libraryItemsAccessibleToUser = libraryItems.filter((li) => this.clients[socketId].user.checkCanAccessLibraryItem(li)) const libraryItemsAccessibleToUser = libraryItems.filter((li) => this.clients[socketId].user.checkCanAccessLibraryItem(li))

View File

@ -90,14 +90,6 @@ class NotificationManager {
this.triggerNotification('onBackupFailed', eventData) this.triggerNotification('onBackupFailed', eventData)
} }
/**
* @param
*/
async onItemUpdated(libraryItem) {
console.log('onItemUpdated', libraryItem)
this.triggerNotification('onItemUpdated', libraryItem)
}
onTest() { onTest() {
this.triggerNotification('onTest') this.triggerNotification('onTest')
} }
@ -132,7 +124,8 @@ class NotificationManager {
} }
await Database.updateSetting(Database.notificationSettings) 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() this.notificationFinished()
} }
@ -199,6 +192,9 @@ class NotificationManager {
const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase()); const eventNameModified = eventName.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}`; const eventKey = `on${eventNameModified.charAt(0).toUpperCase()}${eventNameModified.slice(1)}`;
console.log(eventData)
console.log(Object.keys(eventData))
if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) { if (!Database.notificationSettings.getHasActiveNotificationsForEvent(eventKey)) {
// No logging to prevent console spam // No logging to prevent console spam
Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`) Logger.debug(`[NotificationManager] fireSocketNotification: No active notifications`)
@ -207,11 +203,7 @@ class NotificationManager {
Logger.debug(`[NotificationManager] fireNotificationFromSocket: ${eventKey} event fired`) Logger.debug(`[NotificationManager] fireNotificationFromSocket: ${eventKey} event fired`)
switch (eventKey) { void this.triggerNotification(eventKey, eventData)
case 'onItemUpdated':
void this.onItemUpdated(eventData)
break
}
} }
} }
module.exports = new NotificationManager() module.exports = new NotificationManager()

View File

@ -102,7 +102,7 @@ class Notification {
} }
replaceVariablesInTemplate(templateText, data) { replaceVariablesInTemplate(templateText, data) {
const ptrn = /{{ ?([a-zA-Z]+) ?}}/mg const ptrn = /{{ ?([a-zA-Z.]+) ?}}/mg
var match var match
var updatedTemplate = templateText var updatedTemplate = templateText
@ -130,4 +130,4 @@ class Notification {
} }
} }
} }
module.exports = Notification module.exports = Notification

View File

@ -4,29 +4,48 @@ const LibraryItem = require('../models/LibraryItem')
const libraryItemVariables = [ const libraryItemVariables = [
'id', 'id',
'ino', 'ino',
'oldLibraryItemId',
'libraryId',
'folderId',
'path', 'path',
'relPath', 'relPath',
'mediaId',
'mediaType',
'isFile', 'isFile',
'mtimeMs',
'ctimeMs',
'birthtimeMs',
'addedAt',
'updatedAt',
'isMissing', 'isMissing',
'isInvalid', 'isInvalid',
'mtime', 'mediaType',
'ctime', 'media.id',
'birthtime', 'media.metadata.title',
'size', 'media.metadata.titleIgnorePrefix',
'lastScan', 'media.metadata.subtitle',
'lastScanVersion', 'media.metadata.authorName',
'libraryFiles', 'media.metadata.authorNameLF',
'extraData', 'media.metadata.narratorName',
'title', 'media.metadata.seriesName',
'titleIgnorePrefix', 'media.metadata.genres',
'authorNamesFirstLast', 'media.metadata.publishedYear',
'authorNamesLastFirst', 'media.metadata.publishedDate',
'createdAt', 'media.metadata.publisher',
'updatedAt', 'media.metadata.description',
'libraryId', 'media.metadata.isbn',
'libraryFolderId', '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 = { const libraryItemTestData = {
@ -119,6 +138,18 @@ module.exports.notificationData = {
}, },
// Sockets - Silently crying because not using typescript // 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', name: 'onItemUpdated',
requiresLibrary: true, requiresLibrary: true,
@ -126,11 +157,22 @@ module.exports.notificationData = {
descriptionKey: 'NotificationOnItemUpdatedDescription', descriptionKey: 'NotificationOnItemUpdatedDescription',
variables: libraryItemVariables, variables: libraryItemVariables,
defaults: { defaults: {
title: 'Item Updated: {{title}}', title: 'Item Updated: {{media.metadata.title}}',
body: 'Item {{title}} has been updated.\n\nPath: {{path}}\nSize: {{size}} bytes\nLast Scan: {{lastScan}}\nLibrary ID: {{libraryId}}\nLibrary Folder ID: {{libraryFolderId}}' body: 'Item {{media.metadata.title}} has been added.\n\nPath: {{path}}\nSize: {{size}} bytes\nLibrary ID: {{libraryId}}'
}, },
testData: libraryItemTestData 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 // Test
{ {

View File

@ -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
}