diff --git a/server/Db.js b/server/Db.js index 55d4c73b..f62cbfcc 100644 --- a/server/Db.js +++ b/server/Db.js @@ -280,7 +280,7 @@ class Db { } getAllEntities(entityName) { - var entityDb = this.getEntityDb(entityName) + const entityDb = this.getEntityDb(entityName) return entityDb.select(() => true).then((results) => results.data).catch((error) => { Logger.error(`[DB] Failed to get all ${entityName}`, error) return null @@ -371,16 +371,16 @@ class Db { } updateEntity(entityName, entity) { - var entityDb = this.getEntityDb(entityName) + const entityDb = this.getEntityDb(entityName) - var jsonEntity = entity + let jsonEntity = entity if (entity && entity.toJSON) { jsonEntity = entity.toJSON() } return entityDb.update((record) => record.id === entity.id, () => jsonEntity).then((results) => { Logger.debug(`[DB] Updated ${entityName}: ${results.updated}`) - var arrayKey = this.getEntityArrayKey(entityName) + const arrayKey = this.getEntityArrayKey(entityName) if (this[arrayKey]) { this[arrayKey] = this[arrayKey].map(e => { return e.id === entity.id ? entity : e diff --git a/server/controllers/CollectionController.js b/server/controllers/CollectionController.js index 0c950c41..5557fdb7 100644 --- a/server/controllers/CollectionController.js +++ b/server/controllers/CollectionController.js @@ -40,8 +40,8 @@ class CollectionController { async update(req, res) { const collection = req.collection - var wasUpdated = collection.update(req.body) - var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) + const wasUpdated = collection.update(req.body) + const jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) if (wasUpdated) { await this.db.updateEntity('collection', collection) SocketAuthority.emitter('collection_updated', jsonExpanded) @@ -51,7 +51,11 @@ class CollectionController { async delete(req, res) { const collection = req.collection - var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) + const jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) + + // Close rss feed - remove from db and emit socket event + await this.rssFeedManager.closeFeedForEntityId(collection.id) + await this.db.removeEntity('collection', collection.id) SocketAuthority.emitter('collection_removed', jsonExpanded) res.sendStatus(200) @@ -59,7 +63,7 @@ class CollectionController { async addBook(req, res) { const collection = req.collection - var libraryItem = this.db.libraryItems.find(li => li.id === req.body.id) + const libraryItem = this.db.libraryItems.find(li => li.id === req.body.id) if (!libraryItem) { return res.status(500).send('Book not found') } @@ -70,7 +74,7 @@ class CollectionController { return res.status(500).send('Book already in collection') } collection.addBook(req.body.id) - var jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) + const jsonExpanded = collection.toJSONExpanded(this.db.libraryItems) await this.db.updateEntity('collection', collection) SocketAuthority.emitter('collection_updated', jsonExpanded) res.json(jsonExpanded) diff --git a/server/managers/RssFeedManager.js b/server/managers/RssFeedManager.js index 6550feac..72987f86 100644 --- a/server/managers/RssFeedManager.js +++ b/server/managers/RssFeedManager.js @@ -17,14 +17,43 @@ class RssFeedManager { return Object.values(this.feeds) } + validateFeedEntity(feedObj) { + if (feedObj.entityType === 'collection') { + if (!this.db.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)) { + Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Library item "${feedObj.entityId}" not found`) + return false + } + } else { + Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Invalid entityType "${feedObj.entityType}"`) + return false + } + return true + } + async init() { const feedObjects = await this.db.getAllEntities('feed') - if (feedObjects && feedObjects.length) { - feedObjects.forEach((feedObj) => { - const feed = new Feed(feedObj) - this.feeds[feed.id] = feed - Logger.info(`[RssFeedManager] Opened rss feed ${feed.feedUrl}`) - }) + if (!feedObjects || !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) + } + + const feed = new Feed(feedObj) + this.feeds[feed.id] = feed + Logger.info(`[RssFeedManager] Opened rss feed ${feed.feedUrl}`) } } @@ -141,13 +170,23 @@ class RssFeedManager { return feed } - async closeRssFeed(id) { - if (!this.feeds[id]) return - const feed = this.feeds[id] - await this.db.removeEntity('feed', id) + async handleCloseFeed(feed) { + if (!feed) return + await this.db.removeEntity('feed', feed.id) SocketAuthority.emitter('rss_feed_closed', feed.toJSONMinified()) - delete this.feeds[id] + delete this.feeds[feed.id] Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`) } + + closeRssFeed(id) { + if (!this.feeds[id]) return + return this.handleCloseFeed(this.feeds[id]) + } + + closeFeedForEntityId(entityId) { + const feed = this.findFeedForEntityId(entityId) + if (!feed) return + return this.handleCloseFeed(feed) + } } module.exports = RssFeedManager \ No newline at end of file diff --git a/server/objects/Feed.js b/server/objects/Feed.js index 4f913460..d6b1a61f 100644 --- a/server/objects/Feed.js +++ b/server/objects/Feed.js @@ -87,7 +87,7 @@ class Feed { this.id = slug this.slug = slug this.userId = userId - this.entityType = 'item' + this.entityType = 'libraryItem' this.entityId = libraryItem.id this.entityUpdatedAt = libraryItem.updatedAt this.coverPath = media.coverPath || null diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 59ba0dec..b2afb563 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -386,6 +386,9 @@ class ApiRouter { } } + // Close rss feed - remove from db and emit socket event + await this.rssFeedManager.closeFeedForEntityId(libraryItem.id) + // purge cover cache if (libraryItem.media.coverPath) { await this.cacheManager.purgeCoverCache(libraryItem.id)