Update recent-episodes API route to load from db

This commit is contained in:
advplyr 2023-08-19 14:49:06 -05:00
parent f21d69339f
commit 8d451217a3
6 changed files with 88 additions and 31 deletions

View File

@ -59,6 +59,16 @@ class Database {
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() {
if (!await fs.pathExists(this.dbPath)) {
Logger.info(`[Database] absdatabase.sqlite not found at ${this.dbPath}`)

View File

@ -16,6 +16,7 @@ const naturalSort = createNewSortInstance({
const Database = require('../Database')
const libraryFilters = require('../utils/queries/libraryFilters')
const libraryItemsPodcastFilters = require('../utils/queries/libraryItemsPodcastFilters')
class LibraryController {
constructor() { }
@ -1024,7 +1025,12 @@ class LibraryController {
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)
@ -1032,35 +1038,12 @@ 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)
}

View File

@ -54,7 +54,7 @@ class Podcast extends Model {
static getOldPodcast(libraryItemExpanded) {
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 {
id: podcastExpanded.id,
libraryItemId: libraryItemExpanded.id,

View File

@ -1,4 +1,5 @@
const { DataTypes, Model } = require('sequelize')
const oldPodcastEpisode = require('../objects/entities/PodcastEpisode')
class PodcastEpisode extends Model {
constructor(values, options) {
@ -44,6 +45,10 @@ class PodcastEpisode extends Model {
this.updatedAt
}
/**
* @param {string} libraryItemId
* @returns {oldPodcastEpisode}
*/
getOldPodcastEpisode(libraryItemId = null) {
let enclosure = null
if (this.enclosureURL) {
@ -53,7 +58,7 @@ class PodcastEpisode extends Model {
length: this.enclosureSize !== null ? String(this.enclosureSize) : null
}
}
return {
return new oldPodcastEpisode({
libraryItemId: libraryItemId || null,
podcastId: this.podcastId,
id: this.id,
@ -72,7 +77,7 @@ class PodcastEpisode extends Model {
publishedAt: this.publishedAt?.valueOf() || null,
addedAt: this.createdAt.valueOf(),
updatedAt: this.updatedAt.valueOf()
}
})
}
static createFromOld(oldEpisode) {

View File

@ -94,7 +94,7 @@ class ApiRouter {
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.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.post('/libraries/order', LibraryController.reorder.bind(this))

View File

@ -283,7 +283,7 @@ module.exports = {
const podcast = ep.podcast.toJSON()
delete podcast.libraryItem
libraryItem.media = podcast
libraryItem.recentEpisode = ep.getOldPodcastEpisode(libraryItem.id)
libraryItem.recentEpisode = ep.getOldPodcastEpisode(libraryItem.id).toJSON()
return libraryItem
})
@ -396,5 +396,64 @@ module.exports = {
podcast: itemMatches,
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
}
}