mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-04-16 01:16:24 +02:00
Update recent-episodes API route to load from db
This commit is contained in:
parent
f21d69339f
commit
8d451217a3
@ -59,6 +59,16 @@ class Database {
|
|||||||
return this.models.libraryItem
|
return this.models.libraryItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {typeof import('./models/PodcastEpisode')} */
|
||||||
|
get podcastEpisodeModel() {
|
||||||
|
return this.models.podcastEpisode
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {typeof import('./models/MediaProgress')} */
|
||||||
|
get mediaProgressModel() {
|
||||||
|
return this.models.mediaProgress
|
||||||
|
}
|
||||||
|
|
||||||
async checkHasDb() {
|
async checkHasDb() {
|
||||||
if (!await fs.pathExists(this.dbPath)) {
|
if (!await fs.pathExists(this.dbPath)) {
|
||||||
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)
|
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)
|
||||||
|
@ -16,6 +16,7 @@ const naturalSort = createNewSortInstance({
|
|||||||
|
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
const libraryFilters = require('../utils/queries/libraryFilters')
|
const libraryFilters = require('../utils/queries/libraryFilters')
|
||||||
|
const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters')
|
||||||
|
|
||||||
class LibraryController {
|
class LibraryController {
|
||||||
constructor() { }
|
constructor() { }
|
||||||
@ -1024,7 +1025,12 @@ class LibraryController {
|
|||||||
Logger.info('[LibraryController] Scan complete')
|
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) {
|
async getRecentEpisodes(req, res) {
|
||||||
if (!req.library.isPodcast) {
|
if (!req.library.isPodcast) {
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
@ -1032,35 +1038,12 @@ class LibraryController {
|
|||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
episodes: [],
|
episodes: [],
|
||||||
total: 0,
|
|
||||||
limit: req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 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,
|
page: req.query.page && !isNaN(req.query.page) ? Number(req.query.page) : 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
var allUnfinishedEpisodes = []
|
const offset = payload.page * payload.limit
|
||||||
for (const libraryItem of req.libraryItems) {
|
payload.episodes = await libraryItemsPodcastFilters.getRecentEpisodes(req.user, req.library, payload.limit, offset)
|
||||||
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
|
|
||||||
res.json(payload)
|
res.json(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class Podcast extends Model {
|
|||||||
|
|
||||||
static getOldPodcast(libraryItemExpanded) {
|
static getOldPodcast(libraryItemExpanded) {
|
||||||
const podcastExpanded = libraryItemExpanded.media
|
const podcastExpanded = libraryItemExpanded.media
|
||||||
const podcastEpisodes = podcastExpanded.podcastEpisodes?.map(ep => ep.getOldPodcastEpisode(libraryItemExpanded.id)).sort((a, b) => a.index - b.index)
|
const podcastEpisodes = podcastExpanded.podcastEpisodes?.map(ep => ep.getOldPodcastEpisode(libraryItemExpanded.id).toJSON()).sort((a, b) => a.index - b.index)
|
||||||
return {
|
return {
|
||||||
id: podcastExpanded.id,
|
id: podcastExpanded.id,
|
||||||
libraryItemId: libraryItemExpanded.id,
|
libraryItemId: libraryItemExpanded.id,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const { DataTypes, Model } = require('sequelize')
|
const { DataTypes, Model } = require('sequelize')
|
||||||
|
const oldPodcastEpisode = require('../objects/entities/PodcastEpisode')
|
||||||
|
|
||||||
class PodcastEpisode extends Model {
|
class PodcastEpisode extends Model {
|
||||||
constructor(values, options) {
|
constructor(values, options) {
|
||||||
@ -44,6 +45,10 @@ class PodcastEpisode extends Model {
|
|||||||
this.updatedAt
|
this.updatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} libraryItemId
|
||||||
|
* @returns {oldPodcastEpisode}
|
||||||
|
*/
|
||||||
getOldPodcastEpisode(libraryItemId = null) {
|
getOldPodcastEpisode(libraryItemId = null) {
|
||||||
let enclosure = null
|
let enclosure = null
|
||||||
if (this.enclosureURL) {
|
if (this.enclosureURL) {
|
||||||
@ -53,7 +58,7 @@ class PodcastEpisode extends Model {
|
|||||||
length: this.enclosureSize !== null ? String(this.enclosureSize) : null
|
length: this.enclosureSize !== null ? String(this.enclosureSize) : null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return new oldPodcastEpisode({
|
||||||
libraryItemId: libraryItemId || null,
|
libraryItemId: libraryItemId || null,
|
||||||
podcastId: this.podcastId,
|
podcastId: this.podcastId,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
@ -72,7 +77,7 @@ class PodcastEpisode extends Model {
|
|||||||
publishedAt: this.publishedAt?.valueOf() || null,
|
publishedAt: this.publishedAt?.valueOf() || null,
|
||||||
addedAt: this.createdAt.valueOf(),
|
addedAt: this.createdAt.valueOf(),
|
||||||
updatedAt: this.updatedAt.valueOf()
|
updatedAt: this.updatedAt.valueOf()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFromOld(oldEpisode) {
|
static createFromOld(oldEpisode) {
|
||||||
|
@ -94,7 +94,7 @@ class ApiRouter {
|
|||||||
this.router.delete('/libraries/:id/narrators/:narratorId', LibraryController.middlewareNew.bind(this), LibraryController.removeNarrator.bind(this))
|
this.router.delete('/libraries/:id/narrators/:narratorId', LibraryController.middlewareNew.bind(this), LibraryController.removeNarrator.bind(this))
|
||||||
this.router.get('/libraries/:id/matchall', LibraryController.middlewareNew.bind(this), LibraryController.matchAll.bind(this))
|
this.router.get('/libraries/:id/matchall', LibraryController.middlewareNew.bind(this), LibraryController.matchAll.bind(this))
|
||||||
this.router.post('/libraries/:id/scan', LibraryController.middlewareNew.bind(this), LibraryController.scan.bind(this))
|
this.router.post('/libraries/:id/scan', LibraryController.middlewareNew.bind(this), LibraryController.scan.bind(this))
|
||||||
this.router.get('/libraries/:id/recent-episodes', LibraryController.middleware.bind(this), LibraryController.getRecentEpisodes.bind(this))
|
this.router.get('/libraries/:id/recent-episodes', LibraryController.middlewareNew.bind(this), LibraryController.getRecentEpisodes.bind(this))
|
||||||
this.router.get('/libraries/:id/opml', LibraryController.middleware.bind(this), LibraryController.getOPMLFile.bind(this))
|
this.router.get('/libraries/:id/opml', LibraryController.middleware.bind(this), LibraryController.getOPMLFile.bind(this))
|
||||||
this.router.post('/libraries/order', LibraryController.reorder.bind(this))
|
this.router.post('/libraries/order', LibraryController.reorder.bind(this))
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ module.exports = {
|
|||||||
const podcast = ep.podcast.toJSON()
|
const podcast = ep.podcast.toJSON()
|
||||||
delete podcast.libraryItem
|
delete podcast.libraryItem
|
||||||
libraryItem.media = podcast
|
libraryItem.media = podcast
|
||||||
libraryItem.recentEpisode = ep.getOldPodcastEpisode(libraryItem.id)
|
libraryItem.recentEpisode = ep.getOldPodcastEpisode(libraryItem.id).toJSON()
|
||||||
return libraryItem
|
return libraryItem
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -396,5 +396,64 @@ module.exports = {
|
|||||||
podcast: itemMatches,
|
podcast: itemMatches,
|
||||||
tags: tagMatches
|
tags: tagMatches
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Most recent podcast episodes not finished
|
||||||
|
* @param {import('../../objects/user/User')} oldUser
|
||||||
|
* @param {import('../../objects/Library')} oldLibrary
|
||||||
|
* @param {number} limit
|
||||||
|
* @param {number} offset
|
||||||
|
* @returns {Promise<object[]>}
|
||||||
|
*/
|
||||||
|
async getRecentEpisodes(oldUser, oldLibrary, limit, offset) {
|
||||||
|
const userPermissionPodcastWhere = this.getUserPermissionPodcastWhereQuery(oldUser)
|
||||||
|
|
||||||
|
const episodes = await Database.podcastEpisodeModel.findAll({
|
||||||
|
where: {
|
||||||
|
'$mediaProgresses.isFinished$': {
|
||||||
|
[Sequelize.Op.or]: [null, false]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
replacements: userPermissionPodcastWhere.replacements,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Database.podcastModel,
|
||||||
|
where: userPermissionPodcastWhere.podcastWhere,
|
||||||
|
required: true,
|
||||||
|
include: {
|
||||||
|
model: Database.libraryItemModel,
|
||||||
|
where: {
|
||||||
|
libraryId: oldLibrary.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: Database.mediaProgressModel,
|
||||||
|
where: {
|
||||||
|
userId: oldUser.id
|
||||||
|
},
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
order: [
|
||||||
|
['publishedAt', 'DESC']
|
||||||
|
],
|
||||||
|
subQuery: false,
|
||||||
|
limit,
|
||||||
|
offset
|
||||||
|
})
|
||||||
|
|
||||||
|
const episodeResults = episodes.map((ep) => {
|
||||||
|
const libraryItem = ep.podcast.libraryItem
|
||||||
|
libraryItem.media = ep.podcast
|
||||||
|
const oldPodcast = Database.podcastModel.getOldPodcast(libraryItem)
|
||||||
|
const oldPodcastEpisode = ep.getOldPodcastEpisode(libraryItem.id).toJSONExpanded()
|
||||||
|
oldPodcastEpisode.podcast = oldPodcast
|
||||||
|
oldPodcastEpisode.libraryId = libraryItem.libraryId
|
||||||
|
return oldPodcastEpisode
|
||||||
|
})
|
||||||
|
|
||||||
|
return episodeResults
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user