mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-01-02 00:59:37 +00:00
Merge branch 'master' into shawn/rss-feeds
This commit is contained in:
commit
24989e73ae
45 changed files with 1575 additions and 1193 deletions
|
|
@ -21,7 +21,7 @@ class AuthorController {
|
|||
|
||||
// Used on author landing page to include library items and items grouped in series
|
||||
if (include.includes('items')) {
|
||||
authorJson.libraryItems = await Database.models.libraryItem.getForAuthor(req.author, req.user)
|
||||
authorJson.libraryItems = await Database.libraryItemModel.getForAuthor(req.author, req.user)
|
||||
|
||||
if (include.includes('series')) {
|
||||
const seriesMap = {}
|
||||
|
|
@ -96,7 +96,7 @@ class AuthorController {
|
|||
const existingAuthor = authorNameUpdate ? Database.authors.find(au => au.id !== req.author.id && payload.name === au.name) : false
|
||||
if (existingAuthor) {
|
||||
const bookAuthorsToCreate = []
|
||||
const itemsWithAuthor = await Database.models.libraryItem.getForAuthor(req.author)
|
||||
const itemsWithAuthor = await Database.libraryItemModel.getForAuthor(req.author)
|
||||
itemsWithAuthor.forEach(libraryItem => { // Replace old author with merging author for each book
|
||||
libraryItem.media.metadata.replaceAuthor(req.author, existingAuthor)
|
||||
bookAuthorsToCreate.push({
|
||||
|
|
@ -113,9 +113,11 @@ class AuthorController {
|
|||
// Remove old author
|
||||
await Database.removeAuthor(req.author.id)
|
||||
SocketAuthority.emitter('author_removed', req.author.toJSON())
|
||||
// Update filter data
|
||||
Database.removeAuthorFromFilterData(req.author.libraryId, req.author.id)
|
||||
|
||||
// Send updated num books for merged author
|
||||
const numBooks = await Database.models.libraryItem.getForAuthor(existingAuthor).length
|
||||
const numBooks = await Database.libraryItemModel.getForAuthor(existingAuthor).length
|
||||
SocketAuthority.emitter('author_updated', existingAuthor.toJSONExpanded(numBooks))
|
||||
|
||||
res.json({
|
||||
|
|
@ -130,7 +132,7 @@ class AuthorController {
|
|||
if (hasUpdated) {
|
||||
req.author.updatedAt = Date.now()
|
||||
|
||||
const itemsWithAuthor = await Database.models.libraryItem.getForAuthor(req.author)
|
||||
const itemsWithAuthor = await Database.libraryItemModel.getForAuthor(req.author)
|
||||
if (authorNameUpdate) { // Update author name on all books
|
||||
itemsWithAuthor.forEach(libraryItem => {
|
||||
libraryItem.media.metadata.updateAuthor(req.author)
|
||||
|
|
@ -202,7 +204,7 @@ class AuthorController {
|
|||
|
||||
await Database.updateAuthor(req.author)
|
||||
|
||||
const numBooks = await Database.models.libraryItem.getForAuthor(req.author).length
|
||||
const numBooks = await Database.libraryItemModel.getForAuthor(req.author).length
|
||||
SocketAuthority.emitter('author_updated', req.author.toJSONExpanded(numBooks))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ class CollectionController {
|
|||
}
|
||||
|
||||
// Create collection record
|
||||
await Database.models.collection.createFromOld(newCollection)
|
||||
await Database.collectionModel.createFromOld(newCollection)
|
||||
|
||||
// Get library items in collection
|
||||
const libraryItemsInCollection = await Database.models.libraryItem.getForCollection(newCollection)
|
||||
const libraryItemsInCollection = await Database.libraryItemModel.getForCollection(newCollection)
|
||||
|
||||
// Create collectionBook records
|
||||
let order = 1
|
||||
|
|
@ -50,7 +50,7 @@ class CollectionController {
|
|||
}
|
||||
|
||||
async findAll(req, res) {
|
||||
const collectionsExpanded = await Database.models.collection.getOldCollectionsJsonExpanded(req.user)
|
||||
const collectionsExpanded = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user)
|
||||
res.json({
|
||||
collections: collectionsExpanded
|
||||
})
|
||||
|
|
@ -96,8 +96,8 @@ class CollectionController {
|
|||
if (req.body.books?.length) {
|
||||
const collectionBooks = await req.collection.getCollectionBooks({
|
||||
include: {
|
||||
model: Database.models.book,
|
||||
include: Database.models.libraryItem
|
||||
model: Database.bookModel,
|
||||
include: Database.libraryItemModel
|
||||
},
|
||||
order: [['order', 'ASC']]
|
||||
})
|
||||
|
|
@ -143,7 +143,7 @@ class CollectionController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async addBook(req, res) {
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(req.body.id)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(req.body.id)
|
||||
if (!libraryItem) {
|
||||
return res.status(404).send('Book not found')
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ class CollectionController {
|
|||
}
|
||||
|
||||
// Create collectionBook record
|
||||
await Database.models.collectionBook.create({
|
||||
await Database.collectionBookModel.create({
|
||||
collectionId: req.collection.id,
|
||||
bookId: libraryItem.media.id,
|
||||
order: collectionBooks.length + 1
|
||||
|
|
@ -176,7 +176,7 @@ class CollectionController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async removeBook(req, res) {
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(req.params.bookId)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(req.params.bookId)
|
||||
if (!libraryItem) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
|
@ -227,14 +227,14 @@ class CollectionController {
|
|||
}
|
||||
|
||||
// Get library items associated with ids
|
||||
const libraryItems = await Database.models.libraryItem.findAll({
|
||||
const libraryItems = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Sequelize.Op.in]: bookIdsToAdd
|
||||
}
|
||||
},
|
||||
include: {
|
||||
model: Database.models.book
|
||||
model: Database.bookModel
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -285,14 +285,14 @@ class CollectionController {
|
|||
}
|
||||
|
||||
// Get library items associated with ids
|
||||
const libraryItems = await Database.models.libraryItem.findAll({
|
||||
const libraryItems = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Sequelize.Op.in]: bookIdsToRemove
|
||||
}
|
||||
},
|
||||
include: {
|
||||
model: Database.models.book
|
||||
model: Database.bookModel
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -327,7 +327,7 @@ class CollectionController {
|
|||
|
||||
async middleware(req, res, next) {
|
||||
if (req.params.id) {
|
||||
const collection = await Database.models.collection.findByPk(req.params.id)
|
||||
const collection = await Database.collectionModel.findByPk(req.params.id)
|
||||
if (!collection) {
|
||||
return res.status(404).send('Collection not found')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class FileSystemController {
|
|||
})
|
||||
|
||||
// Do not include existing mapped library paths in response
|
||||
const libraryFoldersPaths = await Database.models.libraryFolder.getAllLibraryFolderPaths()
|
||||
const libraryFoldersPaths = await Database.libraryModelFolder.getAllLibraryFolderPaths()
|
||||
libraryFoldersPaths.forEach((path) => {
|
||||
let dir = path || ''
|
||||
if (dir.includes(global.appRoot)) dir = dir.replace(global.appRoot, '')
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const Library = require('../objects/Library')
|
|||
const libraryHelpers = require('../utils/libraryHelpers')
|
||||
const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters')
|
||||
const libraryItemFilters = require('../utils/queries/libraryItemFilters')
|
||||
const seriesFilters = require('../utils/queries/seriesFilters')
|
||||
const { sort, createNewSortInstance } = require('../libs/fastSort')
|
||||
const naturalSort = createNewSortInstance({
|
||||
comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare
|
||||
|
|
@ -15,6 +16,8 @@ const naturalSort = createNewSortInstance({
|
|||
|
||||
const Database = require('../Database')
|
||||
const libraryFilters = require('../utils/queries/libraryFilters')
|
||||
const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters')
|
||||
const authorFilters = require('../utils/queries/authorFilters')
|
||||
|
||||
class LibraryController {
|
||||
constructor() { }
|
||||
|
|
@ -48,7 +51,7 @@ class LibraryController {
|
|||
|
||||
const library = new Library()
|
||||
|
||||
let currentLargestDisplayOrder = await Database.models.library.getMaxDisplayOrder()
|
||||
let currentLargestDisplayOrder = await Database.libraryModel.getMaxDisplayOrder()
|
||||
if (isNaN(currentLargestDisplayOrder)) currentLargestDisplayOrder = 0
|
||||
newLibraryPayload.displayOrder = currentLargestDisplayOrder + 1
|
||||
library.setData(newLibraryPayload)
|
||||
|
|
@ -67,7 +70,7 @@ class LibraryController {
|
|||
}
|
||||
|
||||
async findAll(req, res) {
|
||||
const libraries = await Database.models.library.getAllOldLibraries()
|
||||
const libraries = await Database.libraryModel.getAllOldLibraries()
|
||||
|
||||
const librariesAccessible = req.user.librariesAccessible || []
|
||||
if (librariesAccessible.length) {
|
||||
|
|
@ -89,7 +92,7 @@ class LibraryController {
|
|||
return res.json({
|
||||
filterdata,
|
||||
issues: filterdata.numIssues,
|
||||
numUserPlaylists: await Database.models.playlist.getNumPlaylistsForUserAndLibrary(req.user.id, req.library.id),
|
||||
numUserPlaylists: await Database.playlistModel.getNumPlaylistsForUserAndLibrary(req.user.id, req.library.id),
|
||||
library: req.library
|
||||
})
|
||||
}
|
||||
|
|
@ -141,17 +144,17 @@ class LibraryController {
|
|||
for (const folder of library.folders) {
|
||||
if (!req.body.folders.some(f => f.id === folder.id)) {
|
||||
// Remove library items in folder
|
||||
const libraryItemsInFolder = await Database.models.libraryItem.findAll({
|
||||
const libraryItemsInFolder = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
libraryFolderId: folder.id
|
||||
},
|
||||
attributes: ['id', 'mediaId', 'mediaType'],
|
||||
include: [
|
||||
{
|
||||
model: Database.models.podcast,
|
||||
model: Database.podcastModel,
|
||||
attributes: ['id'],
|
||||
include: {
|
||||
model: Database.models.podcastEpisode,
|
||||
model: Database.podcastEpisodeModel,
|
||||
attributes: ['id']
|
||||
}
|
||||
}
|
||||
|
|
@ -188,6 +191,8 @@ class LibraryController {
|
|||
return user.checkCanAccessLibrary && user.checkCanAccessLibrary(library.id)
|
||||
}
|
||||
SocketAuthority.emitter('library_updated', library.toJSON(), userFilter)
|
||||
|
||||
await Database.resetLibraryIssuesFilterData(library.id)
|
||||
}
|
||||
return res.json(library.toJSON())
|
||||
}
|
||||
|
|
@ -205,23 +210,23 @@ class LibraryController {
|
|||
this.watcher.removeLibrary(library)
|
||||
|
||||
// Remove collections for library
|
||||
const numCollectionsRemoved = await Database.models.collection.removeAllForLibrary(library.id)
|
||||
const numCollectionsRemoved = await Database.collectionModel.removeAllForLibrary(library.id)
|
||||
if (numCollectionsRemoved) {
|
||||
Logger.info(`[Server] Removed ${numCollectionsRemoved} collections for library "${library.name}"`)
|
||||
}
|
||||
|
||||
// Remove items in this library
|
||||
const libraryItemsInLibrary = await Database.models.libraryItem.findAll({
|
||||
const libraryItemsInLibrary = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
libraryId: library.id
|
||||
},
|
||||
attributes: ['id', 'mediaId', 'mediaType'],
|
||||
include: [
|
||||
{
|
||||
model: Database.models.podcast,
|
||||
model: Database.podcastModel,
|
||||
attributes: ['id'],
|
||||
include: {
|
||||
model: Database.models.podcastEpisode,
|
||||
model: Database.podcastEpisodeModel,
|
||||
attributes: ['id']
|
||||
}
|
||||
}
|
||||
|
|
@ -243,9 +248,15 @@ class LibraryController {
|
|||
await Database.removeLibrary(library.id)
|
||||
|
||||
// Re-order libraries
|
||||
await Database.models.library.resetDisplayOrder()
|
||||
await Database.libraryModel.resetDisplayOrder()
|
||||
|
||||
SocketAuthority.emitter('library_removed', libraryJson)
|
||||
|
||||
// Remove library filter data
|
||||
if (Database.libraryFilterData[library.id]) {
|
||||
delete Database.libraryFilterData[library.id]
|
||||
}
|
||||
|
||||
return res.json(libraryJson)
|
||||
}
|
||||
|
||||
|
|
@ -267,7 +278,7 @@ class LibraryController {
|
|||
}
|
||||
payload.offset = payload.page * payload.limit
|
||||
|
||||
const { libraryItems, count } = await Database.models.libraryItem.getByFilterAndSort(req.library, req.user, payload)
|
||||
const { libraryItems, count } = await Database.libraryItemModel.getByFilterAndSort(req.library, req.user, payload)
|
||||
payload.results = libraryItems
|
||||
payload.total = count
|
||||
|
||||
|
|
@ -471,12 +482,13 @@ class LibraryController {
|
|||
/**
|
||||
* DELETE: /libraries/:id/issues
|
||||
* Remove all library items missing or invalid
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async removeLibraryItemsWithIssues(req, res) {
|
||||
const libraryItemsWithIssues = await Database.models.libraryItem.findAll({
|
||||
const libraryItemsWithIssues = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
libraryId: req.library.id,
|
||||
[Sequelize.Op.or]: [
|
||||
{
|
||||
isMissing: true
|
||||
|
|
@ -489,10 +501,10 @@ class LibraryController {
|
|||
attributes: ['id', 'mediaId', 'mediaType'],
|
||||
include: [
|
||||
{
|
||||
model: Database.models.podcast,
|
||||
model: Database.podcastModel,
|
||||
attributes: ['id'],
|
||||
include: {
|
||||
model: Database.models.podcastEpisode,
|
||||
model: Database.podcastEpisodeModel,
|
||||
attributes: ['id']
|
||||
}
|
||||
}
|
||||
|
|
@ -507,7 +519,7 @@ class LibraryController {
|
|||
Logger.info(`[LibraryController] Removing ${libraryItemsWithIssues.length} items with issues`)
|
||||
for (const libraryItem of libraryItemsWithIssues) {
|
||||
let mediaItemIds = []
|
||||
if (library.isPodcast) {
|
||||
if (req.library.isPodcast) {
|
||||
mediaItemIds = libraryItem.media.podcastEpisodes.map(pe => pe.id)
|
||||
} else {
|
||||
mediaItemIds.push(libraryItem.mediaId)
|
||||
|
|
@ -516,19 +528,22 @@ class LibraryController {
|
|||
await this.handleDeleteLibraryItem(libraryItem.mediaType, libraryItem.id, mediaItemIds)
|
||||
}
|
||||
|
||||
// Set numIssues to 0 for library filter data
|
||||
if (Database.libraryFilterData[req.library.id]) {
|
||||
Database.libraryFilterData[req.library.id].numIssues = 0
|
||||
}
|
||||
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/libraries/:id/series
|
||||
* Optional query string: `?include=rssfeed` that adds `rssFeed` to series if a feed is open
|
||||
*
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
*/
|
||||
* GET: /api/libraries/:id/series
|
||||
* Optional query string: `?include=rssfeed` that adds `rssFeed` to series if a feed is open
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getAllSeriesForLibrary(req, res) {
|
||||
const libraryItems = req.libraryItems
|
||||
|
||||
const include = (req.query.include || '').split(',').map(v => v.trim().toLowerCase()).filter(v => !!v)
|
||||
|
||||
const payload = {
|
||||
|
|
@ -543,45 +558,10 @@ class LibraryController {
|
|||
include: include.join(',')
|
||||
}
|
||||
|
||||
let series = libraryHelpers.getSeriesFromBooks(libraryItems, Database.series, null, payload.filterBy, req.user, payload.minified, req.library.settings.hideSingleBookSeries)
|
||||
|
||||
const direction = payload.sortDesc ? 'desc' : 'asc'
|
||||
series = naturalSort(series).by([
|
||||
{
|
||||
[direction]: (se) => {
|
||||
if (payload.sortBy === 'numBooks') {
|
||||
return se.books.length
|
||||
} else if (payload.sortBy === 'totalDuration') {
|
||||
return se.totalDuration
|
||||
} else if (payload.sortBy === 'addedAt') {
|
||||
return se.addedAt
|
||||
} else if (payload.sortBy === 'lastBookUpdated') {
|
||||
return Math.max(...(se.books).map(x => x.updatedAt), 0)
|
||||
} else if (payload.sortBy === 'lastBookAdded') {
|
||||
return Math.max(...(se.books).map(x => x.addedAt), 0)
|
||||
} else { // sort by name
|
||||
return Database.serverSettings.sortingIgnorePrefix ? se.nameIgnorePrefixSort : se.name
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
payload.total = series.length
|
||||
|
||||
if (payload.limit) {
|
||||
const startIndex = payload.page * payload.limit
|
||||
series = series.slice(startIndex, startIndex + payload.limit)
|
||||
}
|
||||
|
||||
// add rssFeed when "include=rssfeed" is in query string
|
||||
if (include.includes('rssfeed')) {
|
||||
series = await Promise.all(series.map(async (se) => {
|
||||
const feedData = await this.rssFeedManager.findFeedForEntityId(se.id)
|
||||
se.rssFeed = feedData?.toJSONMinified() || null
|
||||
return se
|
||||
}))
|
||||
}
|
||||
const offset = payload.page * payload.limit
|
||||
const { series, count } = await seriesFilters.getFilteredSeries(req.library, req.user, payload.filterBy, payload.sortBy, payload.sortDesc, include, payload.limit, offset)
|
||||
|
||||
payload.total = count
|
||||
payload.results = series
|
||||
res.json(payload)
|
||||
}
|
||||
|
|
@ -644,7 +624,7 @@ class LibraryController {
|
|||
}
|
||||
|
||||
// TODO: Create paginated queries
|
||||
let collections = await Database.models.collection.getOldCollectionsJsonExpanded(req.user, req.library.id, include)
|
||||
let collections = await Database.collectionModel.getOldCollectionsJsonExpanded(req.user, req.library.id, include)
|
||||
|
||||
payload.total = collections.length
|
||||
|
||||
|
|
@ -664,7 +644,7 @@ class LibraryController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async getUserPlaylistsForLibrary(req, res) {
|
||||
let playlistsForUser = await Database.models.playlist.getPlaylistsForUserAndLibrary(req.user.id, req.library.id)
|
||||
let playlistsForUser = await Database.playlistModel.getPlaylistsForUserAndLibrary(req.user.id, req.library.id)
|
||||
playlistsForUser = await Promise.all(playlistsForUser.map(async p => p.getOldJsonExpanded()))
|
||||
|
||||
const payload = {
|
||||
|
|
@ -685,8 +665,8 @@ class LibraryController {
|
|||
|
||||
/**
|
||||
* GET: /api/libraries/:id/filterdata
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getLibraryFilterData(req, res) {
|
||||
const filterData = await libraryFilters.getFilterData(req.library)
|
||||
|
|
@ -694,44 +674,30 @@ class LibraryController {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET: /api/libraries/:id/personalized2
|
||||
* TODO: new endpoint
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* GET: /api/libraries/:id/personalized
|
||||
* Home page shelves
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getUserPersonalizedShelves(req, res) {
|
||||
const limitPerShelf = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) || 10 : 10
|
||||
const include = (req.query.include || '').split(',').map(v => v.trim().toLowerCase()).filter(v => !!v)
|
||||
const shelves = await Database.models.libraryItem.getPersonalizedShelves(req.library, req.user, include, limitPerShelf)
|
||||
const shelves = await Database.libraryItemModel.getPersonalizedShelves(req.library, req.user, include, limitPerShelf)
|
||||
res.json(shelves)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/libraries/:id/personalized
|
||||
* TODO: remove after personalized2 is ready
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
*/
|
||||
async getLibraryUserPersonalizedOptimal(req, res) {
|
||||
const limitPerShelf = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) || 10 : 10
|
||||
const include = (req.query.include || '').split(',').map(v => v.trim().toLowerCase()).filter(v => !!v)
|
||||
|
||||
const categories = await libraryHelpers.buildPersonalizedShelves(this, req.user, req.libraryItems, req.library, limitPerShelf, include)
|
||||
res.json(categories)
|
||||
}
|
||||
|
||||
/**
|
||||
* POST: /api/libraries/order
|
||||
* Change the display order of libraries
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async reorder(req, res) {
|
||||
if (!req.user.isAdminOrUp) {
|
||||
Logger.error('[LibraryController] ReorderLibraries invalid user', req.user)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
const libraries = await Database.models.library.getAllOldLibraries()
|
||||
const libraries = await Database.libraryModel.getAllOldLibraries()
|
||||
|
||||
const orderdata = req.body
|
||||
let hasUpdates = false
|
||||
|
|
@ -759,99 +725,62 @@ class LibraryController {
|
|||
})
|
||||
}
|
||||
|
||||
// GET: Global library search
|
||||
search(req, res) {
|
||||
/**
|
||||
* GET: /api/libraries/:id/search
|
||||
* Search library items with query
|
||||
* ?q=search
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async search(req, res) {
|
||||
if (!req.query.q) {
|
||||
return res.status(400).send('No query string')
|
||||
}
|
||||
const libraryItems = req.libraryItems
|
||||
const maxResults = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 12
|
||||
const limit = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 12
|
||||
const query = req.query.q.trim().toLowerCase()
|
||||
|
||||
const itemMatches = []
|
||||
const authorMatches = {}
|
||||
const narratorMatches = {}
|
||||
const seriesMatches = {}
|
||||
const tagMatches = {}
|
||||
|
||||
libraryItems.forEach((li) => {
|
||||
const queryResult = li.searchQuery(req.query.q)
|
||||
if (queryResult.matchKey) {
|
||||
itemMatches.push({
|
||||
libraryItem: li.toJSONExpanded(),
|
||||
matchKey: queryResult.matchKey,
|
||||
matchText: queryResult.matchText
|
||||
})
|
||||
}
|
||||
if (queryResult.series?.length) {
|
||||
queryResult.series.forEach((se) => {
|
||||
if (!seriesMatches[se.id]) {
|
||||
const _series = Database.series.find(_se => _se.id === se.id)
|
||||
if (_series) seriesMatches[se.id] = { series: _series.toJSON(), books: [li.toJSON()] }
|
||||
} else {
|
||||
seriesMatches[se.id].books.push(li.toJSON())
|
||||
}
|
||||
})
|
||||
}
|
||||
if (queryResult.authors?.length) {
|
||||
queryResult.authors.forEach((au) => {
|
||||
if (!authorMatches[au.id]) {
|
||||
const _author = Database.authors.find(_au => _au.id === au.id)
|
||||
if (_author) {
|
||||
authorMatches[au.id] = _author.toJSON()
|
||||
authorMatches[au.id].numBooks = 1
|
||||
}
|
||||
} else {
|
||||
authorMatches[au.id].numBooks++
|
||||
}
|
||||
})
|
||||
}
|
||||
if (queryResult.tags?.length) {
|
||||
queryResult.tags.forEach((tag) => {
|
||||
if (!tagMatches[tag]) {
|
||||
tagMatches[tag] = { name: tag, books: [li.toJSON()] }
|
||||
} else {
|
||||
tagMatches[tag].books.push(li.toJSON())
|
||||
}
|
||||
})
|
||||
}
|
||||
if (queryResult.narrators?.length) {
|
||||
queryResult.narrators.forEach((narrator) => {
|
||||
if (!narratorMatches[narrator]) {
|
||||
narratorMatches[narrator] = { name: narrator, books: [li.toJSON()] }
|
||||
} else {
|
||||
narratorMatches[narrator].books.push(li.toJSON())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
const itemKey = req.library.mediaType
|
||||
const results = {
|
||||
[itemKey]: itemMatches.slice(0, maxResults),
|
||||
tags: Object.values(tagMatches).slice(0, maxResults),
|
||||
authors: Object.values(authorMatches).slice(0, maxResults),
|
||||
series: Object.values(seriesMatches).slice(0, maxResults),
|
||||
narrators: Object.values(narratorMatches).slice(0, maxResults)
|
||||
}
|
||||
res.json(results)
|
||||
const matches = await libraryItemFilters.search(req.user, req.library, query, limit)
|
||||
res.json(matches)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/libraries/:id/stats
|
||||
* Get stats for library
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async stats(req, res) {
|
||||
var libraryItems = req.libraryItems
|
||||
var authorsWithCount = libraryHelpers.getAuthorsWithCount(libraryItems)
|
||||
var genresWithCount = libraryHelpers.getGenresWithCount(libraryItems)
|
||||
var durationStats = libraryHelpers.getItemDurationStats(libraryItems)
|
||||
var sizeStats = libraryHelpers.getItemSizeStats(libraryItems)
|
||||
var stats = {
|
||||
totalItems: libraryItems.length,
|
||||
totalAuthors: Object.keys(authorsWithCount).length,
|
||||
totalGenres: Object.keys(genresWithCount).length,
|
||||
totalDuration: durationStats.totalDuration,
|
||||
longestItems: durationStats.longestItems,
|
||||
numAudioTracks: durationStats.numAudioTracks,
|
||||
totalSize: libraryHelpers.getLibraryItemsTotalSize(libraryItems),
|
||||
largestItems: sizeStats.largestItems,
|
||||
authorsWithCount,
|
||||
genresWithCount
|
||||
const stats = {
|
||||
largestItems: await libraryItemFilters.getLargestItems(req.library.id, 10)
|
||||
}
|
||||
|
||||
if (req.library.isBook) {
|
||||
const authors = await authorFilters.getAuthorsWithCount(req.library.id)
|
||||
const genres = await libraryItemsBookFilters.getGenresWithCount(req.library.id)
|
||||
const bookStats = await libraryItemsBookFilters.getBookLibraryStats(req.library.id)
|
||||
const longestBooks = await libraryItemsBookFilters.getLongestBooks(req.library.id, 10)
|
||||
|
||||
stats.totalAuthors = authors.length
|
||||
stats.authorsWithCount = authors
|
||||
stats.totalGenres = genres.length
|
||||
stats.genresWithCount = genres
|
||||
stats.totalItems = bookStats.totalItems
|
||||
stats.longestItems = longestBooks
|
||||
stats.totalSize = bookStats.totalSize
|
||||
stats.totalDuration = bookStats.totalDuration
|
||||
stats.numAudioTracks = bookStats.numAudioFiles
|
||||
} else {
|
||||
const genres = await libraryItemsPodcastFilters.getGenresWithCount(req.library.id)
|
||||
const podcastStats = await libraryItemsPodcastFilters.getPodcastLibraryStats(req.library.id)
|
||||
const longestPodcasts = await libraryItemsPodcastFilters.getLongestPodcasts(req.library.id, 10)
|
||||
|
||||
stats.totalGenres = genres.length
|
||||
stats.genresWithCount = genres
|
||||
stats.totalItems = podcastStats.totalItems
|
||||
stats.longestItems = longestPodcasts
|
||||
stats.totalSize = podcastStats.totalSize
|
||||
stats.totalDuration = podcastStats.totalDuration
|
||||
stats.numAudioTracks = podcastStats.numAudioFiles
|
||||
}
|
||||
res.json(stats)
|
||||
}
|
||||
|
|
@ -859,18 +788,18 @@ class LibraryController {
|
|||
/**
|
||||
* GET: /api/libraries/:id/authors
|
||||
* Get authors for library
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getAuthors(req, res) {
|
||||
const { bookWhere, replacements } = libraryItemsBookFilters.getUserPermissionBookWhereQuery(req.user)
|
||||
const authors = await Database.models.author.findAll({
|
||||
const authors = await Database.authorModel.findAll({
|
||||
where: {
|
||||
libraryId: req.library.id
|
||||
},
|
||||
replacements,
|
||||
include: {
|
||||
model: Database.models.book,
|
||||
model: Database.bookModel,
|
||||
attributes: ['id', 'tags', 'explicit'],
|
||||
where: bookWhere,
|
||||
required: true,
|
||||
|
|
@ -903,12 +832,12 @@ class LibraryController {
|
|||
*/
|
||||
async getNarrators(req, res) {
|
||||
// Get all books with narrators
|
||||
const booksWithNarrators = await Database.models.book.findAll({
|
||||
const booksWithNarrators = await Database.bookModel.findAll({
|
||||
where: Sequelize.where(Sequelize.fn('json_array_length', Sequelize.col('narrators')), {
|
||||
[Sequelize.Op.gt]: 0
|
||||
}),
|
||||
include: {
|
||||
model: Database.models.libraryItem,
|
||||
model: Database.libraryItemModel,
|
||||
attributes: ['id', 'libraryId'],
|
||||
where: {
|
||||
libraryId: req.library.id
|
||||
|
|
@ -975,7 +904,7 @@ class LibraryController {
|
|||
await libraryItem.media.update({
|
||||
narrators: libraryItem.media.narrators
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
itemsUpdated.push(oldLibraryItem)
|
||||
}
|
||||
|
||||
|
|
@ -1015,7 +944,7 @@ class LibraryController {
|
|||
await libraryItem.media.update({
|
||||
narrators: libraryItem.media.narrators
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
itemsUpdated.push(oldLibraryItem)
|
||||
}
|
||||
|
||||
|
|
@ -1048,10 +977,16 @@ class LibraryController {
|
|||
}
|
||||
res.sendStatus(200)
|
||||
await this.scanner.scan(req.library, options)
|
||||
await Database.resetLibraryIssuesFilterData(req.library.id)
|
||||
Logger.info('[LibraryController] Scan complete')
|
||||
}
|
||||
|
||||
// GET: api/libraries/:id/recent-episode
|
||||
/**
|
||||
* GET: /api/libraries/:id/recent-episodes
|
||||
* Used for latest page
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getRecentEpisodes(req, res) {
|
||||
if (!req.library.isPodcast) {
|
||||
return res.sendStatus(404)
|
||||
|
|
@ -1059,40 +994,37 @@ class LibraryController {
|
|||
|
||||
const payload = {
|
||||
episodes: [],
|
||||
total: 0,
|
||||
limit: req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 0,
|
||||
page: req.query.page && !isNaN(req.query.page) ? Number(req.query.page) : 0,
|
||||
}
|
||||
|
||||
var allUnfinishedEpisodes = []
|
||||
for (const libraryItem of req.libraryItems) {
|
||||
const unfinishedEpisodes = libraryItem.media.episodes.filter(ep => {
|
||||
const userProgress = req.user.getMediaProgress(libraryItem.id, ep.id)
|
||||
return !userProgress || !userProgress.isFinished
|
||||
}).map(_ep => {
|
||||
const ep = _ep.toJSONExpanded()
|
||||
ep.podcast = libraryItem.media.toJSONMinified()
|
||||
ep.libraryItemId = libraryItem.id
|
||||
ep.libraryId = libraryItem.libraryId
|
||||
return ep
|
||||
})
|
||||
allUnfinishedEpisodes.push(...unfinishedEpisodes)
|
||||
}
|
||||
|
||||
payload.total = allUnfinishedEpisodes.length
|
||||
|
||||
allUnfinishedEpisodes = sort(allUnfinishedEpisodes).desc(ep => ep.publishedAt)
|
||||
|
||||
if (payload.limit) {
|
||||
var startIndex = payload.page * payload.limit
|
||||
allUnfinishedEpisodes = allUnfinishedEpisodes.slice(startIndex, startIndex + payload.limit)
|
||||
}
|
||||
payload.episodes = allUnfinishedEpisodes
|
||||
const offset = payload.page * payload.limit
|
||||
payload.episodes = await libraryItemsPodcastFilters.getRecentEpisodes(req.user, req.library, payload.limit, offset)
|
||||
res.json(payload)
|
||||
}
|
||||
|
||||
getOPMLFile(req, res) {
|
||||
const opmlText = this.podcastManager.generateOPMLFileText(req.libraryItems)
|
||||
/**
|
||||
* GET: /api/libraries/:id/opml
|
||||
* Get OPML file for a podcast library
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getOPMLFile(req, res) {
|
||||
const userPermissionPodcastWhere = libraryItemsPodcastFilters.getUserPermissionPodcastWhereQuery(req.user)
|
||||
const podcasts = await Database.podcastModel.findAll({
|
||||
attributes: ['id', 'feedURL', 'title', 'description', 'itunesPageURL', 'language'],
|
||||
where: userPermissionPodcastWhere.podcastWhere,
|
||||
replacements: userPermissionPodcastWhere.replacements,
|
||||
include: {
|
||||
model: Database.libraryItemModel,
|
||||
attributes: ['id', 'libraryId'],
|
||||
where: {
|
||||
libraryId: req.library.id
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const opmlText = this.podcastManager.generateOPMLFileText(podcasts)
|
||||
res.type('application/xml')
|
||||
res.send(opmlText)
|
||||
}
|
||||
|
|
@ -1109,7 +1041,7 @@ class LibraryController {
|
|||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
const library = await Database.models.library.getOldById(req.params.id)
|
||||
const library = await Database.libraryModel.getOldById(req.params.id)
|
||||
if (!library) {
|
||||
return res.status(404).send('Library not found')
|
||||
}
|
||||
|
|
@ -1122,9 +1054,9 @@ class LibraryController {
|
|||
|
||||
/**
|
||||
* Middleware that is not using libraryItems from memory
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @param {*} next
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
* @param {import('express').NextFunction} next
|
||||
*/
|
||||
async middlewareNew(req, res, next) {
|
||||
if (!req.user.checkCanAccessLibrary(req.params.id)) {
|
||||
|
|
@ -1132,7 +1064,7 @@ class LibraryController {
|
|||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
const library = await Database.models.library.getOldById(req.params.id)
|
||||
const library = await Database.libraryModel.getOldById(req.params.id)
|
||||
if (!library) {
|
||||
return res.status(404).send('Library not found')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class LibraryItemController {
|
|||
Logger.error(`[LibraryItemController] Failed to delete library item from file system at "${libraryItemPath}"`, error)
|
||||
})
|
||||
}
|
||||
await Database.resetLibraryIssuesFilterData(req.libraryItem.libraryId)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +125,7 @@ class LibraryItemController {
|
|||
// Book specific - Get all series being removed from this item
|
||||
let seriesRemoved = []
|
||||
if (libraryItem.isBook && mediaPayload.metadata?.series) {
|
||||
const seriesIdsInUpdate = (mediaPayload.metadata?.series || []).map(se => se.id)
|
||||
const seriesIdsInUpdate = mediaPayload.metadata.series?.map(se => se.id) || []
|
||||
seriesRemoved = libraryItem.media.metadata.series.filter(se => !seriesIdsInUpdate.includes(se.id))
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +314,7 @@ class LibraryItemController {
|
|||
return res.status(400).send('Invalid request body')
|
||||
}
|
||||
|
||||
const itemsToDelete = await Database.models.libraryItem.getAllOldLibraryItems({
|
||||
const itemsToDelete = await Database.libraryItemModel.getAllOldLibraryItems({
|
||||
id: libraryItemIds
|
||||
})
|
||||
|
||||
|
|
@ -332,6 +333,8 @@ class LibraryItemController {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
await Database.resetLibraryIssuesFilterData(req.libraryItem.libraryId)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +349,7 @@ class LibraryItemController {
|
|||
|
||||
for (const updatePayload of updatePayloads) {
|
||||
const mediaPayload = updatePayload.mediaPayload
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(updatePayload.id)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(updatePayload.id)
|
||||
if (!libraryItem) return null
|
||||
|
||||
await this.createAuthorsAndSeriesForItemUpdate(mediaPayload, libraryItem.libraryId)
|
||||
|
|
@ -384,7 +387,7 @@ class LibraryItemController {
|
|||
if (!libraryItemIds.length) {
|
||||
return res.status(403).send('Invalid payload')
|
||||
}
|
||||
const libraryItems = await Database.models.libraryItem.getAllOldLibraryItems({
|
||||
const libraryItems = await Database.libraryItemModel.getAllOldLibraryItems({
|
||||
id: libraryItemIds
|
||||
})
|
||||
res.json({
|
||||
|
|
@ -456,9 +459,11 @@ class LibraryItemController {
|
|||
await this.scanner.scanLibraryItemByRequest(libraryItem)
|
||||
}
|
||||
}
|
||||
|
||||
await Database.resetLibraryIssuesFilterData(req.libraryItem.libraryId)
|
||||
}
|
||||
|
||||
// POST: api/items/:id/scan (admin)
|
||||
// POST: api/items/:id/scan
|
||||
async scan(req, res) {
|
||||
if (!req.user.isAdminOrUp) {
|
||||
Logger.error(`[LibraryItemController] Non-admin user attempted to scan library item`, req.user)
|
||||
|
|
@ -471,6 +476,7 @@ class LibraryItemController {
|
|||
}
|
||||
|
||||
const result = await this.scanner.scanLibraryItemByRequest(req.libraryItem)
|
||||
await Database.resetLibraryIssuesFilterData(req.libraryItem.libraryId)
|
||||
res.json({
|
||||
result: Object.keys(ScanResult).find(key => ScanResult[key] == result)
|
||||
})
|
||||
|
|
@ -694,7 +700,7 @@ class LibraryItemController {
|
|||
}
|
||||
|
||||
async middleware(req, res, next) {
|
||||
req.libraryItem = await Database.models.libraryItem.getOldById(req.params.id)
|
||||
req.libraryItem = await Database.libraryItemModel.getOldById(req.params.id)
|
||||
if (!req.libraryItem?.media) return res.sendStatus(404)
|
||||
|
||||
// Check user can access this library item
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class MeController {
|
|||
|
||||
// PATCH: api/me/progress/:id
|
||||
async createUpdateMediaProgress(req, res) {
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(req.params.id)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(req.params.id)
|
||||
if (!libraryItem) {
|
||||
return res.status(404).send('Item not found')
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ class MeController {
|
|||
// PATCH: api/me/progress/:id/:episodeId
|
||||
async createUpdateEpisodeMediaProgress(req, res) {
|
||||
const episodeId = req.params.episodeId
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(req.params.id)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(req.params.id)
|
||||
if (!libraryItem) {
|
||||
return res.status(404).send('Item not found')
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ class MeController {
|
|||
|
||||
let shouldUpdate = false
|
||||
for (const itemProgress of itemProgressPayloads) {
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(itemProgress.libraryItemId)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(itemProgress.libraryItemId)
|
||||
if (libraryItem) {
|
||||
if (req.user.createUpdateMediaProgress(libraryItem, itemProgress, itemProgress.episodeId)) {
|
||||
const mediaProgress = req.user.getMediaProgress(libraryItem.id, itemProgress.episodeId)
|
||||
|
|
@ -122,7 +122,7 @@ class MeController {
|
|||
|
||||
// POST: api/me/item/:id/bookmark
|
||||
async createBookmark(req, res) {
|
||||
if (!await Database.models.libraryItem.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
if (!await Database.libraryItemModel.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
|
||||
const { time, title } = req.body
|
||||
const bookmark = req.user.createBookmark(req.params.id, time, title)
|
||||
|
|
@ -133,7 +133,7 @@ class MeController {
|
|||
|
||||
// PATCH: api/me/item/:id/bookmark
|
||||
async updateBookmark(req, res) {
|
||||
if (!await Database.models.libraryItem.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
if (!await Database.libraryItemModel.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
|
||||
const { time, title } = req.body
|
||||
if (!req.user.findBookmark(req.params.id, time)) {
|
||||
|
|
@ -151,7 +151,7 @@ class MeController {
|
|||
|
||||
// DELETE: api/me/item/:id/bookmark/:time
|
||||
async removeBookmark(req, res) {
|
||||
if (!await Database.models.libraryItem.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
if (!await Database.libraryItemModel.checkExistsById(req.params.id)) return res.sendStatus(404)
|
||||
|
||||
const time = Number(req.params.time)
|
||||
if (isNaN(time)) return res.sendStatus(500)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class MiscController {
|
|||
const libraryId = req.body.library
|
||||
const folderId = req.body.folder
|
||||
|
||||
const library = await Database.models.library.getOldById(libraryId)
|
||||
const library = await Database.libraryModel.getOldById(libraryId)
|
||||
if (!library) {
|
||||
return res.status(404).send(`Library not found with id ${libraryId}`)
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ class MiscController {
|
|||
}
|
||||
|
||||
const tags = []
|
||||
const books = await Database.models.book.findAll({
|
||||
const books = await Database.bookModel.findAll({
|
||||
attributes: ['tags'],
|
||||
where: Sequelize.where(Sequelize.fn('json_array_length', Sequelize.col('tags')), {
|
||||
[Sequelize.Op.gt]: 0
|
||||
|
|
@ -189,7 +189,7 @@ class MiscController {
|
|||
}
|
||||
}
|
||||
|
||||
const podcasts = await Database.models.podcast.findAll({
|
||||
const podcasts = await Database.podcastModel.findAll({
|
||||
attributes: ['tags'],
|
||||
where: Sequelize.where(Sequelize.fn('json_array_length', Sequelize.col('tags')), {
|
||||
[Sequelize.Op.gt]: 0
|
||||
|
|
@ -248,7 +248,7 @@ class MiscController {
|
|||
await libraryItem.media.update({
|
||||
tags: libraryItem.media.tags
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
|
||||
numItemsUpdated++
|
||||
}
|
||||
|
|
@ -289,7 +289,7 @@ class MiscController {
|
|||
await libraryItem.media.update({
|
||||
tags: libraryItem.media.tags
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
|
||||
numItemsUpdated++
|
||||
}
|
||||
|
|
@ -311,7 +311,7 @@ class MiscController {
|
|||
return res.sendStatus(404)
|
||||
}
|
||||
const genres = []
|
||||
const books = await Database.models.book.findAll({
|
||||
const books = await Database.bookModel.findAll({
|
||||
attributes: ['genres'],
|
||||
where: Sequelize.where(Sequelize.fn('json_array_length', Sequelize.col('genres')), {
|
||||
[Sequelize.Op.gt]: 0
|
||||
|
|
@ -323,7 +323,7 @@ class MiscController {
|
|||
}
|
||||
}
|
||||
|
||||
const podcasts = await Database.models.podcast.findAll({
|
||||
const podcasts = await Database.podcastModel.findAll({
|
||||
attributes: ['genres'],
|
||||
where: Sequelize.where(Sequelize.fn('json_array_length', Sequelize.col('genres')), {
|
||||
[Sequelize.Op.gt]: 0
|
||||
|
|
@ -382,7 +382,7 @@ class MiscController {
|
|||
await libraryItem.media.update({
|
||||
genres: libraryItem.media.genres
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
|
||||
numItemsUpdated++
|
||||
}
|
||||
|
|
@ -423,7 +423,7 @@ class MiscController {
|
|||
await libraryItem.media.update({
|
||||
genres: libraryItem.media.genres
|
||||
})
|
||||
const oldLibraryItem = Database.models.libraryItem.getOldLibraryItem(libraryItem)
|
||||
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
|
||||
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
|
||||
numItemsUpdated++
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ class PlaylistController {
|
|||
}
|
||||
|
||||
// Create Playlist record
|
||||
const newPlaylist = await Database.models.playlist.createFromOld(oldPlaylist)
|
||||
const newPlaylist = await Database.playlistModel.createFromOld(oldPlaylist)
|
||||
|
||||
// Lookup all library items in playlist
|
||||
const libraryItemIds = oldPlaylist.items.map(i => i.libraryItemId).filter(i => i)
|
||||
const libraryItemsInPlaylist = await Database.models.libraryItem.findAll({
|
||||
const libraryItemsInPlaylist = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: libraryItemIds
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ class PlaylistController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async findAllForUser(req, res) {
|
||||
const playlistsForUser = await Database.models.playlist.findAll({
|
||||
const playlistsForUser = await Database.playlistModel.findAll({
|
||||
where: {
|
||||
userId: req.user.id
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ class PlaylistController {
|
|||
// If array of items is passed in then update order of playlist media items
|
||||
const libraryItemIds = req.body.items?.map(i => i.libraryItemId).filter(i => i) || []
|
||||
if (libraryItemIds.length) {
|
||||
const libraryItems = await Database.models.libraryItem.findAll({
|
||||
const libraryItems = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: libraryItemIds
|
||||
}
|
||||
|
|
@ -173,14 +173,14 @@ class PlaylistController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async addItem(req, res) {
|
||||
const oldPlaylist = await Database.models.playlist.getById(req.playlist.id)
|
||||
const oldPlaylist = await Database.playlistModel.getById(req.playlist.id)
|
||||
const itemToAdd = req.body
|
||||
|
||||
if (!itemToAdd.libraryItemId) {
|
||||
return res.status(400).send('Request body has no libraryItemId')
|
||||
}
|
||||
|
||||
const libraryItem = await Database.models.libraryItem.getOldById(itemToAdd.libraryItemId)
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(itemToAdd.libraryItemId)
|
||||
if (!libraryItem) {
|
||||
return res.status(400).send('Library item not found')
|
||||
}
|
||||
|
|
@ -217,7 +217,7 @@ class PlaylistController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async removeItem(req, res) {
|
||||
const oldLibraryItem = await Database.models.libraryItem.getOldById(req.params.libraryItemId)
|
||||
const oldLibraryItem = await Database.libraryItemModel.getOldById(req.params.libraryItemId)
|
||||
if (!oldLibraryItem) {
|
||||
return res.status(404).send('Library item not found')
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ class PlaylistController {
|
|||
}
|
||||
|
||||
// Find all library items
|
||||
const libraryItems = await Database.models.libraryItem.findAll({
|
||||
const libraryItems = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: libraryItemIds
|
||||
}
|
||||
|
|
@ -345,7 +345,7 @@ class PlaylistController {
|
|||
}
|
||||
|
||||
// Find all library items
|
||||
const libraryItems = await Database.models.libraryItem.findAll({
|
||||
const libraryItems = await Database.libraryItemModel.findAll({
|
||||
where: {
|
||||
id: libraryItemIds
|
||||
}
|
||||
|
|
@ -391,7 +391,7 @@ class PlaylistController {
|
|||
* @param {*} res
|
||||
*/
|
||||
async createFromCollection(req, res) {
|
||||
const collection = await Database.models.collection.findByPk(req.params.collectionId)
|
||||
const collection = await Database.collectionModel.findByPk(req.params.collectionId)
|
||||
if (!collection) {
|
||||
return res.status(404).send('Collection not found')
|
||||
}
|
||||
|
|
@ -416,7 +416,7 @@ class PlaylistController {
|
|||
})
|
||||
|
||||
// Create Playlist record
|
||||
const newPlaylist = await Database.models.playlist.createFromOld(oldPlaylist)
|
||||
const newPlaylist = await Database.playlistModel.createFromOld(oldPlaylist)
|
||||
|
||||
// Create PlaylistMediaItem records
|
||||
const mediaItemsToAdd = []
|
||||
|
|
@ -438,7 +438,7 @@ class PlaylistController {
|
|||
|
||||
async middleware(req, res, next) {
|
||||
if (req.params.id) {
|
||||
const playlist = await Database.models.playlist.findByPk(req.params.id)
|
||||
const playlist = await Database.playlistModel.findByPk(req.params.id)
|
||||
if (!playlist) {
|
||||
return res.status(404).send('Playlist not found')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class PodcastController {
|
|||
}
|
||||
const payload = req.body
|
||||
|
||||
const library = await Database.models.library.getOldById(payload.libraryId)
|
||||
const library = await Database.libraryModel.getOldById(payload.libraryId)
|
||||
if (!library) {
|
||||
Logger.error(`[PodcastController] Create: Library not found "${payload.libraryId}"`)
|
||||
return res.status(404).send('Library not found')
|
||||
|
|
@ -34,7 +34,7 @@ class PodcastController {
|
|||
const podcastPath = filePathToPOSIX(payload.path)
|
||||
|
||||
// Check if a library item with this podcast folder exists already
|
||||
const existingLibraryItem = (await Database.models.libraryItem.count({
|
||||
const existingLibraryItem = (await Database.libraryItemModel.count({
|
||||
where: {
|
||||
path: podcastPath
|
||||
}
|
||||
|
|
@ -272,13 +272,13 @@ class PodcastController {
|
|||
}
|
||||
|
||||
// Update/remove playlists that had this podcast episode
|
||||
const playlistMediaItems = await Database.models.playlistMediaItem.findAll({
|
||||
const playlistMediaItems = await Database.playlistMediaItemModel.findAll({
|
||||
where: {
|
||||
mediaItemId: episodeId
|
||||
},
|
||||
include: {
|
||||
model: Database.models.playlist,
|
||||
include: Database.models.playlistMediaItem
|
||||
model: Database.playlistModel,
|
||||
include: Database.playlistMediaItemModel
|
||||
}
|
||||
})
|
||||
for (const pmi of playlistMediaItems) {
|
||||
|
|
@ -297,7 +297,7 @@ class PodcastController {
|
|||
}
|
||||
|
||||
// Remove media progress for this episode
|
||||
const mediaProgressRemoved = await Database.models.mediaProgress.destroy({
|
||||
const mediaProgressRemoved = await Database.mediaProgressModel.destroy({
|
||||
where: {
|
||||
mediaItemId: episode.id
|
||||
}
|
||||
|
|
@ -312,7 +312,7 @@ class PodcastController {
|
|||
}
|
||||
|
||||
async middleware(req, res, next) {
|
||||
const item = await Database.models.libraryItem.getOldById(req.params.id)
|
||||
const item = await Database.libraryItemModel.getOldById(req.params.id)
|
||||
if (!item?.media) return res.sendStatus(404)
|
||||
|
||||
if (!item.isPodcast) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class RSSFeedController {
|
|||
async openRSSFeedForItem(req, res) {
|
||||
const options = req.body || {}
|
||||
|
||||
const item = await Database.models.libraryItem.getOldById(req.params.itemId)
|
||||
const item = await Database.libraryItemModel.getOldById(req.params.itemId)
|
||||
if (!item) return res.sendStatus(404)
|
||||
|
||||
// Check user can access this library item
|
||||
|
|
@ -54,7 +54,7 @@ class RSSFeedController {
|
|||
async openRSSFeedForCollection(req, res) {
|
||||
const options = req.body || {}
|
||||
|
||||
const collection = await Database.models.collection.findByPk(req.params.collectionId)
|
||||
const collection = await Database.collectionModel.findByPk(req.params.collectionId)
|
||||
if (!collection) return res.sendStatus(404)
|
||||
|
||||
// Check request body options exist
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class SessionController {
|
|||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
const minifiedUserObjects = await Database.models.user.getMinifiedUserObjects()
|
||||
const minifiedUserObjects = await Database.userModel.getMinifiedUserObjects()
|
||||
const openSessions = this.playbackSessionManager.sessions.map(se => {
|
||||
return {
|
||||
...se.toJSON(),
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ class ToolsController {
|
|||
}
|
||||
|
||||
if (req.params.id) {
|
||||
const item = await Database.models.libraryItem.getOldById(req.params.id)
|
||||
const item = await Database.libraryItemModel.getOldById(req.params.id)
|
||||
if (!item?.media) return res.sendStatus(404)
|
||||
|
||||
// Check user can access this library item
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class UserController {
|
|||
const includes = (req.query.include || '').split(',').map(i => i.trim())
|
||||
|
||||
// Minimal toJSONForBrowser does not include mediaProgress and bookmarks
|
||||
const allUsers = await Database.models.user.getOldUsers()
|
||||
const allUsers = await Database.userModel.getOldUsers()
|
||||
const users = allUsers.map(u => u.toJSONForBrowser(hideRootToken, true))
|
||||
|
||||
if (includes.includes('latestSession')) {
|
||||
|
|
@ -47,20 +47,20 @@ class UserController {
|
|||
}
|
||||
|
||||
// Get user media progress with associated mediaItem
|
||||
const mediaProgresses = await Database.models.mediaProgress.findAll({
|
||||
const mediaProgresses = await Database.mediaProgressModel.findAll({
|
||||
where: {
|
||||
userId: req.reqUser.id
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: Database.models.book,
|
||||
model: Database.bookModel,
|
||||
attributes: ['id', 'title', 'coverPath', 'updatedAt']
|
||||
},
|
||||
{
|
||||
model: Database.models.podcastEpisode,
|
||||
model: Database.podcastEpisodeModel,
|
||||
attributes: ['id', 'title'],
|
||||
include: {
|
||||
model: Database.models.podcast,
|
||||
model: Database.podcastModel,
|
||||
attributes: ['id', 'title', 'coverPath', 'updatedAt']
|
||||
}
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ class UserController {
|
|||
const account = req.body
|
||||
const username = account.username
|
||||
|
||||
const usernameExists = await Database.models.user.getUserByUsername(username)
|
||||
const usernameExists = await Database.userModel.getUserByUsername(username)
|
||||
if (usernameExists) {
|
||||
return res.status(500).send('Username already taken')
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ class UserController {
|
|||
var shouldUpdateToken = false
|
||||
|
||||
if (account.username !== undefined && account.username !== user.username) {
|
||||
const usernameExists = await Database.models.user.getUserByUsername(account.username)
|
||||
const usernameExists = await Database.userModel.getUserByUsername(account.username)
|
||||
if (usernameExists) {
|
||||
return res.status(500).send('Username already taken')
|
||||
}
|
||||
|
|
@ -169,7 +169,7 @@ class UserController {
|
|||
// Todo: check if user is logged in and cancel streams
|
||||
|
||||
// Remove user playlists
|
||||
const userPlaylists = await Database.models.playlist.findAll({
|
||||
const userPlaylists = await Database.playlistModel.findAll({
|
||||
where: {
|
||||
userId: user.id
|
||||
}
|
||||
|
|
@ -233,7 +233,7 @@ class UserController {
|
|||
}
|
||||
|
||||
if (req.params.id) {
|
||||
req.reqUser = await Database.models.user.getUserById(req.params.id)
|
||||
req.reqUser = await Database.userModel.getUserById(req.params.id)
|
||||
if (!req.reqUser) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue