mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-24 12:49:38 +00:00
Init sqlite take 2
This commit is contained in:
parent
d86a3b3dc2
commit
cf7fd315b6
88 changed files with 7017 additions and 692 deletions
|
|
@ -10,8 +10,7 @@ const { writeConcatFile } = require('../utils/ffmpegHelpers')
|
|||
const toneHelpers = require('../utils/toneHelpers')
|
||||
|
||||
class AbMergeManager {
|
||||
constructor(db, taskManager) {
|
||||
this.db = db
|
||||
constructor(taskManager) {
|
||||
this.taskManager = taskManager
|
||||
|
||||
this.itemsCacheDir = Path.join(global.MetadataPath, 'cache/items')
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ const toneHelpers = require('../utils/toneHelpers')
|
|||
const Task = require('../objects/Task')
|
||||
|
||||
class AudioMetadataMangaer {
|
||||
constructor(db, taskManager) {
|
||||
this.db = db
|
||||
constructor(taskManager) {
|
||||
this.taskManager = taskManager
|
||||
|
||||
this.itemsCacheDir = Path.join(global.MetadataPath, 'cache/items')
|
||||
|
|
|
|||
|
|
@ -10,15 +10,14 @@ const { downloadFile, filePathToPOSIX } = require('../utils/fileUtils')
|
|||
const { extractCoverArt } = require('../utils/ffmpegHelpers')
|
||||
|
||||
class CoverManager {
|
||||
constructor(db, cacheManager) {
|
||||
this.db = db
|
||||
constructor(cacheManager) {
|
||||
this.cacheManager = cacheManager
|
||||
|
||||
this.ItemMetadataPath = Path.posix.join(global.MetadataPath, 'items')
|
||||
}
|
||||
|
||||
getCoverDirectory(libraryItem) {
|
||||
if (this.db.serverSettings.storeCoverWithItem && !libraryItem.isFile && !libraryItem.isMusic) {
|
||||
if (global.ServerSettings.storeCoverWithItem && !libraryItem.isFile && !libraryItem.isMusic) {
|
||||
return libraryItem.path
|
||||
} else {
|
||||
return Path.posix.join(this.ItemMetadataPath, libraryItem.id)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
const cron = require('../libs/nodeCron')
|
||||
const Logger = require('../Logger')
|
||||
const Database = require('../Database')
|
||||
|
||||
class CronManager {
|
||||
constructor(db, scanner, podcastManager) {
|
||||
this.db = db
|
||||
constructor(scanner, podcastManager) {
|
||||
this.scanner = scanner
|
||||
this.podcastManager = podcastManager
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ class CronManager {
|
|||
}
|
||||
|
||||
initLibraryScanCrons() {
|
||||
for (const library of this.db.libraries) {
|
||||
for (const library of Database.libraries) {
|
||||
if (library.settings.autoScanCronExpression) {
|
||||
this.startCronForLibrary(library)
|
||||
}
|
||||
|
|
@ -64,7 +64,7 @@ class CronManager {
|
|||
|
||||
initPodcastCrons() {
|
||||
const cronExpressionMap = {}
|
||||
this.db.libraryItems.forEach((li) => {
|
||||
Database.libraryItems.forEach((li) => {
|
||||
if (li.mediaType === 'podcast' && li.media.autoDownloadEpisodes) {
|
||||
if (!li.media.autoDownloadSchedule) {
|
||||
Logger.error(`[CronManager] Podcast auto download schedule is not set for ${li.media.metadata.title}`)
|
||||
|
|
@ -119,7 +119,7 @@ class CronManager {
|
|||
// Get podcast library items to check
|
||||
const libraryItems = []
|
||||
for (const libraryItemId of libraryItemIds) {
|
||||
const libraryItem = this.db.libraryItems.find(li => li.id === libraryItemId)
|
||||
const libraryItem = Database.libraryItems.find(li => li.id === libraryItemId)
|
||||
if (!libraryItem) {
|
||||
Logger.error(`[CronManager] Library item ${libraryItemId} not found for episode check cron ${expression}`)
|
||||
podcastCron.libraryItemIds = podcastCron.libraryItemIds.filter(lid => lid !== libraryItemId) // Filter it out
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
const nodemailer = require('nodemailer')
|
||||
const Logger = require("../Logger")
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
class EmailManager {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
}
|
||||
constructor() { }
|
||||
|
||||
getTransporter() {
|
||||
return nodemailer.createTransport(this.db.emailSettings.getTransportObject())
|
||||
return nodemailer.createTransport(Database.emailSettings.getTransportObject())
|
||||
}
|
||||
|
||||
async sendTest(res) {
|
||||
|
|
@ -25,8 +22,8 @@ class EmailManager {
|
|||
}
|
||||
|
||||
transporter.sendMail({
|
||||
from: this.db.emailSettings.fromAddress,
|
||||
to: this.db.emailSettings.testAddress || this.db.emailSettings.fromAddress,
|
||||
from: Database.emailSettings.fromAddress,
|
||||
to: Database.emailSettings.testAddress || Database.emailSettings.fromAddress,
|
||||
subject: 'Test email from Audiobookshelf',
|
||||
text: 'Success!'
|
||||
}).then((result) => {
|
||||
|
|
@ -52,7 +49,7 @@ class EmailManager {
|
|||
}
|
||||
|
||||
transporter.sendMail({
|
||||
from: this.db.emailSettings.fromAddress,
|
||||
from: Database.emailSettings.fromAddress,
|
||||
to: device.email,
|
||||
subject: "Here is your Ebook!",
|
||||
html: '<div dir="auto"></div>',
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ const Logger = require('../Logger')
|
|||
const TAG = '[LogManager]'
|
||||
|
||||
class LogManager {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
|
||||
constructor() {
|
||||
this.DailyLogPath = Path.posix.join(global.MetadataPath, 'logs', 'daily')
|
||||
this.ScanLogPath = Path.posix.join(global.MetadataPath, 'logs', 'scans')
|
||||
|
||||
|
|
@ -20,12 +18,8 @@ class LogManager {
|
|||
this.dailyLogFiles = []
|
||||
}
|
||||
|
||||
get serverSettings() {
|
||||
return this.db.serverSettings || {}
|
||||
}
|
||||
|
||||
get loggerDailyLogsToKeep() {
|
||||
return this.serverSettings.loggerDailyLogsToKeep || 7
|
||||
return global.ServerSettings.loggerDailyLogsToKeep || 7
|
||||
}
|
||||
|
||||
async ensureLogDirs() {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
const axios = require('axios')
|
||||
const Logger = require("../Logger")
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Database = require('../Database')
|
||||
const { notificationData } = require('../utils/notifications')
|
||||
|
||||
class NotificationManager {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
|
||||
constructor() {
|
||||
this.sendingNotification = false
|
||||
this.notificationQueue = []
|
||||
}
|
||||
|
|
@ -16,10 +15,10 @@ class NotificationManager {
|
|||
}
|
||||
|
||||
onPodcastEpisodeDownloaded(libraryItem, episode) {
|
||||
if (!this.db.notificationSettings.isUseable) return
|
||||
if (!Database.notificationSettings.isUseable) return
|
||||
|
||||
Logger.debug(`[NotificationManager] onPodcastEpisodeDownloaded: Episode "${episode.title}" for podcast ${libraryItem.media.metadata.title}`)
|
||||
const library = this.db.libraries.find(lib => lib.id === libraryItem.libraryId)
|
||||
const library = Database.libraries.find(lib => lib.id === libraryItem.libraryId)
|
||||
const eventData = {
|
||||
libraryItemId: libraryItem.id,
|
||||
libraryId: libraryItem.libraryId,
|
||||
|
|
@ -42,19 +41,19 @@ class NotificationManager {
|
|||
}
|
||||
|
||||
async triggerNotification(eventName, eventData, intentionallyFail = false) {
|
||||
if (!this.db.notificationSettings.isUseable) return
|
||||
if (!Database.notificationSettings.isUseable) return
|
||||
|
||||
// Will queue the notification if sendingNotification and queue is not full
|
||||
if (!this.checkTriggerNotification(eventName, eventData)) return
|
||||
|
||||
const notifications = this.db.notificationSettings.getActiveNotificationsForEvent(eventName)
|
||||
const notifications = Database.notificationSettings.getActiveNotificationsForEvent(eventName)
|
||||
for (const notification of notifications) {
|
||||
Logger.debug(`[NotificationManager] triggerNotification: Sending ${eventName} notification ${notification.id}`)
|
||||
const success = intentionallyFail ? false : await this.sendNotification(notification, eventData)
|
||||
|
||||
notification.updateNotificationFired(success)
|
||||
if (!success) { // Failed notification
|
||||
if (notification.numConsecutiveFailedAttempts >= this.db.notificationSettings.maxFailedAttempts) {
|
||||
if (notification.numConsecutiveFailedAttempts >= Database.notificationSettings.maxFailedAttempts) {
|
||||
Logger.error(`[NotificationManager] triggerNotification: ${notification.eventName}/${notification.id} reached max failed attempts`)
|
||||
notification.enabled = false
|
||||
} else {
|
||||
|
|
@ -63,8 +62,8 @@ class NotificationManager {
|
|||
}
|
||||
}
|
||||
|
||||
await this.db.updateEntity('settings', this.db.notificationSettings)
|
||||
SocketAuthority.emitter('notifications_updated', this.db.notificationSettings.toJSON())
|
||||
await Database.updateSetting(Database.notificationSettings)
|
||||
SocketAuthority.emitter('notifications_updated', Database.notificationSettings.toJSON())
|
||||
|
||||
this.notificationFinished()
|
||||
}
|
||||
|
|
@ -72,7 +71,7 @@ class NotificationManager {
|
|||
// Return TRUE if notification should be triggered now
|
||||
checkTriggerNotification(eventName, eventData) {
|
||||
if (this.sendingNotification) {
|
||||
if (this.notificationQueue.length >= this.db.notificationSettings.maxNotificationQueue) {
|
||||
if (this.notificationQueue.length >= Database.notificationSettings.maxNotificationQueue) {
|
||||
Logger.warn(`[NotificationManager] Notification queue is full - ignoring event ${eventName}`)
|
||||
} else {
|
||||
Logger.debug(`[NotificationManager] Queueing notification ${eventName} (Queue size: ${this.notificationQueue.length})`)
|
||||
|
|
@ -92,7 +91,7 @@ class NotificationManager {
|
|||
const nextNotificationEvent = this.notificationQueue.shift()
|
||||
this.triggerNotification(nextNotificationEvent.eventName, nextNotificationEvent.eventData)
|
||||
}
|
||||
}, this.db.notificationSettings.notificationDelay)
|
||||
}, Database.notificationSettings.notificationDelay)
|
||||
}
|
||||
|
||||
sendTestNotification(notification) {
|
||||
|
|
@ -107,7 +106,7 @@ class NotificationManager {
|
|||
|
||||
sendNotification(notification, eventData) {
|
||||
const payload = notification.getApprisePayload(eventData)
|
||||
return axios.post(this.db.notificationSettings.appriseApiUrl, payload, { timeout: 6000 }).then((response) => {
|
||||
return axios.post(Database.notificationSettings.appriseApiUrl, payload, { timeout: 6000 }).then((response) => {
|
||||
Logger.debug(`[NotificationManager] sendNotification: ${notification.eventName}/${notification.id} response=`, response.data)
|
||||
return true
|
||||
}).catch((error) => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const Path = require('path')
|
|||
const serverVersion = require('../../package.json').version
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Database = require('../Database')
|
||||
|
||||
const date = require('../libs/dateAndTime')
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
|
@ -15,8 +16,7 @@ const DeviceInfo = require('../objects/DeviceInfo')
|
|||
const Stream = require('../objects/Stream')
|
||||
|
||||
class PlaybackSessionManager {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
constructor() {
|
||||
this.StreamsPath = Path.join(global.MetadataPath, 'streams')
|
||||
|
||||
this.sessions = []
|
||||
|
|
@ -33,19 +33,31 @@ class PlaybackSessionManager {
|
|||
return session?.stream || null
|
||||
}
|
||||
|
||||
getDeviceInfo(req) {
|
||||
async getDeviceInfo(req) {
|
||||
const ua = uaParserJs(req.headers['user-agent'])
|
||||
const ip = requestIp.getClientIp(req)
|
||||
|
||||
const clientDeviceInfo = req.body?.deviceInfo || null
|
||||
|
||||
const deviceInfo = new DeviceInfo()
|
||||
deviceInfo.setData(ip, ua, clientDeviceInfo, serverVersion)
|
||||
deviceInfo.setData(ip, ua, clientDeviceInfo, serverVersion, req.user.id)
|
||||
|
||||
if (clientDeviceInfo?.deviceId) {
|
||||
const existingDevice = await Database.getDeviceByDeviceId(clientDeviceInfo.deviceId)
|
||||
if (existingDevice) {
|
||||
if (existingDevice.update(deviceInfo)) {
|
||||
await Database.updateDevice(existingDevice)
|
||||
}
|
||||
return existingDevice
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return deviceInfo
|
||||
}
|
||||
|
||||
async startSessionRequest(req, res, episodeId) {
|
||||
const deviceInfo = this.getDeviceInfo(req)
|
||||
const deviceInfo = await this.getDeviceInfo(req)
|
||||
Logger.debug(`[PlaybackSessionManager] startSessionRequest for device ${deviceInfo.deviceDescription}`)
|
||||
const { user, libraryItem, body: options } = req
|
||||
const session = await this.startSession(user, deviceInfo, libraryItem, episodeId, options)
|
||||
|
|
@ -77,7 +89,7 @@ class PlaybackSessionManager {
|
|||
}
|
||||
|
||||
async syncLocalSession(user, sessionJson) {
|
||||
const libraryItem = this.db.getLibraryItem(sessionJson.libraryItemId)
|
||||
const libraryItem = Database.getLibraryItem(sessionJson.libraryItemId)
|
||||
const episode = (sessionJson.episodeId && libraryItem && libraryItem.isPodcast) ? libraryItem.media.getEpisode(sessionJson.episodeId) : null
|
||||
if (!libraryItem || (libraryItem.isPodcast && !episode)) {
|
||||
Logger.error(`[PlaybackSessionManager] syncLocalSession: Media item not found for session "${sessionJson.displayTitle}" (${sessionJson.id})`)
|
||||
|
|
@ -88,12 +100,12 @@ class PlaybackSessionManager {
|
|||
}
|
||||
}
|
||||
|
||||
let session = await this.db.getPlaybackSession(sessionJson.id)
|
||||
let session = await Database.getPlaybackSession(sessionJson.id)
|
||||
if (!session) {
|
||||
// New session from local
|
||||
session = new PlaybackSession(sessionJson)
|
||||
Logger.debug(`[PlaybackSessionManager] Inserting new session for "${session.displayTitle}" (${session.id})`)
|
||||
await this.db.insertEntity('session', session)
|
||||
await Database.createPlaybackSession(session)
|
||||
} else {
|
||||
session.currentTime = sessionJson.currentTime
|
||||
session.timeListening = sessionJson.timeListening
|
||||
|
|
@ -102,7 +114,7 @@ class PlaybackSessionManager {
|
|||
session.dayOfWeek = date.format(new Date(), 'dddd')
|
||||
|
||||
Logger.debug(`[PlaybackSessionManager] Updated session for "${session.displayTitle}" (${session.id})`)
|
||||
await this.db.updateEntity('session', session)
|
||||
await Database.updatePlaybackSession(session)
|
||||
}
|
||||
|
||||
const result = {
|
||||
|
|
@ -126,8 +138,8 @@ class PlaybackSessionManager {
|
|||
|
||||
// Update user and emit socket event
|
||||
if (result.progressSynced) {
|
||||
await this.db.updateEntity('user', user)
|
||||
const itemProgress = user.getMediaProgress(session.libraryItemId, session.episodeId)
|
||||
if (itemProgress) await Database.upsertMediaProgress(itemProgress)
|
||||
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
id: itemProgress.id,
|
||||
sessionId: session.id,
|
||||
|
|
@ -155,7 +167,7 @@ class PlaybackSessionManager {
|
|||
|
||||
async startSession(user, deviceInfo, libraryItem, episodeId, options) {
|
||||
// Close any sessions already open for user and device
|
||||
const userSessions = this.sessions.filter(playbackSession => playbackSession.userId === user.id && playbackSession.deviceId === deviceInfo.deviceId)
|
||||
const userSessions = this.sessions.filter(playbackSession => playbackSession.userId === user.id && playbackSession.deviceId === deviceInfo.id)
|
||||
for (const session of userSessions) {
|
||||
Logger.info(`[PlaybackSessionManager] startSession: Closing open session "${session.displayTitle}" for user "${user.username}" (Device: ${session.deviceDescription})`)
|
||||
await this.closeSession(user, session, null)
|
||||
|
|
@ -213,13 +225,13 @@ class PlaybackSessionManager {
|
|||
user.currentSessionId = newPlaybackSession.id
|
||||
|
||||
this.sessions.push(newPlaybackSession)
|
||||
SocketAuthority.adminEmitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
SocketAuthority.adminEmitter('user_stream_update', user.toJSONForPublic(this.sessions, Database.libraryItems))
|
||||
|
||||
return newPlaybackSession
|
||||
}
|
||||
|
||||
async syncSession(user, session, syncData) {
|
||||
const libraryItem = this.db.libraryItems.find(li => li.id === session.libraryItemId)
|
||||
const libraryItem = Database.libraryItems.find(li => li.id === session.libraryItemId)
|
||||
if (!libraryItem) {
|
||||
Logger.error(`[PlaybackSessionManager] syncSession Library Item not found "${session.libraryItemId}"`)
|
||||
return null
|
||||
|
|
@ -236,9 +248,8 @@ class PlaybackSessionManager {
|
|||
}
|
||||
const wasUpdated = user.createUpdateMediaProgress(libraryItem, itemProgressUpdate, session.episodeId)
|
||||
if (wasUpdated) {
|
||||
|
||||
await this.db.updateEntity('user', user)
|
||||
const itemProgress = user.getMediaProgress(session.libraryItemId, session.episodeId)
|
||||
if (itemProgress) await Database.upsertMediaProgress(itemProgress)
|
||||
SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', {
|
||||
id: itemProgress.id,
|
||||
sessionId: session.id,
|
||||
|
|
@ -259,7 +270,7 @@ class PlaybackSessionManager {
|
|||
await this.saveSession(session)
|
||||
}
|
||||
Logger.debug(`[PlaybackSessionManager] closeSession "${session.id}"`)
|
||||
SocketAuthority.adminEmitter('user_stream_update', user.toJSONForPublic(this.sessions, this.db.libraryItems))
|
||||
SocketAuthority.adminEmitter('user_stream_update', user.toJSONForPublic(this.sessions, Database.libraryItems))
|
||||
SocketAuthority.clientEmitter(session.userId, 'user_session_closed', session.id)
|
||||
return this.removeSession(session.id)
|
||||
}
|
||||
|
|
@ -268,10 +279,10 @@ class PlaybackSessionManager {
|
|||
if (!session.timeListening) return // Do not save a session with no listening time
|
||||
|
||||
if (session.lastSave) {
|
||||
return this.db.updateEntity('session', session)
|
||||
return Database.updatePlaybackSession(session)
|
||||
} else {
|
||||
session.lastSave = Date.now()
|
||||
return this.db.insertEntity('session', session)
|
||||
return Database.createPlaybackSession(session)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -305,16 +316,5 @@ class PlaybackSessionManager {
|
|||
Logger.error(`[PlaybackSessionManager] cleanOrphanStreams failed`, error)
|
||||
}
|
||||
}
|
||||
|
||||
// Android app v0.9.54 and below had a bug where listening time was sending unix timestamp
|
||||
// See https://github.com/advplyr/audiobookshelf/issues/868
|
||||
// Remove playback sessions with listening time too high
|
||||
async removeInvalidSessions() {
|
||||
const selectFunc = (session) => isNaN(session.timeListening) || Number(session.timeListening) > 36000000
|
||||
const numSessionsRemoved = await this.db.removeEntities('session', selectFunc, true)
|
||||
if (numSessionsRemoved) {
|
||||
Logger.info(`[PlaybackSessionManager] Removed ${numSessionsRemoved} invalid playback sessions`)
|
||||
}
|
||||
}
|
||||
}
|
||||
module.exports = PlaybackSessionManager
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Database = require('../Database')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
|
||||
|
|
@ -19,8 +20,7 @@ const AudioFile = require('../objects/files/AudioFile')
|
|||
const Task = require("../objects/Task")
|
||||
|
||||
class PodcastManager {
|
||||
constructor(db, watcher, notificationManager, taskManager) {
|
||||
this.db = db
|
||||
constructor(watcher, notificationManager, taskManager) {
|
||||
this.watcher = watcher
|
||||
this.notificationManager = notificationManager
|
||||
this.taskManager = taskManager
|
||||
|
|
@ -32,10 +32,6 @@ class PodcastManager {
|
|||
this.MaxFailedEpisodeChecks = 24
|
||||
}
|
||||
|
||||
get serverSettings() {
|
||||
return this.db.serverSettings || {}
|
||||
}
|
||||
|
||||
getEpisodeDownloadsInQueue(libraryItemId) {
|
||||
return this.downloadQueue.filter(d => d.libraryItemId === libraryItemId)
|
||||
}
|
||||
|
|
@ -59,6 +55,7 @@ class PodcastManager {
|
|||
const newPe = new PodcastEpisode()
|
||||
newPe.setData(ep, index++)
|
||||
newPe.libraryItemId = libraryItem.id
|
||||
newPe.podcastId = libraryItem.media.id
|
||||
const newPeDl = new PodcastEpisodeDownload()
|
||||
newPeDl.setData(newPe, libraryItem, isAutoDownload, libraryItem.libraryId)
|
||||
this.startPodcastEpisodeDownload(newPeDl)
|
||||
|
|
@ -153,7 +150,7 @@ class PodcastManager {
|
|||
return false
|
||||
}
|
||||
|
||||
const libraryItem = this.db.libraryItems.find(li => li.id === this.currentDownload.libraryItem.id)
|
||||
const libraryItem = Database.libraryItems.find(li => li.id === this.currentDownload.libraryItem.id)
|
||||
if (!libraryItem) {
|
||||
Logger.error(`[PodcastManager] Podcast Episode finished but library item was not found ${this.currentDownload.libraryItem.id}`)
|
||||
return false
|
||||
|
|
@ -182,7 +179,7 @@ class PodcastManager {
|
|||
}
|
||||
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
await Database.updateLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
const podcastEpisodeExpanded = podcastEpisode.toJSONExpanded()
|
||||
podcastEpisodeExpanded.libraryItem = libraryItem.toJSONExpanded()
|
||||
|
|
@ -235,6 +232,7 @@ class PodcastManager {
|
|||
}
|
||||
const newAudioFile = new AudioFile()
|
||||
newAudioFile.setDataFromProbe(libraryFile, mediaProbeData)
|
||||
newAudioFile.index = 1
|
||||
return newAudioFile
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +272,7 @@ class PodcastManager {
|
|||
|
||||
libraryItem.media.lastEpisodeCheck = Date.now()
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
await Database.updateLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
return libraryItem.media.autoDownloadEpisodes
|
||||
}
|
||||
|
|
@ -313,7 +311,7 @@ class PodcastManager {
|
|||
|
||||
libraryItem.media.lastEpisodeCheck = Date.now()
|
||||
libraryItem.updatedAt = Date.now()
|
||||
await this.db.updateLibraryItem(libraryItem)
|
||||
await Database.updateLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', libraryItem.toJSONExpanded())
|
||||
|
||||
return newEpisodes
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@ const Path = require('path')
|
|||
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
const Database = require('../Database')
|
||||
|
||||
const fs = require('../libs/fsExtra')
|
||||
const Feed = require('../objects/Feed')
|
||||
|
||||
class RssFeedManager {
|
||||
constructor(db) {
|
||||
this.db = db
|
||||
|
||||
constructor() {
|
||||
this.feeds = {}
|
||||
}
|
||||
|
||||
|
|
@ -19,18 +18,18 @@ class RssFeedManager {
|
|||
|
||||
validateFeedEntity(feedObj) {
|
||||
if (feedObj.entityType === 'collection') {
|
||||
if (!this.db.collections.some(li => li.id === feedObj.entityId)) {
|
||||
if (!Database.collections.some(li => li.id === feedObj.entityId)) {
|
||||
Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Collection "${feedObj.entityId}" not found`)
|
||||
return false
|
||||
}
|
||||
} else if (feedObj.entityType === 'libraryItem') {
|
||||
if (!this.db.libraryItems.some(li => li.id === feedObj.entityId)) {
|
||||
if (!Database.libraryItems.some(li => li.id === feedObj.entityId)) {
|
||||
Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Library item "${feedObj.entityId}" not found`)
|
||||
return false
|
||||
}
|
||||
} else if (feedObj.entityType === 'series') {
|
||||
const series = this.db.series.find(s => s.id === feedObj.entityId)
|
||||
const hasSeriesBook = this.db.libraryItems.some(li => li.mediaType === 'book' && li.media.metadata.hasSeries(series.id) && li.media.tracks.length)
|
||||
const series = Database.series.find(s => s.id === feedObj.entityId)
|
||||
const hasSeriesBook = Database.libraryItems.some(li => li.mediaType === 'book' && li.media.metadata.hasSeries(series.id) && li.media.tracks.length)
|
||||
if (!hasSeriesBook) {
|
||||
Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Series "${feedObj.entityId}" not found or has no audio tracks`)
|
||||
return false
|
||||
|
|
@ -43,19 +42,13 @@ class RssFeedManager {
|
|||
}
|
||||
|
||||
async init() {
|
||||
const feedObjects = await this.db.getAllEntities('feed')
|
||||
if (!feedObjects || !feedObjects.length) return
|
||||
const feedObjects = Database.feeds
|
||||
if (!feedObjects?.length) return
|
||||
|
||||
for (const feedObj of feedObjects) {
|
||||
// Migration: In v2.2.12 entityType "item" was updated to "libraryItem"
|
||||
if (feedObj.entityType === 'item') {
|
||||
feedObj.entityType = 'libraryItem'
|
||||
await this.db.updateEntity('feed', feedObj)
|
||||
}
|
||||
|
||||
// Remove invalid feeds
|
||||
if (!this.validateFeedEntity(feedObj)) {
|
||||
await this.db.removeEntity('feed', feedObj.id)
|
||||
await Database.removeFeed(feedObj.id)
|
||||
}
|
||||
|
||||
const feed = new Feed(feedObj)
|
||||
|
|
@ -82,7 +75,7 @@ class RssFeedManager {
|
|||
|
||||
// Check if feed needs to be updated
|
||||
if (feed.entityType === 'libraryItem') {
|
||||
const libraryItem = this.db.getLibraryItem(feed.entityId)
|
||||
const libraryItem = Database.getLibraryItem(feed.entityId)
|
||||
|
||||
let mostRecentlyUpdatedAt = libraryItem.updatedAt
|
||||
if (libraryItem.isPodcast) {
|
||||
|
|
@ -94,12 +87,12 @@ class RssFeedManager {
|
|||
if (libraryItem && (!feed.entityUpdatedAt || mostRecentlyUpdatedAt > feed.entityUpdatedAt)) {
|
||||
Logger.debug(`[RssFeedManager] Updating RSS feed for item ${libraryItem.id} "${libraryItem.media.metadata.title}"`)
|
||||
feed.updateFromItem(libraryItem)
|
||||
await this.db.updateEntity('feed', feed)
|
||||
await Database.updateFeed(feed)
|
||||
}
|
||||
} else if (feed.entityType === 'collection') {
|
||||
const collection = this.db.collections.find(c => c.id === feed.entityId)
|
||||
const collection = Database.collections.find(c => c.id === feed.entityId)
|
||||
if (collection) {
|
||||
const collectionExpanded = collection.toJSONExpanded(this.db.libraryItems)
|
||||
const collectionExpanded = collection.toJSONExpanded(Database.libraryItems)
|
||||
|
||||
// Find most recently updated item in collection
|
||||
let mostRecentlyUpdatedAt = collectionExpanded.lastUpdate
|
||||
|
|
@ -113,15 +106,15 @@ class RssFeedManager {
|
|||
Logger.debug(`[RssFeedManager] Updating RSS feed for collection "${collection.name}"`)
|
||||
|
||||
feed.updateFromCollection(collectionExpanded)
|
||||
await this.db.updateEntity('feed', feed)
|
||||
await Database.updateFeed(feed)
|
||||
}
|
||||
}
|
||||
} else if (feed.entityType === 'series') {
|
||||
const series = this.db.series.find(s => s.id === feed.entityId)
|
||||
const series = Database.series.find(s => s.id === feed.entityId)
|
||||
if (series) {
|
||||
const seriesJson = series.toJSON()
|
||||
// Get books in series that have audio tracks
|
||||
seriesJson.books = this.db.libraryItems.filter(li => li.mediaType === 'book' && li.media.metadata.hasSeries(series.id) && li.media.tracks.length)
|
||||
seriesJson.books = Database.libraryItems.filter(li => li.mediaType === 'book' && li.media.metadata.hasSeries(series.id) && li.media.tracks.length)
|
||||
|
||||
// Find most recently updated item in series
|
||||
let mostRecentlyUpdatedAt = seriesJson.updatedAt
|
||||
|
|
@ -140,7 +133,7 @@ class RssFeedManager {
|
|||
Logger.debug(`[RssFeedManager] Updating RSS feed for series "${seriesJson.name}"`)
|
||||
|
||||
feed.updateFromSeries(seriesJson)
|
||||
await this.db.updateEntity('feed', feed)
|
||||
await Database.updateFeed(feed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,7 +190,7 @@ class RssFeedManager {
|
|||
this.feeds[feed.id] = feed
|
||||
|
||||
Logger.debug(`[RssFeedManager] Opened RSS feed "${feed.feedUrl}"`)
|
||||
await this.db.insertEntity('feed', feed)
|
||||
await Database.createFeed(feed)
|
||||
SocketAuthority.emitter('rss_feed_open', feed.toJSONMinified())
|
||||
return feed
|
||||
}
|
||||
|
|
@ -214,7 +207,7 @@ class RssFeedManager {
|
|||
this.feeds[feed.id] = feed
|
||||
|
||||
Logger.debug(`[RssFeedManager] Opened RSS feed "${feed.feedUrl}"`)
|
||||
await this.db.insertEntity('feed', feed)
|
||||
await Database.createFeed(feed)
|
||||
SocketAuthority.emitter('rss_feed_open', feed.toJSONMinified())
|
||||
return feed
|
||||
}
|
||||
|
|
@ -231,14 +224,14 @@ class RssFeedManager {
|
|||
this.feeds[feed.id] = feed
|
||||
|
||||
Logger.debug(`[RssFeedManager] Opened RSS feed "${feed.feedUrl}"`)
|
||||
await this.db.insertEntity('feed', feed)
|
||||
await Database.createFeed(feed)
|
||||
SocketAuthority.emitter('rss_feed_open', feed.toJSONMinified())
|
||||
return feed
|
||||
}
|
||||
|
||||
async handleCloseFeed(feed) {
|
||||
if (!feed) return
|
||||
await this.db.removeEntity('feed', feed.id)
|
||||
await Database.removeFeed(feed.id)
|
||||
SocketAuthority.emitter('rss_feed_closed', feed.toJSONMinified())
|
||||
delete this.feeds[feed.id]
|
||||
Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue