mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-01 00:18:14 +01:00
Merge pull request #2920 from rasmuslos/master
Add item sessions endpoint
This commit is contained in:
commit
d99a77837b
@ -6,7 +6,7 @@ const { toNumber } = require('../utils/index')
|
||||
const userStats = require('../utils/queries/userStats')
|
||||
|
||||
class MeController {
|
||||
constructor() { }
|
||||
constructor() {}
|
||||
|
||||
getCurrentUser(req, res) {
|
||||
res.json(req.user.toJSONForBrowser())
|
||||
@ -33,6 +33,43 @@ class MeController {
|
||||
res.json(payload)
|
||||
}
|
||||
|
||||
/**
|
||||
* GET: /api/me/item/listening-sessions/:libraryItemId/:episodeId
|
||||
*
|
||||
* @this import('../routers/ApiRouter')
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getItemListeningSessions(req, res) {
|
||||
const libraryItem = await Database.libraryItemModel.findByPk(req.params.libraryItemId)
|
||||
const episode = await Database.podcastEpisodeModel.findByPk(req.params.episodeId)
|
||||
|
||||
if (!libraryItem || (libraryItem.mediaType === 'podcast' && !episode)) {
|
||||
Logger.error(`[MeController] Media item not found for library item id "${req.params.libraryItemId}"`)
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
const mediaItemId = episode?.id || libraryItem.mediaId
|
||||
let listeningSessions = await this.getUserItemListeningSessionsHelper(req.user.id, mediaItemId)
|
||||
|
||||
const itemsPerPage = toNumber(req.query.itemsPerPage, 10) || 10
|
||||
const page = toNumber(req.query.page, 0)
|
||||
|
||||
const start = page * itemsPerPage
|
||||
const sessions = listeningSessions.slice(start, start + itemsPerPage)
|
||||
|
||||
const payload = {
|
||||
total: listeningSessions.length,
|
||||
numPages: Math.ceil(listeningSessions.length / itemsPerPage),
|
||||
page,
|
||||
itemsPerPage,
|
||||
sessions
|
||||
}
|
||||
|
||||
res.json(payload)
|
||||
}
|
||||
|
||||
// GET: api/me/listening-stats
|
||||
async getListeningStats(req, res) {
|
||||
const listeningStats = await this.getUserListeningStatsHelpers(req.user.id)
|
||||
@ -80,7 +117,7 @@ class MeController {
|
||||
if (!libraryItem) {
|
||||
return res.status(404).send('Item not found')
|
||||
}
|
||||
if (!libraryItem.media.episodes.find(ep => ep.id === episodeId)) {
|
||||
if (!libraryItem.media.episodes.find((ep) => ep.id === episodeId)) {
|
||||
Logger.error(`[MeController] removeEpisode episode ${episodeId} not found for item ${libraryItem.id}`)
|
||||
return res.status(404).send('Episode not found')
|
||||
}
|
||||
@ -123,7 +160,7 @@ class MeController {
|
||||
|
||||
// POST: api/me/item/:id/bookmark
|
||||
async createBookmark(req, res) {
|
||||
if (!await Database.libraryItemModel.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)
|
||||
@ -134,7 +171,7 @@ class MeController {
|
||||
|
||||
// PATCH: api/me/item/:id/bookmark
|
||||
async updateBookmark(req, res) {
|
||||
if (!await Database.libraryItemModel.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)) {
|
||||
@ -152,7 +189,7 @@ class MeController {
|
||||
|
||||
// DELETE: api/me/item/:id/bookmark/:time
|
||||
async removeBookmark(req, res) {
|
||||
if (!await Database.libraryItemModel.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)
|
||||
@ -254,11 +291,10 @@ class MeController {
|
||||
// TODO: More efficient to do this in a single query
|
||||
for (const mediaProgress of req.user.mediaProgress) {
|
||||
if (!mediaProgress.isFinished && (mediaProgress.progress > 0 || mediaProgress.ebookProgress > 0)) {
|
||||
|
||||
const libraryItem = await Database.libraryItemModel.getOldById(mediaProgress.libraryItemId)
|
||||
if (libraryItem) {
|
||||
if (mediaProgress.episodeId && libraryItem.mediaType === 'podcast') {
|
||||
const episode = libraryItem.media.episodes.find(ep => ep.id === mediaProgress.episodeId)
|
||||
const episode = libraryItem.media.episodes.find((ep) => ep.id === mediaProgress.episodeId)
|
||||
if (episode) {
|
||||
const libraryItemWithEpisode = {
|
||||
...libraryItem.toJSONMinified(),
|
||||
@ -277,7 +313,9 @@ class MeController {
|
||||
}
|
||||
}
|
||||
|
||||
itemsInProgress = sort(itemsInProgress).desc(li => li.progressLastUpdate).slice(0, limit)
|
||||
itemsInProgress = sort(itemsInProgress)
|
||||
.desc((li) => li.progressLastUpdate)
|
||||
.slice(0, limit)
|
||||
res.json({
|
||||
libraryItems: itemsInProgress
|
||||
})
|
||||
@ -317,19 +355,22 @@ class MeController {
|
||||
|
||||
// GET: api/me/progress/:id/remove-from-continue-listening
|
||||
async removeItemFromContinueListening(req, res) {
|
||||
const mediaProgress = req.user.mediaProgress.find(mp => mp.id === req.params.id)
|
||||
const mediaProgress = req.user.mediaProgress.find((mp) => mp.id === req.params.id)
|
||||
if (!mediaProgress) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
const hasUpdated = req.user.removeProgressFromContinueListening(req.params.id)
|
||||
if (hasUpdated) {
|
||||
await Database.mediaProgressModel.update({
|
||||
hideFromContinueListening: true
|
||||
}, {
|
||||
where: {
|
||||
id: mediaProgress.id
|
||||
await Database.mediaProgressModel.update(
|
||||
{
|
||||
hideFromContinueListening: true
|
||||
},
|
||||
{
|
||||
where: {
|
||||
id: mediaProgress.id
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
SocketAuthority.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
|
||||
}
|
||||
res.json(req.user.toJSONForBrowser())
|
||||
@ -337,9 +378,9 @@ class MeController {
|
||||
|
||||
/**
|
||||
* GET: /api/me/stats/year/:year
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*
|
||||
* @param {import('express').Request} req
|
||||
* @param {import('express').Response} res
|
||||
*/
|
||||
async getStatsForYear(req, res) {
|
||||
const year = Number(req.params.year)
|
||||
@ -351,4 +392,4 @@ class MeController {
|
||||
res.json(data)
|
||||
}
|
||||
}
|
||||
module.exports = new MeController()
|
||||
module.exports = new MeController()
|
||||
|
@ -166,6 +166,7 @@ class ApiRouter {
|
||||
//
|
||||
this.router.get('/me', MeController.getCurrentUser.bind(this))
|
||||
this.router.get('/me/listening-sessions', MeController.getListeningSessions.bind(this))
|
||||
this.router.get('/me/item/listening-sessions/:libraryItemId/:episodeId?', MeController.getItemListeningSessions.bind(this))
|
||||
this.router.get('/me/listening-stats', MeController.getListeningStats.bind(this))
|
||||
this.router.get('/me/progress/:id/remove-from-continue-listening', MeController.removeItemFromContinueListening.bind(this))
|
||||
this.router.get('/me/progress/:id/:episodeId?', MeController.getMediaProgress.bind(this))
|
||||
@ -425,9 +426,9 @@ class ApiRouter {
|
||||
/**
|
||||
* Used when a series is removed from a book
|
||||
* Series is removed if it only has 1 book
|
||||
*
|
||||
*
|
||||
* @param {string} bookId
|
||||
* @param {string[]} seriesIds
|
||||
* @param {string[]} seriesIds
|
||||
*/
|
||||
async checkRemoveEmptySeries(bookId, seriesIds) {
|
||||
if (!seriesIds?.length) return
|
||||
@ -455,7 +456,7 @@ class ApiRouter {
|
||||
|
||||
/**
|
||||
* Remove an empty series & close an open RSS feed
|
||||
* @param {import('../models/Series')} series
|
||||
* @param {import('../models/Series')} series
|
||||
*/
|
||||
async removeEmptySeries(series) {
|
||||
await this.rssFeedManager.closeFeedForEntityId(series.id)
|
||||
@ -474,6 +475,11 @@ class ApiRouter {
|
||||
return userSessions.sort((a, b) => b.updatedAt - a.updatedAt)
|
||||
}
|
||||
|
||||
async getUserItemListeningSessionsHelper(userId, mediaItemId) {
|
||||
const userSessions = await Database.getPlaybackSessions({ userId, mediaItemId })
|
||||
return userSessions.sort((a, b) => b.updatedAt - a.updatedAt)
|
||||
}
|
||||
|
||||
async getUserListeningStatsHelpers(userId) {
|
||||
const today = date.format(new Date(), 'YYYY-MM-DD')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user