From 9123dcb3651e53b705f1b0d8a7c1e9730bcf5f2f Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 3 Sep 2023 10:49:02 -0500 Subject: [PATCH] Remove series search api endpoint, update authors and series to load from db --- server/Database.js | 20 ---------------- server/Server.js | 9 ++++++- server/controllers/MeController.js | 4 ++-- server/controllers/RSSFeedController.js | 4 ++-- server/controllers/SeriesController.js | 13 +--------- server/managers/RssFeedManager.js | 4 ++-- server/models/Author.js | 24 +++++++++++++++++-- server/models/Series.js | 32 ++++++++++++++++++++++++- server/routers/ApiRouter.js | 6 ++--- server/scanner/Scanner.js | 16 ++++++------- 10 files changed, 79 insertions(+), 53 deletions(-) diff --git a/server/Database.js b/server/Database.js index bf1c1851..e131fb11 100644 --- a/server/Database.js +++ b/server/Database.js @@ -19,8 +19,6 @@ class Database { // TODO: below data should be loaded from the DB as needed this.libraryItems = [] this.settings = [] - this.authors = [] - this.series = [] // Cached library filter data this.libraryFilterData = {} @@ -274,12 +272,6 @@ class Database { this.libraryItems = await this.models.libraryItem.loadAllLibraryItems() Logger.info(`[Database] Loaded ${this.libraryItems.length} library items`) - this.authors = await this.models.author.getOldAuthors() - Logger.info(`[Database] Loaded ${this.authors.length} authors`) - - this.series = await this.models.series.getAllOldSeries() - Logger.info(`[Database] Loaded ${this.series.length} series`) - // Set if root user has been created this.hasRootUser = await this.models.user.getHasRootUser() @@ -456,31 +448,26 @@ class Database { async createSeries(oldSeries) { if (!this.sequelize) return false await this.models.series.createFromOld(oldSeries) - this.series.push(oldSeries) } async createBulkSeries(oldSeriesObjs) { if (!this.sequelize) return false await this.models.series.createBulkFromOld(oldSeriesObjs) - this.series.push(...oldSeriesObjs) } async removeSeries(seriesId) { if (!this.sequelize) return false await this.models.series.removeById(seriesId) - this.series = this.series.filter(se => se.id !== seriesId) } async createAuthor(oldAuthor) { if (!this.sequelize) return false await this.models.author.createFromOld(oldAuthor) - this.authors.push(oldAuthor) } async createBulkAuthors(oldAuthors) { if (!this.sequelize) return false await this.models.author.createBulkFromOld(oldAuthors) - this.authors.push(...oldAuthors) } updateAuthor(oldAuthor) { @@ -491,24 +478,17 @@ class Database { async removeAuthor(authorId) { if (!this.sequelize) return false await this.models.author.removeById(authorId) - this.authors = this.authors.filter(au => au.id !== authorId) } async createBulkBookAuthors(bookAuthors) { if (!this.sequelize) return false await this.models.bookAuthor.bulkCreate(bookAuthors) - this.authors.push(...bookAuthors) } async removeBulkBookAuthors(authorId = null, bookId = null) { if (!this.sequelize) return false if (!authorId && !bookId) return await this.models.bookAuthor.removeByIds(authorId, bookId) - this.authors = this.authors.filter(au => { - if (authorId && au.authorId !== authorId) return true - if (bookId && au.bookId !== bookId) return true - return false - }) } getPlaybackSessions(where = null) { diff --git a/server/Server.js b/server/Server.js index c9810cc8..47cf6851 100644 --- a/server/Server.js +++ b/server/Server.js @@ -289,8 +289,15 @@ class Server { for (const _user of users) { let hasUpdated = false if (_user.seriesHideFromContinueListening.length) { + const seriesHiding = (await Database.seriesModel.findAll({ + where: { + id: _user.seriesHideFromContinueListening + }, + attributes: ['id'], + raw: true + })).map(se => se.id) _user.seriesHideFromContinueListening = _user.seriesHideFromContinueListening.filter(seriesId => { - if (!Database.series.some(se => se.id === seriesId)) { // Series removed + if (!seriesHiding.includes(seriesId)) { // Series removed hasUpdated = true return false } diff --git a/server/controllers/MeController.js b/server/controllers/MeController.js index f5e252c1..4c6b3ab4 100644 --- a/server/controllers/MeController.js +++ b/server/controllers/MeController.js @@ -281,7 +281,7 @@ class MeController { // GET: api/me/series/:id/remove-from-continue-listening async removeSeriesFromContinueListening(req, res) { - const series = Database.series.find(se => se.id === req.params.id) + const series = await Database.seriesModel.getOldById(req.params.id) if (!series) { Logger.error(`[MeController] removeSeriesFromContinueListening: Series ${req.params.id} not found`) return res.sendStatus(404) @@ -297,7 +297,7 @@ class MeController { // GET: api/me/series/:id/readd-to-continue-listening async readdSeriesFromContinueListening(req, res) { - const series = Database.series.find(se => se.id === req.params.id) + const series = await Database.seriesModel.getOldById(req.params.id) if (!series) { Logger.error(`[MeController] readdSeriesFromContinueListening: Series ${req.params.id} not found`) return res.sendStatus(404) diff --git a/server/controllers/RSSFeedController.js b/server/controllers/RSSFeedController.js index 68d31ee1..9b7acf70 100644 --- a/server/controllers/RSSFeedController.js +++ b/server/controllers/RSSFeedController.js @@ -9,7 +9,7 @@ class RSSFeedController { const feeds = await this.rssFeedManager.getFeeds() res.json({ feeds: feeds.map(f => f.toJSON()), - minified: feeds.map(f => f.toJSONMinified()) + minified: feeds.map(f => f.toJSONMinified()) }) } @@ -88,7 +88,7 @@ class RSSFeedController { async openRSSFeedForSeries(req, res) { const options = req.body || {} - const series = Database.series.find(se => se.id === req.params.seriesId) + const series = await Database.seriesModel.getOldById(req.params.seriesId) if (!series) return res.sendStatus(404) // Check request body options exist diff --git a/server/controllers/SeriesController.js b/server/controllers/SeriesController.js index 61801fcf..38ab3da9 100644 --- a/server/controllers/SeriesController.js +++ b/server/controllers/SeriesController.js @@ -43,17 +43,6 @@ class SeriesController { res.json(seriesJson) } - async search(req, res) { - var q = (req.query.q || '').toLowerCase() - if (!q) return res.json([]) - var limit = (req.query.limit && !isNaN(req.query.limit)) ? Number(req.query.limit) : 25 - var series = Database.series.filter(se => se.name.toLowerCase().includes(q)) - series = series.slice(0, limit) - res.json({ - results: series - }) - } - async update(req, res) { const hasUpdated = req.series.update(req.body) if (hasUpdated) { @@ -64,7 +53,7 @@ class SeriesController { } async middleware(req, res, next) { - const series = Database.series.find(se => se.id === req.params.id) + const series = await Database.seriesModel.getOldById(req.params.id) if (!series) return res.sendStatus(404) /** diff --git a/server/managers/RssFeedManager.js b/server/managers/RssFeedManager.js index fa2ae7e1..0c0821ae 100644 --- a/server/managers/RssFeedManager.js +++ b/server/managers/RssFeedManager.js @@ -25,7 +25,7 @@ class RssFeedManager { return false } } else if (feedObj.entityType === 'series') { - const series = Database.series.find(s => s.id === feedObj.entityId) + const series = await Database.seriesModel.getOldById(feedObj.entityId) if (!series) { Logger.error(`[RssFeedManager] Removing feed "${feedObj.id}". Series "${feedObj.entityId}" not found`) return false @@ -123,7 +123,7 @@ class RssFeedManager { } } } else if (feed.entityType === 'series') { - const series = Database.series.find(s => s.id === feed.entityId) + const series = await Database.seriesModel.getOldById(feed.entityId) if (series) { const seriesJson = series.toJSON() diff --git a/server/models/Author.js b/server/models/Author.js index ea8fc9db..34ae3629 100644 --- a/server/models/Author.js +++ b/server/models/Author.js @@ -1,4 +1,4 @@ -const { DataTypes, Model } = require('sequelize') +const { DataTypes, Model, literal } = require('sequelize') const oldAuthor = require('../objects/entities/Author') @@ -86,7 +86,7 @@ class Author extends Model { /** * Get oldAuthor by id * @param {string} authorId - * @returns {oldAuthor} + * @returns {Promise} */ static async getOldById(authorId) { const author = await this.findByPk(authorId) @@ -103,6 +103,26 @@ class Author extends Model { return (await this.count({ where: { id: authorId } })) > 0 } + /** + * Get old author by name and libraryId. name case insensitive + * TODO: Look for authors ignoring punctuation + * + * @param {string} authorName + * @param {string} libraryId + * @returns {Promise} + */ + static async getOldByNameAndLibrary(authorName, libraryId) { + const author = (await this.findOne({ + where: [ + literal(`name = '${authorName}' COLLATE NOCASE`), + { + libraryId + } + ] + }))?.getOldAuthor() + return author + } + /** * Initialize model * @param {import('../Database').sequelize} sequelize diff --git a/server/models/Series.js b/server/models/Series.js index 576cafce..375e8021 100644 --- a/server/models/Series.js +++ b/server/models/Series.js @@ -1,4 +1,4 @@ -const { DataTypes, Model } = require('sequelize') +const { DataTypes, Model, literal } = require('sequelize') const oldSeries = require('../objects/entities/Series') @@ -75,6 +75,17 @@ class Series extends Model { }) } + /** + * Get oldSeries by id + * @param {string} seriesId + * @returns {Promise} + */ + static async getOldById(seriesId) { + const series = await this.findByPk(seriesId) + if (!series) return null + return series.getOldSeries() + } + /** * Check if series exists * @param {string} seriesId @@ -84,6 +95,25 @@ class Series extends Model { return (await this.count({ where: { id: seriesId } })) > 0 } + /** + * Get old series by name and libraryId. name case insensitive + * + * @param {string} seriesName + * @param {string} libraryId + * @returns {Promise} + */ + static async getOldByNameAndLibrary(seriesName, libraryId) { + const series = (await this.findOne({ + where: [ + literal(`name = '${seriesName}' COLLATE NOCASE`), + { + libraryId + } + ] + }))?.getOldSeries() + return series + } + /** * Initialize model * @param {import('../Database').sequelize} sequelize diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index 03f382fe..14641e00 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -1,3 +1,4 @@ +const sequelize = require('sequelize') const express = require('express') const Path = require('path') @@ -217,7 +218,6 @@ class ApiRouter { // // Series Routes // - this.router.get('/series/search', SeriesController.search.bind(this)) this.router.get('/series/:id', SeriesController.middleware.bind(this), SeriesController.findOne.bind(this)) this.router.patch('/series/:id', SeriesController.middleware.bind(this), SeriesController.update.bind(this)) @@ -572,7 +572,7 @@ class ApiRouter { } if (!mediaMetadata.authors[i].id || mediaMetadata.authors[i].id.startsWith('new')) { - let author = Database.authors.find(au => au.libraryId === libraryId && au.checkNameEquals(authorName)) + let author = await Database.authorModel.getOldByNameAndLibrary(authorName, libraryId) if (!author) { author = new Author() author.setData(mediaMetadata.authors[i], libraryId) @@ -609,7 +609,7 @@ class ApiRouter { } if (!mediaMetadata.series[i].id || mediaMetadata.series[i].id.startsWith('new')) { - let seriesItem = Database.series.find(se => se.libraryId === libraryId && se.checkNameEquals(seriesName)) + let seriesItem = await Database.seriesModel.getOldByNameAndLibrary(seriesName, libraryId) if (!seriesItem) { seriesItem = new Series() seriesItem.setData(mediaMetadata.series[i], libraryId) diff --git a/server/scanner/Scanner.js b/server/scanner/Scanner.js index 7b6d0d12..d7f264bb 100644 --- a/server/scanner/Scanner.js +++ b/server/scanner/Scanner.js @@ -479,8 +479,8 @@ class Scanner { // Create or match all new authors and series if (libraryItem.media.metadata.authors.some(au => au.id.startsWith('new'))) { const newAuthors = [] - libraryItem.media.metadata.authors = libraryItem.media.metadata.authors.map((tempMinAuthor) => { - let _author = Database.authors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(tempMinAuthor.name)) + libraryItem.media.metadata.authors = Promise.all(libraryItem.media.metadata.authors.map(async (tempMinAuthor) => { + let _author = await Database.authorModel.getOldByNameAndLibrary(tempMinAuthor.name, libraryItem.libraryId) if (!_author) _author = newAuthors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(tempMinAuthor.name)) // Check new unsaved authors if (!_author) { // Must create new author _author = new Author() @@ -494,7 +494,7 @@ class Scanner { id: _author.id, name: _author.name } - }) + })) if (newAuthors.length) { await Database.createBulkAuthors(newAuthors) SocketAuthority.emitter('authors_added', newAuthors.map(au => au.toJSON())) @@ -502,8 +502,8 @@ class Scanner { } if (libraryItem.media.metadata.series.some(se => se.id.startsWith('new'))) { const newSeries = [] - libraryItem.media.metadata.series = libraryItem.media.metadata.series.map((tempMinSeries) => { - let _series = Database.series.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(tempMinSeries.name)) + libraryItem.media.metadata.series = await Promise.all(libraryItem.media.metadata.series.map(async (tempMinSeries) => { + let _series = await Database.seriesModel.getOldByNameAndLibrary(tempMinSeries.name, libraryItem.libraryId) if (!_series) { // Check new unsaved series _series = newSeries.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(tempMinSeries.name)) @@ -521,7 +521,7 @@ class Scanner { name: _series.name, sequence: tempMinSeries.sequence } - }) + })) if (newSeries.length) { await Database.createBulkSeries(newSeries) SocketAuthority.emitter('multiple_series_added', newSeries.map(se => se.toJSON())) @@ -931,7 +931,7 @@ class Scanner { } const authorPayload = [] for (const authorName of matchData.author) { - let author = Database.authors.find(au => au.libraryId === libraryItem.libraryId && au.checkNameEquals(authorName)) + let author = await Database.authorModel.getOldByNameAndLibrary(authorName, libraryItem.libraryId) if (!author) { author = new Author() author.setData({ name: authorName }, libraryItem.libraryId) @@ -950,7 +950,7 @@ class Scanner { if (!Array.isArray(matchData.series)) matchData.series = [{ series: matchData.series, sequence: matchData.sequence }] const seriesPayload = [] for (const seriesMatchItem of matchData.series) { - let seriesItem = Database.series.find(se => se.libraryId === libraryItem.libraryId && se.checkNameEquals(seriesMatchItem.series)) + let seriesItem = await Database.seriesModel.getOldByNameAndLibrary(seriesMatchItem.series, libraryItem.libraryId) if (!seriesItem) { seriesItem = new Series() seriesItem.setData({ name: seriesMatchItem.series }, libraryItem.libraryId)