mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Update:Refactor socket connection management into SocketAuthority
This commit is contained in:
parent
42e68edc65
commit
e2af33e136
196
server/Server.js
196
server/Server.js
@ -1,7 +1,6 @@
|
||||
const Path = require('path')
|
||||
const express = require('express')
|
||||
const http = require('http')
|
||||
const SocketIO = require('socket.io')
|
||||
const fs = require('./libs/fsExtra')
|
||||
const fileUpload = require('./libs/expressFileupload')
|
||||
const rateLimit = require('./libs/expressRateLimit')
|
||||
@ -13,11 +12,11 @@ const dbMigration = require('./utils/dbMigration')
|
||||
const filePerms = require('./utils/filePerms')
|
||||
const Logger = require('./Logger')
|
||||
|
||||
// Classes
|
||||
const Auth = require('./Auth')
|
||||
const Watcher = require('./Watcher')
|
||||
const Scanner = require('./scanner/Scanner')
|
||||
const Db = require('./Db')
|
||||
const SocketAuthority = require('./SocketAuthority')
|
||||
|
||||
const ApiRouter = require('./routers/ApiRouter')
|
||||
const HlsRouter = require('./routers/HlsRouter')
|
||||
@ -67,70 +66,30 @@ class Server {
|
||||
this.auth = new Auth(this.db)
|
||||
|
||||
// Managers
|
||||
this.taskManager = new TaskManager(this.emitter.bind(this))
|
||||
this.notificationManager = new NotificationManager(this.db, this.emitter.bind(this))
|
||||
this.backupManager = new BackupManager(this.db, this.emitter.bind(this))
|
||||
this.taskManager = new TaskManager()
|
||||
this.notificationManager = new NotificationManager(this.db)
|
||||
this.backupManager = new BackupManager(this.db)
|
||||
this.logManager = new LogManager(this.db)
|
||||
this.cacheManager = new CacheManager()
|
||||
this.abMergeManager = new AbMergeManager(this.db, this.taskManager, this.clientEmitter.bind(this))
|
||||
this.playbackSessionManager = new PlaybackSessionManager(this.db, this.emitter.bind(this), this.clientEmitter.bind(this))
|
||||
this.abMergeManager = new AbMergeManager(this.db, this.taskManager)
|
||||
this.playbackSessionManager = new PlaybackSessionManager(this.db)
|
||||
this.coverManager = new CoverManager(this.db, this.cacheManager)
|
||||
this.podcastManager = new PodcastManager(this.db, this.watcher, this.emitter.bind(this), this.notificationManager)
|
||||
this.audioMetadataManager = new AudioMetadataMangaer(this.db, this.taskManager, this.emitter.bind(this), this.clientEmitter.bind(this))
|
||||
this.rssFeedManager = new RssFeedManager(this.db, this.emitter.bind(this))
|
||||
this.podcastManager = new PodcastManager(this.db, this.watcher, this.notificationManager)
|
||||
this.audioMetadataManager = new AudioMetadataMangaer(this.db, this.taskManager)
|
||||
this.rssFeedManager = new RssFeedManager(this.db)
|
||||
|
||||
this.scanner = new Scanner(this.db, this.coverManager, this.emitter.bind(this))
|
||||
this.scanner = new Scanner(this.db, this.coverManager)
|
||||
this.cronManager = new CronManager(this.db, this.scanner, this.podcastManager)
|
||||
|
||||
// Routers
|
||||
this.apiRouter = new ApiRouter(this.db, this.auth, this.scanner, this.playbackSessionManager, this.abMergeManager, this.coverManager, this.backupManager, this.watcher, this.cacheManager, this.podcastManager, this.audioMetadataManager, this.rssFeedManager, this.cronManager, this.notificationManager, this.taskManager, this.getUsersOnline.bind(this), this.emitter.bind(this), this.clientEmitter.bind(this))
|
||||
this.hlsRouter = new HlsRouter(this.db, this.auth, this.playbackSessionManager, this.emitter.bind(this))
|
||||
this.apiRouter = new ApiRouter(this)
|
||||
this.hlsRouter = new HlsRouter(this.db, this.auth, this.playbackSessionManager)
|
||||
this.staticRouter = new StaticRouter(this.db)
|
||||
|
||||
Logger.logManager = this.logManager
|
||||
|
||||
this.server = null
|
||||
this.io = null
|
||||
|
||||
this.clients = {}
|
||||
}
|
||||
|
||||
// returns an array of User.toJSONForPublic with `connections` for the # of socket connections
|
||||
// a user can have many socket connections
|
||||
getUsersOnline() {
|
||||
const onlineUsersMap = {}
|
||||
Object.values(this.clients).filter(c => c.user).forEach(client => {
|
||||
if (onlineUsersMap[client.user.id]) {
|
||||
onlineUsersMap[client.user.id].connections++
|
||||
} else {
|
||||
onlineUsersMap[client.user.id] = {
|
||||
...client.user.toJSONForPublic(this.playbackSessionManager.sessions, this.db.libraryItems),
|
||||
connections: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
return Object.values(onlineUsersMap)
|
||||
}
|
||||
|
||||
getClientsForUser(userId) {
|
||||
return Object.values(this.clients).filter(c => c.user && c.user.id === userId)
|
||||
}
|
||||
|
||||
emitter(ev, data) {
|
||||
// Logger.debug('EMITTER', ev)
|
||||
this.io.emit(ev, data)
|
||||
}
|
||||
|
||||
clientEmitter(userId, ev, data) {
|
||||
var clients = this.getClientsForUser(userId)
|
||||
if (!clients.length) {
|
||||
return Logger.debug(`[Server] clientEmitter - no clients found for user ${userId}`)
|
||||
}
|
||||
clients.forEach((client) => {
|
||||
if (client.socket) {
|
||||
client.socket.emit(ev, data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
authMiddleware(req, res, next) {
|
||||
@ -283,71 +242,8 @@ class Server {
|
||||
Logger.info(`Listening on http://${this.Host}:${this.Port}`)
|
||||
})
|
||||
|
||||
this.io = new SocketIO.Server(this.server, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ["GET", "POST"]
|
||||
}
|
||||
})
|
||||
this.io.on('connection', (socket) => {
|
||||
this.clients[socket.id] = {
|
||||
id: socket.id,
|
||||
socket,
|
||||
connected_at: Date.now()
|
||||
}
|
||||
socket.sheepClient = this.clients[socket.id]
|
||||
|
||||
Logger.info('[Server] Socket Connected', socket.id)
|
||||
|
||||
// Required for associating a User with a socket
|
||||
socket.on('auth', (token) => this.authenticateSocket(socket, token))
|
||||
|
||||
// Scanning
|
||||
socket.on('cancel_scan', this.cancelScan.bind(this))
|
||||
|
||||
// Logs
|
||||
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
||||
socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id))
|
||||
socket.on('fetch_daily_logs', () => this.logManager.socketRequestDailyLogs(socket))
|
||||
|
||||
// Events for testing
|
||||
socket.on('message_all_users', (payload) => {
|
||||
// admin user can send a message to all authenticated users
|
||||
// displays on the web app as a toast
|
||||
const client = this.clients[socket.id] || {}
|
||||
if (client.user && client.user.isAdminOrUp) {
|
||||
this.emitter('admin_message', payload.message || '')
|
||||
} else {
|
||||
Logger.error(`[Server] Non-admin user sent the message_all_users event`)
|
||||
}
|
||||
})
|
||||
socket.on('ping', () => {
|
||||
const client = this.clients[socket.id] || {}
|
||||
const user = client.user || {}
|
||||
Logger.debug(`[Server] Received ping from socket ${user.username || 'No User'}`)
|
||||
socket.emit('pong')
|
||||
})
|
||||
|
||||
// Sent automatically from socket.io clients
|
||||
socket.on('disconnect', (reason) => {
|
||||
Logger.removeSocketListener(socket.id)
|
||||
|
||||
const _client = this.clients[socket.id]
|
||||
if (!_client) {
|
||||
Logger.warn(`[Server] Socket ${socket.id} disconnect, no client (Reason: ${reason})`)
|
||||
} else if (!_client.user) {
|
||||
Logger.info(`[Server] Unauth socket ${socket.id} disconnected (Reason: ${reason})`)
|
||||
delete this.clients[socket.id]
|
||||
} else {
|
||||
Logger.debug('[Server] User Offline ' + _client.user.username)
|
||||
this.io.emit('user_offline', _client.user.toJSONForPublic(this.playbackSessionManager.sessions, this.db.libraryItems))
|
||||
|
||||
const disconnectTime = Date.now() - _client.connected_at
|
||||
Logger.info(`[Server] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms (Reason: ${reason})`)
|
||||
delete this.clients[socket.id]
|
||||
}
|
||||
})
|
||||
})
|
||||
// Start listening for socket connections
|
||||
SocketAuthority.initialize(this)
|
||||
}
|
||||
|
||||
async initializeServer(req, res) {
|
||||
@ -366,11 +262,6 @@ class Server {
|
||||
await this.scanner.scanFilesChanged(fileUpdates)
|
||||
}
|
||||
|
||||
cancelScan(id) {
|
||||
Logger.debug('[Server] Cancel scan', id)
|
||||
this.scanner.setCancelLibraryScan(id)
|
||||
}
|
||||
|
||||
// Remove unused /metadata/items/{id} folders
|
||||
async purgeMetadata() {
|
||||
var itemsMetadata = Path.join(global.MetadataPath, 'items')
|
||||
@ -449,68 +340,11 @@ class Server {
|
||||
logout(req, res) {
|
||||
var { socketId } = req.body
|
||||
Logger.info(`[Server] User ${req.user ? req.user.username : 'Unknown'} is logging out with socket ${socketId}`)
|
||||
|
||||
// Strip user and client from client and client socket
|
||||
if (socketId && this.clients[socketId]) {
|
||||
var client = this.clients[socketId]
|
||||
var clientSocket = client.socket
|
||||
Logger.debug(`[Server] Found user client ${clientSocket.id}, Has user: ${!!client.user}, Socket has client: ${!!clientSocket.sheepClient}`)
|
||||
|
||||
if (client.user) {
|
||||
Logger.debug('[Server] User Offline ' + client.user.username)
|
||||
this.io.emit('user_offline', client.user.toJSONForPublic(null, this.db.libraryItems))
|
||||
}
|
||||
|
||||
delete this.clients[socketId].user
|
||||
if (clientSocket && clientSocket.sheepClient) delete this.clients[socketId].socket.sheepClient
|
||||
} else if (socketId) {
|
||||
Logger.warn(`[Server] No client for socket ${socketId}`)
|
||||
}
|
||||
SocketAuthority.logout(socketId)
|
||||
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
// When setting up a socket connection the user needs to be associated with a socket id
|
||||
// for this the client will send a 'auth' event that includes the users API token
|
||||
async authenticateSocket(socket, token) {
|
||||
const user = await this.auth.authenticateUser(token)
|
||||
if (!user) {
|
||||
Logger.error('Cannot validate socket - invalid token')
|
||||
return socket.emit('invalid_token')
|
||||
}
|
||||
const client = this.clients[socket.id]
|
||||
|
||||
if (client.user !== undefined) {
|
||||
Logger.debug(`[Server] Authenticating socket client already has user`, client.user.username)
|
||||
}
|
||||
|
||||
client.user = user
|
||||
|
||||
if (!client.user.toJSONForBrowser) {
|
||||
Logger.error('Invalid user...', client.user)
|
||||
return
|
||||
}
|
||||
|
||||
Logger.debug(`[Server] User Online ${client.user.username}`)
|
||||
|
||||
// TODO: Send to authenticated clients only
|
||||
this.io.emit('user_online', client.user.toJSONForPublic(this.playbackSessionManager.sessions, this.db.libraryItems))
|
||||
|
||||
user.lastSeen = Date.now()
|
||||
await this.db.updateEntity('user', user)
|
||||
|
||||
const initialPayload = {
|
||||
userId: client.user.id,
|
||||
username: client.user.username,
|
||||
librariesScanning: this.scanner.librariesScanning
|
||||
}
|
||||
if (user.isAdminOrUp) {
|
||||
initialPayload.usersOnline = this.getUsersOnline()
|
||||
}
|
||||
|
||||
client.socket.emit('init', initialPayload)
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.watcher.close()
|
||||
Logger.info('Watcher Closed')
|
||||
|
186
server/SocketAuthority.js
Normal file
186
server/SocketAuthority.js
Normal file
@ -0,0 +1,186 @@
|
||||
const SocketIO = require('socket.io')
|
||||
const Logger = require('./Logger')
|
||||
|
||||
class SocketAuthority {
|
||||
constructor() {
|
||||
this.Server = null
|
||||
this.io = null
|
||||
|
||||
this.clients = {}
|
||||
}
|
||||
|
||||
// returns an array of User.toJSONForPublic with `connections` for the # of socket connections
|
||||
// a user can have many socket connections
|
||||
getUsersOnline() {
|
||||
const onlineUsersMap = {}
|
||||
Object.values(this.clients).filter(c => c.user).forEach(client => {
|
||||
if (onlineUsersMap[client.user.id]) {
|
||||
onlineUsersMap[client.user.id].connections++
|
||||
} else {
|
||||
onlineUsersMap[client.user.id] = {
|
||||
...client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions, this.Server.db.libraryItems),
|
||||
connections: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
return Object.values(onlineUsersMap)
|
||||
}
|
||||
|
||||
getClientsForUser(userId) {
|
||||
return Object.values(this.clients).filter(c => c.user && c.user.id === userId)
|
||||
}
|
||||
|
||||
emitter(evt, data) {
|
||||
for (const socketId in this.clients) {
|
||||
this.clients[socketId].socket.emit(evt, data)
|
||||
}
|
||||
}
|
||||
|
||||
clientEmitter(userId, ev, data) {
|
||||
var clients = this.getClientsForUser(userId)
|
||||
if (!clients.length) {
|
||||
return Logger.debug(`[Server] clientEmitter - no clients found for user ${userId}`)
|
||||
}
|
||||
clients.forEach((client) => {
|
||||
if (client.socket) {
|
||||
client.socket.emit(ev, data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
initialize(Server) {
|
||||
this.Server = Server
|
||||
|
||||
this.io = new SocketIO.Server(this.Server.server, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: ["GET", "POST"]
|
||||
}
|
||||
})
|
||||
this.io.on('connection', (socket) => {
|
||||
this.clients[socket.id] = {
|
||||
id: socket.id,
|
||||
socket,
|
||||
connected_at: Date.now()
|
||||
}
|
||||
socket.sheepClient = this.clients[socket.id]
|
||||
|
||||
Logger.info('[Server] Socket Connected', socket.id)
|
||||
|
||||
// Required for associating a User with a socket
|
||||
socket.on('auth', (token) => this.authenticateSocket(socket, token))
|
||||
|
||||
// Scanning
|
||||
socket.on('cancel_scan', this.cancelScan.bind(this))
|
||||
|
||||
// Logs
|
||||
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
||||
socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id))
|
||||
socket.on('fetch_daily_logs', () => this.Server.logManager.socketRequestDailyLogs(socket))
|
||||
|
||||
// Events for testing
|
||||
socket.on('message_all_users', (payload) => {
|
||||
// admin user can send a message to all authenticated users
|
||||
// displays on the web app as a toast
|
||||
const client = this.clients[socket.id] || {}
|
||||
if (client.user && client.user.isAdminOrUp) {
|
||||
this.emitter('admin_message', payload.message || '')
|
||||
} else {
|
||||
Logger.error(`[Server] Non-admin user sent the message_all_users event`)
|
||||
}
|
||||
})
|
||||
socket.on('ping', () => {
|
||||
const client = this.clients[socket.id] || {}
|
||||
const user = client.user || {}
|
||||
Logger.debug(`[Server] Received ping from socket ${user.username || 'No User'}`)
|
||||
socket.emit('pong')
|
||||
})
|
||||
|
||||
// Sent automatically from socket.io clients
|
||||
socket.on('disconnect', (reason) => {
|
||||
Logger.removeSocketListener(socket.id)
|
||||
|
||||
const _client = this.clients[socket.id]
|
||||
if (!_client) {
|
||||
Logger.warn(`[Server] Socket ${socket.id} disconnect, no client (Reason: ${reason})`)
|
||||
} else if (!_client.user) {
|
||||
Logger.info(`[Server] Unauth socket ${socket.id} disconnected (Reason: ${reason})`)
|
||||
delete this.clients[socket.id]
|
||||
} else {
|
||||
Logger.debug('[Server] User Offline ' + _client.user.username)
|
||||
this.io.emit('user_offline', _client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions, this.Server.db.libraryItems))
|
||||
|
||||
const disconnectTime = Date.now() - _client.connected_at
|
||||
Logger.info(`[Server] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms (Reason: ${reason})`)
|
||||
delete this.clients[socket.id]
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// When setting up a socket connection the user needs to be associated with a socket id
|
||||
// for this the client will send a 'auth' event that includes the users API token
|
||||
async authenticateSocket(socket, token) {
|
||||
const user = await this.Server.auth.authenticateUser(token)
|
||||
if (!user) {
|
||||
Logger.error('Cannot validate socket - invalid token')
|
||||
return socket.emit('invalid_token')
|
||||
}
|
||||
const client = this.clients[socket.id]
|
||||
|
||||
if (client.user !== undefined) {
|
||||
Logger.debug(`[Server] Authenticating socket client already has user`, client.user.username)
|
||||
}
|
||||
|
||||
client.user = user
|
||||
|
||||
if (!client.user.toJSONForBrowser) {
|
||||
Logger.error('Invalid user...', client.user)
|
||||
return
|
||||
}
|
||||
|
||||
Logger.debug(`[Server] User Online ${client.user.username}`)
|
||||
|
||||
// TODO: Send to authenticated clients only
|
||||
this.io.emit('user_online', client.user.toJSONForPublic(this.Server.playbackSessionManager.sessions, this.Server.db.libraryItems))
|
||||
|
||||
user.lastSeen = Date.now()
|
||||
await this.Server.db.updateEntity('user', user)
|
||||
|
||||
const initialPayload = {
|
||||
userId: client.user.id,
|
||||
username: client.user.username,
|
||||
librariesScanning: this.Server.scanner.librariesScanning
|
||||
}
|
||||
if (user.isAdminOrUp) {
|
||||
initialPayload.usersOnline = this.getUsersOnline()
|
||||
}
|
||||
|
||||
client.socket.emit('init', initialPayload)
|
||||
}
|
||||
|
||||
logout(socketId) {
|
||||
// Strip user and client from client and client socket
|
||||
if (socketId && this.clients[socketId]) {
|
||||
var client = this.clients[socketId]
|
||||
var clientSocket = client.socket
|
||||
Logger.debug(`[Server] Found user client ${clientSocket.id}, Has user: ${!!client.user}, Socket has client: ${!!clientSocket.sheepClient}`)
|
||||
|
||||
if (client.user) {
|
||||
Logger.debug('[Server] User Offline ' + client.user.username)
|
||||
this.io.emit('user_offline', client.user.toJSONForPublic(null, this.Server.db.libraryItems))
|
||||
}
|
||||
|
||||
delete this.clients[socketId].user
|
||||
if (clientSocket && clientSocket.sheepClient) delete this.clients[socketId].socket.sheepClient
|
||||
} else if (socketId) {
|
||||
Logger.warn(`[Server] No client for socket ${socketId}`)
|
||||
}
|
||||
}
|
||||
|
||||
cancelScan(id) {
|
||||
Logger.debug('[Server] Cancel scan', id)
|
||||
this.Server.scanner.setCancelLibraryScan(id)
|
||||
}
|
||||
}
|
||||
module.exports = new SocketAuthority()
|
@ -1,4 +1,6 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const { reqSupportsWebp } = require('../utils/index')
|
||||
const { createNewSortInstance } = require('../libs/fastSort')
|
||||
|
||||
@ -93,18 +95,18 @@ class AuthorController {
|
||||
})
|
||||
if (itemsWithAuthor.length) {
|
||||
await this.db.updateLibraryItems(itemsWithAuthor)
|
||||
this.emitter('items_updated', itemsWithAuthor.map(li => li.toJSONExpanded()))
|
||||
SocketAuthority.emitter('items_updated', itemsWithAuthor.map(li => li.toJSONExpanded()))
|
||||
}
|
||||
|
||||
// Remove old author
|
||||
await this.db.removeEntity('author', req.author.id)
|
||||
this.emitter('author_removed', req.author.toJSON())
|
||||
SocketAuthority.emitter('author_removed', req.author.toJSON())
|
||||
|
||||
// Send updated num books for merged author
|
||||
var numBooks = this.db.libraryItems.filter(li => {
|
||||
return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(existingAuthor.id)
|
||||
}).length
|
||||
this.emitter('author_updated', existingAuthor.toJSONExpanded(numBooks))
|
||||
SocketAuthority.emitter('author_updated', existingAuthor.toJSONExpanded(numBooks))
|
||||
|
||||
res.json({
|
||||
author: existingAuthor.toJSON(),
|
||||
@ -121,7 +123,7 @@ class AuthorController {
|
||||
})
|
||||
if (itemsWithAuthor.length) {
|
||||
await this.db.updateLibraryItems(itemsWithAuthor)
|
||||
this.emitter('items_updated', itemsWithAuthor.map(li => li.toJSONExpanded()))
|
||||
SocketAuthority.emitter('items_updated', itemsWithAuthor.map(li => li.toJSONExpanded()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +131,7 @@ class AuthorController {
|
||||
var numBooks = this.db.libraryItems.filter(li => {
|
||||
return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(req.author.id)
|
||||
}).length
|
||||
this.emitter('author_updated', req.author.toJSONExpanded(numBooks))
|
||||
SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
|
||||
}
|
||||
|
||||
res.json({
|
||||
@ -190,7 +192,7 @@ class AuthorController {
|
||||
var numBooks = this.db.libraryItems.filter(li => {
|
||||
return li.media.metadata.hasAuthor && li.media.metadata.hasAuthor(req.author.id)
|
||||
}).length
|
||||
this.emitter('author_updated', req.author.toJSONExpanded(numBooks))
|
||||
SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
|
||||
}
|
||||
|
||||
res.json({
|
||||
|
@ -1,4 +1,6 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const Collection = require('../objects/Collection')
|
||||
|
||||
class CollectionController {
|
||||
@ -13,7 +15,7 @@ class CollectionController {
|
||||
}
|
||||
var jsonExpanded = newCollection.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.insertEntity('collection', newCollection)
|
||||
this.emitter('collection_added', jsonExpanded)
|
||||
SocketAuthority.emitter('collection_added', jsonExpanded)
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
@ -32,7 +34,7 @@ class CollectionController {
|
||||
var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.emitter('collection_updated', jsonExpanded)
|
||||
SocketAuthority.emitter('collection_updated', jsonExpanded)
|
||||
}
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
@ -41,7 +43,7 @@ class CollectionController {
|
||||
const collection = req.collection
|
||||
var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.removeEntity('collection', collection.id)
|
||||
this.emitter('collection_removed', jsonExpanded)
|
||||
SocketAuthority.emitter('collection_removed', jsonExpanded)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
@ -60,7 +62,7 @@ class CollectionController {
|
||||
collection.addBook(req.body.id)
|
||||
var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.emitter('collection_updated', jsonExpanded)
|
||||
SocketAuthority.emitter('collection_updated', jsonExpanded)
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
@ -71,7 +73,7 @@ class CollectionController {
|
||||
collection.removeBook(req.params.bookId)
|
||||
var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.emitter('collection_updated', jsonExpanded)
|
||||
SocketAuthority.emitter('collection_updated', jsonExpanded)
|
||||
}
|
||||
res.json(collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
@ -92,7 +94,7 @@ class CollectionController {
|
||||
}
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.emitter('collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
SocketAuthority.emitter('collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
res.json(collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
@ -113,7 +115,7 @@ class CollectionController {
|
||||
}
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.emitter('collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
SocketAuthority.emitter('collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
res.json(collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ const Path = require('path')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const filePerms = require('../utils/filePerms')
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Library = require('../objects/Library')
|
||||
const libraryHelpers = require('../utils/libraryHelpers')
|
||||
const { sort, createNewSortInstance } = require('../libs/fastSort')
|
||||
@ -43,7 +44,7 @@ class LibraryController {
|
||||
library.setData(newLibraryPayload)
|
||||
await this.db.insertEntity('library', library)
|
||||
// TODO: Only emit to users that have access
|
||||
this.emitter('library_added', library.toJSON())
|
||||
SocketAuthority.emitter('library_added', library.toJSON())
|
||||
|
||||
// Add library watcher
|
||||
this.watcher.addLibrary(library)
|
||||
@ -120,7 +121,7 @@ class LibraryController {
|
||||
}
|
||||
}
|
||||
await this.db.updateEntity('library', library)
|
||||
this.emitter('library_updated', library.toJSON())
|
||||
SocketAuthority.emitter('library_updated', library.toJSON())
|
||||
}
|
||||
return res.json(library.toJSON())
|
||||
}
|
||||
@ -147,7 +148,7 @@ class LibraryController {
|
||||
|
||||
var libraryJson = library.toJSON()
|
||||
await this.db.removeEntity('library', library.id)
|
||||
this.emitter('library_removed', libraryJson)
|
||||
SocketAuthority.emitter('library_removed', libraryJson)
|
||||
return res.json(libraryJson)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const { reqSupportsWebp, isNullOrNaN } = require('../utils/index')
|
||||
const { ScanResult } = require('../utils/constants')
|
||||
|
||||
@ -53,7 +55,7 @@ class LibraryItemController {
|
||||
if (hasUpdates) {
|
||||
Logger.debug(`[LibraryItemController] Updated now saving`)
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
res.json(libraryItem.toJSON())
|
||||
}
|
||||
@ -97,7 +99,7 @@ class LibraryItemController {
|
||||
|
||||
Logger.debug(`[LibraryItemController] Updated library item media ${libraryItem.media.metadata.title}`)
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
res.json({
|
||||
updated: hasUpdates,
|
||||
@ -132,7 +134,7 @@ class LibraryItemController {
|
||||
}
|
||||
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
res.json({
|
||||
success: true,
|
||||
cover: result.cover
|
||||
@ -152,7 +154,7 @@ class LibraryItemController {
|
||||
}
|
||||
if (validationResult.updated) {
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
res.json({
|
||||
success: true,
|
||||
@ -168,7 +170,7 @@ class LibraryItemController {
|
||||
libraryItem.updateMediaCover('')
|
||||
await this.cacheManager.purgeCoverCache(libraryItem.id)
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
|
||||
res.sendStatus(200)
|
||||
@ -228,7 +230,7 @@ class LibraryItemController {
|
||||
}
|
||||
libraryItem.media.updateAudioTracks(orderedFileData)
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
res.json(libraryItem.toJSON())
|
||||
}
|
||||
|
||||
@ -284,7 +286,7 @@ class LibraryItemController {
|
||||
if (hasUpdates) {
|
||||
Logger.debug(`[LibraryItemController] Updated library item media ${libraryItem.media.metadata.title}`)
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
itemsUpdated++
|
||||
}
|
||||
}
|
||||
@ -342,7 +344,7 @@ class LibraryItemController {
|
||||
updates: itemsUpdated,
|
||||
unmatched: itemsUnmatched
|
||||
}
|
||||
this.clientEmitter(req.user.id, 'batch_quickmatch_complete', result)
|
||||
SocketAuthority.clientEmitter(req.user.id, 'batch_quickmatch_complete', result)
|
||||
}
|
||||
|
||||
// DELETE: api/items/all
|
||||
@ -410,7 +412,7 @@ class LibraryItemController {
|
||||
const wasUpdated = req.libraryItem.media.updateChapters(chapters)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateLibraryItem(req.libraryItem)
|
||||
this.emitter('item_updated', req.libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', req.libraryItem.toJSONExpanded())
|
||||
}
|
||||
|
||||
res.json({
|
||||
|
@ -1,4 +1,5 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const { sort } = require('../libs/fastSort')
|
||||
const { isObject, toNumber } = require('../utils/index')
|
||||
|
||||
@ -48,7 +49,7 @@ class MeController {
|
||||
return res.sendStatus(200)
|
||||
}
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
@ -62,7 +63,7 @@ class MeController {
|
||||
var wasUpdated = req.user.createUpdateMediaProgress(libraryItem, req.body)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.sendStatus(200)
|
||||
}
|
||||
@ -82,7 +83,7 @@ class MeController {
|
||||
var wasUpdated = req.user.createUpdateMediaProgress(libraryItem, req.body, episodeId)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.sendStatus(200)
|
||||
}
|
||||
@ -107,7 +108,7 @@ class MeController {
|
||||
|
||||
if (shouldUpdate) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
|
||||
res.sendStatus(200)
|
||||
@ -120,7 +121,7 @@ class MeController {
|
||||
const { time, title } = req.body
|
||||
var bookmark = req.user.createBookmark(libraryItem.id, time, title)
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
res.json(bookmark)
|
||||
}
|
||||
|
||||
@ -136,7 +137,7 @@ class MeController {
|
||||
var bookmark = req.user.updateBookmark(libraryItem.id, time, title)
|
||||
if (!bookmark) return res.sendStatus(500)
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
res.json(bookmark)
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ class MeController {
|
||||
}
|
||||
req.user.removeBookmark(libraryItem.id, time)
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
@ -233,7 +234,7 @@ class MeController {
|
||||
Logger.debug(`[MeController] syncLocalMediaProgress server updates = ${numServerProgressUpdates}, local updates = ${updatedLocalMediaProgress.length}`)
|
||||
if (numServerProgressUpdates > 0) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
|
||||
res.json({
|
||||
@ -288,7 +289,7 @@ class MeController {
|
||||
const hasUpdated = req.user.addSeriesToHideFromContinueListening(req.params.id)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.json(req.user.toJSONForBrowser())
|
||||
}
|
||||
@ -304,7 +305,7 @@ class MeController {
|
||||
const hasUpdated = req.user.removeSeriesFromHideFromContinueListening(req.params.id)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.json(req.user.toJSONForBrowser())
|
||||
}
|
||||
@ -314,7 +315,7 @@ class MeController {
|
||||
const hasUpdated = req.user.removeProgressFromContinueListening(req.params.id)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('user', req.user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.json(req.user.toJSONForBrowser())
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
const axios = require('axios')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
const { getPodcastFeed, findMatchingEpisodes } = require('../utils/podcastUtils')
|
||||
const LibraryItem = require('../objects/LibraryItem')
|
||||
const { getFileTimestampsWithIno } = require('../utils/fileUtils')
|
||||
const filePerms = require('../utils/filePerms')
|
||||
|
||||
const LibraryItem = require('../objects/LibraryItem')
|
||||
|
||||
class PodcastController {
|
||||
|
||||
async create(req, res) {
|
||||
@ -75,7 +78,7 @@ class PodcastController {
|
||||
}
|
||||
|
||||
await this.db.insertLibraryItem(libraryItem)
|
||||
this.emitter('item_added', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_added', libraryItem.toJSONExpanded())
|
||||
|
||||
res.json(libraryItem.toJSONExpanded())
|
||||
|
||||
@ -194,7 +197,7 @@ class PodcastController {
|
||||
var wasUpdated = libraryItem.media.updateEpisode(episodeId, req.body)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
|
||||
res.json(libraryItem.toJSONExpanded())
|
||||
@ -229,7 +232,7 @@ class PodcastController {
|
||||
}
|
||||
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
res.json(libraryItem.toJSON())
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
class SeriesController {
|
||||
constructor() { }
|
||||
@ -38,7 +39,7 @@ class SeriesController {
|
||||
const hasUpdated = req.series.update(req.body)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('series', req.series)
|
||||
this.emitter('series_updated', req.series)
|
||||
SocketAuthority.emitter('series_updated', req.series)
|
||||
}
|
||||
res.json(req.series)
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const User = require('../objects/user/User')
|
||||
|
||||
const { getId, toNumber } = require('../utils/index')
|
||||
@ -44,7 +46,7 @@ class UserController {
|
||||
var newUser = new User(account)
|
||||
var success = await this.db.insertEntity('user', newUser)
|
||||
if (success) {
|
||||
this.clientEmitter(req.user.id, 'user_added', newUser)
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_added', newUser)
|
||||
res.json({
|
||||
user: newUser.toJSONForBrowser()
|
||||
})
|
||||
@ -85,7 +87,7 @@ class UserController {
|
||||
Logger.info(`[UserController] User ${user.username} was generated a new api token`)
|
||||
}
|
||||
await this.db.updateEntity('user', user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', user.toJSONForBrowser())
|
||||
}
|
||||
|
||||
res.json({
|
||||
@ -109,7 +111,7 @@ class UserController {
|
||||
|
||||
var userJson = user.toJSONForBrowser()
|
||||
await this.db.removeEntity('user', user.id)
|
||||
this.clientEmitter(req.user.id, 'user_removed', userJson)
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_removed', userJson)
|
||||
res.json({
|
||||
success: true
|
||||
})
|
||||
@ -170,7 +172,7 @@ class UserController {
|
||||
if (progressPurged) {
|
||||
Logger.info(`[UserController] Purged ${progressPurged} media progress for user ${user.username}`)
|
||||
await this.db.updateEntity('user', user)
|
||||
this.clientEmitter(req.user.id, 'user_updated', user.toJSONForBrowser())
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', user.toJSONForBrowser())
|
||||
}
|
||||
|
||||
res.json(this.userJsonWithItemProgressDetails(user, !req.user.isRoot))
|
||||
@ -181,10 +183,9 @@ class UserController {
|
||||
if (!req.user.isAdminOrUp) {
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
const usersOnline = this.getUsersOnline()
|
||||
|
||||
res.json({
|
||||
usersOnline,
|
||||
usersOnline: SocketAuthority.getUsersOnline(),
|
||||
openSessions: this.playbackSessionManager.sessions
|
||||
})
|
||||
}
|
||||
|
@ -10,10 +10,9 @@ const { writeConcatFile } = require('../utils/ffmpegHelpers')
|
||||
const toneHelpers = require('../utils/toneHelpers')
|
||||
|
||||
class AbMergeManager {
|
||||
constructor(db, taskManager, clientEmitter) {
|
||||
constructor(db, taskManager) {
|
||||
this.db = db
|
||||
this.taskManager = taskManager
|
||||
this.clientEmitter = clientEmitter
|
||||
|
||||
this.itemsCacheDir = Path.join(global.MetadataPath, 'cache/items')
|
||||
this.downloadDirPath = Path.join(global.MetadataPath, 'downloads')
|
||||
|
@ -1,18 +1,20 @@
|
||||
const Path = require('path')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const workerThreads = require('worker_threads')
|
||||
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
const filePerms = require('../utils/filePerms')
|
||||
const { secondsToTimestamp } = require('../utils/index')
|
||||
const { writeMetadataFile } = require('../utils/ffmpegHelpers')
|
||||
const toneHelpers = require('../utils/toneHelpers')
|
||||
|
||||
class AudioMetadataMangaer {
|
||||
constructor(db, taskManager, emitter, clientEmitter) {
|
||||
constructor(db, taskManager) {
|
||||
this.db = db
|
||||
this.taskManager = taskManager
|
||||
this.emitter = emitter
|
||||
this.clientEmitter = clientEmitter
|
||||
}
|
||||
|
||||
updateMetadataForItem(user, libraryItem, useTone, forceEmbedChapters) {
|
||||
@ -40,7 +42,7 @@ class AudioMetadataMangaer {
|
||||
audioFiles: audioFiles.map(af => ({ index: af.index, ino: af.ino, filename: af.metadata.filename }))
|
||||
}
|
||||
|
||||
this.emitter('audio_metadata_started', itemAudioMetadataPayload)
|
||||
SocketAuthority.emitter('audio_metadata_started', itemAudioMetadataPayload)
|
||||
|
||||
// Write chapters file
|
||||
var toneJsonPath = null
|
||||
@ -67,7 +69,7 @@ class AudioMetadataMangaer {
|
||||
itemAudioMetadataPayload.results = results
|
||||
itemAudioMetadataPayload.elapsed = elapsed
|
||||
itemAudioMetadataPayload.finishedAt = Date.now()
|
||||
this.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
||||
SocketAuthority.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
||||
}
|
||||
|
||||
async updateAudioFileMetadataWithTone(libraryItemId, audioFile, toneJsonPath, itemCacheDir) {
|
||||
@ -77,7 +79,7 @@ class AudioMetadataMangaer {
|
||||
ino: audioFile.ino,
|
||||
filename: audioFile.metadata.filename
|
||||
}
|
||||
this.emitter('audiofile_metadata_started', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_started', resultPayload)
|
||||
|
||||
// Backup audio file
|
||||
try {
|
||||
@ -98,7 +100,7 @@ class AudioMetadataMangaer {
|
||||
Logger.info(`[AudioMetadataManager] Successfully tagged audio file "${audioFile.metadata.path}"`)
|
||||
}
|
||||
|
||||
this.emitter('audiofile_metadata_finished', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_finished', resultPayload)
|
||||
return resultPayload
|
||||
}
|
||||
|
||||
@ -115,7 +117,7 @@ class AudioMetadataMangaer {
|
||||
audioFiles: audioFiles.map(af => ({ index: af.index, ino: af.ino, filename: af.metadata.filename }))
|
||||
}
|
||||
|
||||
this.emitter('audio_metadata_started', itemAudioMetadataPayload)
|
||||
SocketAuthority.emitter('audio_metadata_started', itemAudioMetadataPayload)
|
||||
|
||||
var downloadsPath = Path.join(global.MetadataPath, 'downloads')
|
||||
var outputDir = Path.join(downloadsPath, libraryItem.id)
|
||||
@ -143,7 +145,7 @@ class AudioMetadataMangaer {
|
||||
itemAudioMetadataPayload.results = results
|
||||
itemAudioMetadataPayload.elapsed = elapsed
|
||||
itemAudioMetadataPayload.finishedAt = Date.now()
|
||||
this.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
||||
SocketAuthority.emitter('audio_metadata_finished', itemAudioMetadataPayload)
|
||||
}
|
||||
|
||||
updateAudioFileMetadataWithFfmpeg(libraryItemId, audioFile, outputDir, metadataFilePath, coverPath = '') {
|
||||
@ -154,7 +156,7 @@ class AudioMetadataMangaer {
|
||||
ino: audioFile.ino,
|
||||
filename: audioFile.metadata.filename
|
||||
}
|
||||
this.emitter('audiofile_metadata_started', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_started', resultPayload)
|
||||
|
||||
Logger.debug(`[AudioFileMetadataManager] Starting audio file metadata encode for "${audioFile.metadata.filename}"`)
|
||||
|
||||
@ -229,19 +231,19 @@ class AudioMetadataMangaer {
|
||||
Logger.debug(`[AudioFileMetadataManager] Audio file replaced successfully "${inputPath}"`)
|
||||
|
||||
resultPayload.success = true
|
||||
this.emitter('audiofile_metadata_finished', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_finished', resultPayload)
|
||||
resolve(resultPayload)
|
||||
}).catch((error) => {
|
||||
Logger.error(`[AudioFileMetadataManager] Audio file failed to move "${inputPath}"`, error)
|
||||
resultPayload.success = false
|
||||
this.emitter('audiofile_metadata_finished', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_finished', resultPayload)
|
||||
resolve(resultPayload)
|
||||
})
|
||||
} else {
|
||||
Logger.debug(`[AudioFileMetadataManager] Metadata encode FAILED for "${audioFile.metadata.filename}"`)
|
||||
|
||||
resultPayload.success = false
|
||||
this.emitter('audiofile_metadata_finished', resultPayload)
|
||||
SocketAuthority.emitter('audiofile_metadata_finished', resultPayload)
|
||||
resolve(resultPayload)
|
||||
}
|
||||
} else if (message.type === 'FFMPEG') {
|
||||
|
@ -1,4 +1,6 @@
|
||||
const Path = require('path')
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const cron = require('../libs/nodeCron')
|
||||
const fs = require('../libs/fsExtra')
|
||||
@ -8,18 +10,16 @@ const StreamZip = require('../libs/nodeStreamZip')
|
||||
// Utils
|
||||
const { getFileSize } = require('../utils/fileUtils')
|
||||
const filePerms = require('../utils/filePerms')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
const Backup = require('../objects/Backup')
|
||||
|
||||
class BackupManager {
|
||||
constructor(db, emitter) {
|
||||
constructor(db) {
|
||||
this.BackupPath = Path.join(global.MetadataPath, 'backups')
|
||||
this.ItemsMetadataPath = Path.join(global.MetadataPath, 'items')
|
||||
this.AuthorsMetadataPath = Path.join(global.MetadataPath, 'authors')
|
||||
|
||||
this.db = db
|
||||
this.emitter = emitter
|
||||
|
||||
this.scheduleTask = null
|
||||
|
||||
@ -130,7 +130,7 @@ class BackupManager {
|
||||
await zip.extract('metadata-authors/', this.AuthorsMetadataPath)
|
||||
}
|
||||
await this.db.reinit()
|
||||
this.emitter('backup_applied')
|
||||
SocketAuthority.emitter('backup_applied')
|
||||
}
|
||||
|
||||
async loadBackups() {
|
||||
|
@ -1,11 +1,11 @@
|
||||
const axios = require('axios')
|
||||
const Logger = require("../Logger")
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const { notificationData } = require('../utils/notifications')
|
||||
|
||||
class NotificationManager {
|
||||
constructor(db, emitter) {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
this.emitter = emitter
|
||||
|
||||
this.sendingNotification = false
|
||||
this.notificationQueue = []
|
||||
@ -58,7 +58,7 @@ class NotificationManager {
|
||||
}
|
||||
|
||||
await this.db.updateEntity('settings', this.db.notificationSettings)
|
||||
this.emitter('notifications_updated', this.db.notificationSettings)
|
||||
SocketAuthority.emitter('notifications_updated', this.db.notificationSettings)
|
||||
|
||||
this.notificationFinished()
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
const Path = require('path')
|
||||
const date = require('../libs/dateAndTime')
|
||||
const serverVersion = require('../../package.json').version
|
||||
const { PlayMethod } = require('../utils/constants')
|
||||
const PlaybackSession = require('../objects/PlaybackSession')
|
||||
const DeviceInfo = require('../objects/DeviceInfo')
|
||||
const Stream = require('../objects/Stream')
|
||||
const Logger = require('../Logger')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const date = require('../libs/dateAndTime')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const uaParserJs = require('../libs/uaParser')
|
||||
const requestIp = require('../libs/requestIp')
|
||||
|
||||
const { PlayMethod } = require('../utils/constants')
|
||||
|
||||
const PlaybackSession = require('../objects/PlaybackSession')
|
||||
const DeviceInfo = require('../objects/DeviceInfo')
|
||||
const Stream = require('../objects/Stream')
|
||||
|
||||
|
||||
class PlaybackSessionManager {
|
||||
constructor(db, emitter, clientEmitter) {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
this.StreamsPath = Path.join(global.MetadataPath, 'streams')
|
||||
this.emitter = emitter
|
||||
this.clientEmitter = clientEmitter
|
||||
|
||||
this.sessions = []
|
||||
this.localSessionLock = {}
|
||||
@ -98,7 +100,7 @@ class PlaybackSessionManager {
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('user', user)
|
||||
var itemProgress = user.getMediaProgress(session.libraryItemId, session.episodeId)
|
||||
this.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
id: itemProgress.id,
|
||||
data: itemProgress.toJSON()
|
||||
})
|
||||
@ -147,7 +149,7 @@ class PlaybackSessionManager {
|
||||
newPlaybackSession.playMethod = PlayMethod.DIRECTPLAY
|
||||
} else {
|
||||
Logger.debug(`[PlaybackSessionManager] "${user.username}" starting stream session for item "${libraryItem.id}"`)
|
||||
var stream = new Stream(newPlaybackSession.id, this.StreamsPath, user, libraryItem, episodeId, userStartTime, this.clientEmitter.bind(this))
|
||||
var stream = new Stream(newPlaybackSession.id, this.StreamsPath, user, libraryItem, episodeId, userStartTime)
|
||||
await stream.generatePlaylist()
|
||||
stream.start() // Start transcode
|
||||
|
||||
@ -167,7 +169,7 @@ class PlaybackSessionManager {
|
||||
user.currentSessionId = newPlaybackSession.id
|
||||
|
||||
this.sessions.push(newPlaybackSession)
|
||||
this.emitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
SocketAuthority.emitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
|
||||
return newPlaybackSession
|
||||
}
|
||||
@ -193,7 +195,7 @@ class PlaybackSessionManager {
|
||||
|
||||
await this.db.updateEntity('user', user)
|
||||
var itemProgress = user.getMediaProgress(session.libraryItemId, session.episodeId)
|
||||
this.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
id: itemProgress.id,
|
||||
data: itemProgress.toJSON()
|
||||
})
|
||||
@ -211,7 +213,7 @@ class PlaybackSessionManager {
|
||||
await this.saveSession(session)
|
||||
}
|
||||
Logger.debug(`[PlaybackSessionManager] closeSession "${session.id}"`)
|
||||
this.emitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
SocketAuthority.emitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
return this.removeSession(session.id)
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,24 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
const { getPodcastFeed } = require('../utils/podcastUtils')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
const { downloadFile, removeFile } = require('../utils/fileUtils')
|
||||
const filePerms = require('../utils/filePerms')
|
||||
const { levenshteinDistance } = require('../utils/index')
|
||||
const opmlParser = require('../utils/parsers/parseOPML')
|
||||
const prober = require('../utils/prober')
|
||||
|
||||
const LibraryFile = require('../objects/files/LibraryFile')
|
||||
const PodcastEpisodeDownload = require('../objects/PodcastEpisodeDownload')
|
||||
const PodcastEpisode = require('../objects/entities/PodcastEpisode')
|
||||
const AudioFile = require('../objects/files/AudioFile')
|
||||
|
||||
class PodcastManager {
|
||||
constructor(db, watcher, emitter, notificationManager) {
|
||||
constructor(db, watcher, notificationManager) {
|
||||
this.db = db
|
||||
this.watcher = watcher
|
||||
this.emitter = emitter
|
||||
this.notificationManager = notificationManager
|
||||
|
||||
this.downloadQueue = []
|
||||
@ -63,11 +64,11 @@ class PodcastManager {
|
||||
async startPodcastEpisodeDownload(podcastEpisodeDownload) {
|
||||
if (this.currentDownload) {
|
||||
this.downloadQueue.push(podcastEpisodeDownload)
|
||||
this.emitter('episode_download_queued', podcastEpisodeDownload.toJSONForClient())
|
||||
SocketAuthority.emitter('episode_download_queued', podcastEpisodeDownload.toJSONForClient())
|
||||
return
|
||||
}
|
||||
|
||||
this.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient())
|
||||
SocketAuthority.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient())
|
||||
this.currentDownload = podcastEpisodeDownload
|
||||
|
||||
// Ignores all added files to this dir
|
||||
@ -97,7 +98,7 @@ class PodcastManager {
|
||||
this.currentDownload.setFinished(false)
|
||||
}
|
||||
|
||||
this.emitter('episode_download_finished', this.currentDownload.toJSONForClient())
|
||||
SocketAuthority.emitter('episode_download_finished', this.currentDownload.toJSONForClient())
|
||||
|
||||
this.watcher.removeIgnoreDir(this.currentDownload.libraryItem.path)
|
||||
this.currentDownload = null
|
||||
@ -141,7 +142,7 @@ class PodcastManager {
|
||||
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
|
||||
if (this.currentDownload.isAutoDownload) { // Notifications only for auto downloaded episodes
|
||||
this.notificationManager.onPodcastEpisodeDownloaded(libraryItem, podcastEpisode)
|
||||
@ -230,7 +231,7 @@ class PodcastManager {
|
||||
libraryItem.media.lastEpisodeCheck = Date.now()
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
return libraryItem.media.autoDownloadEpisodes
|
||||
}
|
||||
|
||||
@ -269,7 +270,7 @@ class PodcastManager {
|
||||
libraryItem.media.lastEpisodeCheck = Date.now()
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
|
||||
return newEpisodes
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
const Path = require('path')
|
||||
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Feed = require('../objects/Feed')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
// Not functional at the moment
|
||||
class RssFeedManager {
|
||||
constructor(db, emitter) {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
this.emitter = emitter
|
||||
|
||||
this.feeds = {}
|
||||
}
|
||||
|
||||
@ -104,7 +106,7 @@ class RssFeedManager {
|
||||
|
||||
Logger.debug(`[RssFeedManager] Opened RSS feed ${feed.feedUrl}`)
|
||||
await this.db.insertEntity('feed', feed)
|
||||
this.emitter('rss_feed_open', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl })
|
||||
SocketAuthority.emitter('rss_feed_open', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl })
|
||||
return feed
|
||||
}
|
||||
|
||||
@ -118,7 +120,7 @@ class RssFeedManager {
|
||||
if (!this.feeds[id]) return
|
||||
var feed = this.feeds[id]
|
||||
await this.db.removeEntity('feed', id)
|
||||
this.emitter('rss_feed_closed', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl })
|
||||
SocketAuthority.emitter('rss_feed_closed', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl })
|
||||
delete this.feeds[id]
|
||||
Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`)
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
class TaskManager {
|
||||
constructor(emitter) {
|
||||
this.emitter = emitter
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
class TaskManager {
|
||||
constructor() {
|
||||
this.tasks = []
|
||||
}
|
||||
|
||||
addTask(task) {
|
||||
this.tasks.push(task)
|
||||
this.emitter('task_started', task.toJSON())
|
||||
SocketAuthority.emitter('task_started', task.toJSON())
|
||||
}
|
||||
|
||||
taskFinished(task) {
|
||||
if (this.tasks.some(t => t.id === task.id)) {
|
||||
this.tasks = this.tasks.filter(t => t.id !== task.id)
|
||||
this.emitter('task_finished', task.toJSON())
|
||||
SocketAuthority.emitter('task_finished', task.toJSON())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
const Ffmpeg = require('../libs/fluentFfmpeg')
|
||||
|
||||
const EventEmitter = require('events')
|
||||
const Path = require('path')
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Ffmpeg = require('../libs/fluentFfmpeg')
|
||||
|
||||
const { secondsToTimestamp } = require('../utils/index')
|
||||
const { writeConcatFile } = require('../utils/ffmpegHelpers')
|
||||
const { AudioMimeType } = require('../utils/constants')
|
||||
@ -10,14 +14,13 @@ const hlsPlaylistGenerator = require('../utils/hlsPlaylistGenerator')
|
||||
const AudioTrack = require('./files/AudioTrack')
|
||||
|
||||
class Stream extends EventEmitter {
|
||||
constructor(sessionId, streamPath, user, libraryItem, episodeId, startTime, clientEmitter, transcodeOptions = {}) {
|
||||
constructor(sessionId, streamPath, user, libraryItem, episodeId, startTime, transcodeOptions = {}) {
|
||||
super()
|
||||
|
||||
this.id = sessionId
|
||||
this.user = user
|
||||
this.libraryItem = libraryItem
|
||||
this.episodeId = episodeId
|
||||
this.clientEmitter = clientEmitter
|
||||
|
||||
this.transcodeOptions = transcodeOptions
|
||||
|
||||
@ -408,7 +411,7 @@ class Stream extends EventEmitter {
|
||||
}
|
||||
|
||||
clientEmit(evtName, data) {
|
||||
if (this.clientEmitter) this.clientEmitter(this.user.id, evtName, data)
|
||||
SocketAuthority.clientEmitter(this.user.id, evtName, data)
|
||||
}
|
||||
|
||||
getAudioTrack() {
|
||||
|
@ -1,8 +1,11 @@
|
||||
const express = require('express')
|
||||
const Path = require('path')
|
||||
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
const date = require('../libs/dateAndTime')
|
||||
const Logger = require('../Logger')
|
||||
|
||||
const LibraryController = require('../controllers/LibraryController')
|
||||
const UserController = require('../controllers/UserController')
|
||||
@ -29,25 +32,22 @@ const Author = require('../objects/entities/Author')
|
||||
const Series = require('../objects/entities/Series')
|
||||
|
||||
class ApiRouter {
|
||||
constructor(db, auth, scanner, playbackSessionManager, abMergeManager, coverManager, backupManager, watcher, cacheManager, podcastManager, audioMetadataManager, rssFeedManager, cronManager, notificationManager, taskManager, getUsersOnline, emitter, clientEmitter) {
|
||||
this.db = db
|
||||
this.auth = auth
|
||||
this.scanner = scanner
|
||||
this.playbackSessionManager = playbackSessionManager
|
||||
this.abMergeManager = abMergeManager
|
||||
this.backupManager = backupManager
|
||||
this.coverManager = coverManager
|
||||
this.watcher = watcher
|
||||
this.cacheManager = cacheManager
|
||||
this.podcastManager = podcastManager
|
||||
this.audioMetadataManager = audioMetadataManager
|
||||
this.rssFeedManager = rssFeedManager
|
||||
this.cronManager = cronManager
|
||||
this.notificationManager = notificationManager
|
||||
this.taskManager = taskManager
|
||||
this.getUsersOnline = getUsersOnline
|
||||
this.emitter = emitter
|
||||
this.clientEmitter = clientEmitter
|
||||
constructor(Server) {
|
||||
this.db = Server.db
|
||||
this.auth = Server.auth
|
||||
this.scanner = Server.scanner
|
||||
this.playbackSessionManager = Server.playbackSessionManager
|
||||
this.abMergeManager = Server.abMergeManager
|
||||
this.backupManager = Server.backupManager
|
||||
this.coverManager = Server.coverManager
|
||||
this.watcher = Server.watcher
|
||||
this.cacheManager = Server.cacheManager
|
||||
this.podcastManager = Server.podcastManager
|
||||
this.audioMetadataManager = Server.audioMetadataManager
|
||||
this.rssFeedManager = Server.rssFeedManager
|
||||
this.cronManager = Server.cronManager
|
||||
this.notificationManager = Server.notificationManager
|
||||
this.taskManager = Server.taskManager
|
||||
|
||||
this.bookFinder = new BookFinder()
|
||||
this.authorFinder = new AuthorFinder()
|
||||
@ -353,7 +353,7 @@ class ApiRouter {
|
||||
var collection = collectionsWithBook[i]
|
||||
collection.removeBook(libraryItem.id)
|
||||
await this.db.updateEntity('collection', collection)
|
||||
this.clientEmitter(collection.userId, 'collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
SocketAuthority.clientEmitter(collection.userId, 'collection_updated', collection.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
|
||||
// purge cover cache
|
||||
@ -363,7 +363,7 @@ class ApiRouter {
|
||||
|
||||
var json = libraryItem.toJSONExpanded()
|
||||
await this.db.removeLibraryItem(libraryItem.id)
|
||||
this.emitter('item_removed', json)
|
||||
SocketAuthority.emitter('item_removed', json)
|
||||
}
|
||||
|
||||
async getUserListeningSessionsHelper(userId) {
|
||||
@ -454,7 +454,7 @@ class ApiRouter {
|
||||
}
|
||||
if (newAuthors.length) {
|
||||
await this.db.insertEntities('author', newAuthors)
|
||||
this.emitter('authors_added', newAuthors)
|
||||
SocketAuthority.emitter('authors_added', newAuthors)
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,7 +478,7 @@ class ApiRouter {
|
||||
}
|
||||
if (newSeries.length) {
|
||||
await this.db.insertEntities('series', newSeries)
|
||||
this.emitter('authors_added', newSeries)
|
||||
SocketAuthority.emitter('authors_added', newSeries)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
const express = require('express')
|
||||
const Path = require('path')
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
|
||||
class HlsRouter {
|
||||
constructor(db, auth, playbackSessionManager, emitter) {
|
||||
constructor(db, auth, playbackSessionManager) {
|
||||
this.db = db
|
||||
this.auth = auth
|
||||
this.playbackSessionManager = playbackSessionManager
|
||||
this.emitter = emitter
|
||||
|
||||
this.router = express()
|
||||
this.init()
|
||||
@ -49,7 +52,7 @@ class HlsRouter {
|
||||
if (startTimeForReset) {
|
||||
// HLS.js will restart the stream at the new time
|
||||
Logger.info(`[HlsRouter] Resetting Stream - notify client @${startTimeForReset}s`)
|
||||
this.emitter('stream_reset', {
|
||||
SocketAuthority.emitter('stream_reset', {
|
||||
startTime: startTimeForReset,
|
||||
streamId: stream.id
|
||||
})
|
||||
|
@ -1,8 +1,9 @@
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Path = require('path')
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
// Utils
|
||||
const Logger = require('../Logger')
|
||||
const { groupFilesIntoLibraryItemPaths, getLibraryItemFileData, scanFolder } = require('../utils/scandir')
|
||||
const { comparePaths } = require('../utils/index')
|
||||
const { getIno } = require('../utils/fileUtils')
|
||||
@ -20,12 +21,11 @@ const Author = require('../objects/entities/Author')
|
||||
const Series = require('../objects/entities/Series')
|
||||
|
||||
class Scanner {
|
||||
constructor(db, coverManager, emitter) {
|
||||
constructor(db, coverManager) {
|
||||
this.ScanLogPath = Path.posix.join(global.MetadataPath, 'logs', 'scans')
|
||||
|
||||
this.db = db
|
||||
this.coverManager = coverManager
|
||||
this.emitter = emitter
|
||||
|
||||
this.cancelLibraryScan = {}
|
||||
this.librariesScanning = []
|
||||
@ -113,7 +113,7 @@ class Scanner {
|
||||
}
|
||||
|
||||
if (hasUpdated) {
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
return ScanResult.UPDATED
|
||||
}
|
||||
@ -139,7 +139,7 @@ class Scanner {
|
||||
libraryScan.verbose = false
|
||||
this.librariesScanning.push(libraryScan.getScanEmitData)
|
||||
|
||||
this.emitter('scan_start', libraryScan.getScanEmitData)
|
||||
SocketAuthority.emitter('scan_start', libraryScan.getScanEmitData)
|
||||
|
||||
Logger.info(`[Scanner] Starting library scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
||||
|
||||
@ -158,11 +158,11 @@ class Scanner {
|
||||
if (canceled && !libraryScan.totalResults) {
|
||||
var emitData = libraryScan.getScanEmitData
|
||||
emitData.results = null
|
||||
this.emitter('scan_complete', emitData)
|
||||
SocketAuthority.emitter('scan_complete', emitData)
|
||||
return
|
||||
}
|
||||
|
||||
this.emitter('scan_complete', libraryScan.getScanEmitData)
|
||||
SocketAuthority.emitter('scan_complete', libraryScan.getScanEmitData)
|
||||
|
||||
if (libraryScan.totalResults) {
|
||||
libraryScan.saveLog(this.ScanLogPath)
|
||||
@ -302,7 +302,7 @@ class Scanner {
|
||||
|
||||
async updateLibraryItemChunk(itemsToUpdate) {
|
||||
await this.db.updateLibraryItems(itemsToUpdate)
|
||||
this.emitter('items_updated', itemsToUpdate.map(li => li.toJSONExpanded()))
|
||||
SocketAuthority.emitter('items_updated', itemsToUpdate.map(li => li.toJSONExpanded()))
|
||||
}
|
||||
|
||||
async rescanLibraryItemDataChunk(itemDataToRescan, libraryScan) {
|
||||
@ -320,7 +320,7 @@ class Scanner {
|
||||
if (itemsUpdated.length) {
|
||||
libraryScan.resultsUpdated += itemsUpdated.length
|
||||
await this.db.updateLibraryItems(itemsUpdated)
|
||||
this.emitter('items_updated', itemsUpdated.map(li => li.toJSONExpanded()))
|
||||
SocketAuthority.emitter('items_updated', itemsUpdated.map(li => li.toJSONExpanded()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,7 +337,7 @@ class Scanner {
|
||||
|
||||
libraryScan.resultsAdded += newLibraryItems.length
|
||||
await this.db.insertLibraryItems(newLibraryItems)
|
||||
this.emitter('items_added', newLibraryItems.map(li => li.toJSONExpanded()))
|
||||
SocketAuthority.emitter('items_added', newLibraryItems.map(li => li.toJSONExpanded()))
|
||||
}
|
||||
|
||||
async rescanLibraryItem(libraryItemCheckData, libraryScan) {
|
||||
@ -458,7 +458,7 @@ class Scanner {
|
||||
})
|
||||
if (newAuthors.length) {
|
||||
await this.db.insertEntities('author', newAuthors)
|
||||
this.emitter('authors_added', newAuthors.map(au => au.toJSON()))
|
||||
SocketAuthority.emitter('authors_added', newAuthors.map(au => au.toJSON()))
|
||||
}
|
||||
}
|
||||
if (libraryItem.media.metadata.series.some(se => se.id.startsWith('new'))) {
|
||||
@ -479,7 +479,7 @@ class Scanner {
|
||||
})
|
||||
if (newSeries.length) {
|
||||
await this.db.insertEntities('series', newSeries)
|
||||
this.emitter('series_added', newSeries.map(se => se.toJSON()))
|
||||
SocketAuthority.emitter('series_added', newSeries.map(se => se.toJSON()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -602,7 +602,7 @@ class Scanner {
|
||||
Logger.info(`[Scanner] Scanning file update group and library item was deleted "${existingLibraryItem.media.metadata.title}" - marking as missing`)
|
||||
existingLibraryItem.setMissing()
|
||||
await this.db.updateLibraryItem(existingLibraryItem)
|
||||
this.emitter('item_updated', existingLibraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', existingLibraryItem.toJSONExpanded())
|
||||
|
||||
itemGroupingResults[itemDir] = ScanResult.REMOVED
|
||||
continue;
|
||||
@ -629,7 +629,7 @@ class Scanner {
|
||||
if (newLibraryItem) {
|
||||
await this.createNewAuthorsAndSeries(newLibraryItem)
|
||||
await this.db.insertLibraryItem(newLibraryItem)
|
||||
this.emitter('item_added', newLibraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_added', newLibraryItem.toJSONExpanded())
|
||||
}
|
||||
itemGroupingResults[itemDir] = newLibraryItem ? ScanResult.ADDED : ScanResult.NOTHING
|
||||
}
|
||||
@ -747,7 +747,7 @@ class Scanner {
|
||||
}
|
||||
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
this.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
}
|
||||
|
||||
return {
|
||||
@ -846,7 +846,7 @@ class Scanner {
|
||||
author = new Author()
|
||||
author.setData({ name: authorName })
|
||||
await this.db.insertEntity('author', author)
|
||||
this.emitter('author_added', author)
|
||||
SocketAuthority.emitter('author_added', author)
|
||||
}
|
||||
authorPayload.push(author.toJSONMinimal())
|
||||
}
|
||||
@ -864,7 +864,7 @@ class Scanner {
|
||||
seriesItem = new Series()
|
||||
seriesItem.setData({ name: seriesMatchItem.series })
|
||||
await this.db.insertEntity('series', seriesItem)
|
||||
this.emitter('series_added', seriesItem)
|
||||
SocketAuthority.emitter('series_added', seriesItem)
|
||||
}
|
||||
seriesPayload.push(seriesItem.toJSONMinimal(seriesMatchItem.sequence))
|
||||
}
|
||||
@ -955,7 +955,7 @@ class Scanner {
|
||||
var libraryScan = new LibraryScan()
|
||||
libraryScan.setData(library, null, 'match')
|
||||
this.librariesScanning.push(libraryScan.getScanEmitData)
|
||||
this.emitter('scan_start', libraryScan.getScanEmitData)
|
||||
SocketAuthority.emitter('scan_start', libraryScan.getScanEmitData)
|
||||
|
||||
Logger.info(`[Scanner] matchLibraryItems: Starting library match scan ${libraryScan.id} for ${libraryScan.libraryName}`)
|
||||
|
||||
@ -987,14 +987,14 @@ class Scanner {
|
||||
delete this.cancelLibraryScan[libraryScan.libraryId]
|
||||
var scanData = libraryScan.getScanEmitData
|
||||
scanData.results = false
|
||||
this.emitter('scan_complete', scanData)
|
||||
SocketAuthority.emitter('scan_complete', scanData)
|
||||
this.librariesScanning = this.librariesScanning.filter(ls => ls.id !== library.id)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.librariesScanning = this.librariesScanning.filter(ls => ls.id !== library.id)
|
||||
this.emitter('scan_complete', libraryScan.getScanEmitData)
|
||||
SocketAuthority.emitter('scan_complete', libraryScan.getScanEmitData)
|
||||
}
|
||||
|
||||
probeAudioFileWithTone(audioFile) {
|
||||
|
Loading…
Reference in New Issue
Block a user