mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-06-28 01:16:10 +02:00
first draft
This commit is contained in:
parent
25c7e95a64
commit
04ba949182
@ -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.<string, SocketClient>} */
|
||||
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))
|
||||
|
@ -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()
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user