mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-01 00:18:14 +01:00
Add:Playlist API endpoints
This commit is contained in:
parent
59ed2ec87f
commit
f9b87b94bf
185
server/controllers/PlaylistController.js
Normal file
185
server/controllers/PlaylistController.js
Normal file
@ -0,0 +1,185 @@
|
||||
const Logger = require('../Logger')
|
||||
const SocketAuthority = require('../SocketAuthority')
|
||||
|
||||
const Playlist = require('../objects/Playlist')
|
||||
|
||||
class PlaylistController {
|
||||
constructor() { }
|
||||
|
||||
// POST: api/playlists
|
||||
async create(req, res) {
|
||||
const newPlaylist = new Playlist()
|
||||
req.body.userId = req.user.id
|
||||
const success = newPlaylist.setData(req.body)
|
||||
if (!success) {
|
||||
return res.status(400).send('Invalid playlist request data')
|
||||
}
|
||||
const jsonExpanded = newPlaylist.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.insertEntity('playlist', newPlaylist)
|
||||
SocketAuthority.emitter('playlist_added', jsonExpanded)
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
// GET: api/playlists
|
||||
findAllForUser(req, res) {
|
||||
res.json({
|
||||
playlists: this.db.playlists.filter(p => p.userId === req.user.id).map(p => p.toJSONExpanded(this.db.libraryItems))
|
||||
})
|
||||
}
|
||||
|
||||
// GET: api/playlists/:id
|
||||
findOne(req, res) {
|
||||
res.json(req.playlist.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
|
||||
// PATCH: api/playlists/:id
|
||||
async update(req, res) {
|
||||
const playlist = req.playlist
|
||||
let wasUpdated = playlist.update(req.body)
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('playlist', playlist)
|
||||
SocketAuthority.emitter('playlist_updated', jsonExpanded)
|
||||
}
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
// DELETE: api/playlists/:id
|
||||
async delete(req, res) {
|
||||
const playlist = req.playlist
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.removeEntity('playlist', playlist.id)
|
||||
SocketAuthority.emitter('playlist_removed', jsonExpanded)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
// POST: api/playlists/:id/item
|
||||
async addItem(req, res) {
|
||||
const playlist = req.playlist
|
||||
const itemToAdd = req.body
|
||||
|
||||
if (!itemToAdd.libraryItemId) {
|
||||
return res.status(400).send('Request body has no libraryItemId')
|
||||
}
|
||||
|
||||
const libraryItem = this.db.libraryItems.find(li => li.id === itemToAdd.libraryItemId)
|
||||
if (!libraryItem) {
|
||||
return res.status(400).send('Library item not found')
|
||||
}
|
||||
if (libraryItem.libraryId !== playlist.libraryId) {
|
||||
return res.status(400).send('Library item in different library')
|
||||
}
|
||||
if (playlist.containsItem(itemToAdd)) {
|
||||
return res.status(400).send('Item already in playlist')
|
||||
}
|
||||
if ((itemToAdd.episodeId && !libraryItem.isPodcast) || (libraryItem.isPodcast && !itemToAdd.episodeId)) {
|
||||
return res.status(400).send('Invalid item to add for this library type')
|
||||
}
|
||||
if (itemToAdd.episodeId && !libraryItem.media.checkHasEpisode(itemToAdd.episodeId)) {
|
||||
return res.status(400).send('Episode not found in library item')
|
||||
}
|
||||
|
||||
playlist.addItem(itemToAdd.libraryItemId, itemToAdd.episodeId)
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.updateEntity('playlist', playlist)
|
||||
SocketAuthority.emitter('playlist_updated', jsonExpanded)
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
// DELETE: api/playlists/:id/item/:libraryItemId/:episodeId?
|
||||
async removeItem(req, res) {
|
||||
const playlist = req.playlist
|
||||
const itemToRemove = {
|
||||
libraryItemId: req.params.libraryItemId,
|
||||
episodeId: req.params.episodeId || null
|
||||
}
|
||||
if (!playlist.containsItem(itemToRemove)) {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
|
||||
playlist.removeItem(itemToRemove.libraryItemId, itemToRemove.episodeId)
|
||||
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
await this.db.updateEntity('playlist', playlist)
|
||||
SocketAuthority.emitter('playlist_updated', jsonExpanded)
|
||||
res.json(playlist.toJSONExpanded(this.db.libraryItems))
|
||||
}
|
||||
|
||||
// POST: api/playlists/:id/batch/add
|
||||
async addBatch(req, res) {
|
||||
const playlist = req.playlist
|
||||
if (!req.body.items || !req.body.items.length) {
|
||||
return res.status(500).send('Invalid request body')
|
||||
}
|
||||
const itemsToAdd = req.body.items
|
||||
let hasUpdated = false
|
||||
for (const item of itemsToAdd) {
|
||||
if (!item.libraryItemId) {
|
||||
return res.status(400).send('Item does not have libraryItemId')
|
||||
}
|
||||
|
||||
if (!playlist.containsItem(item)) {
|
||||
playlist.addItem(item.libraryItemId, item.episodeId)
|
||||
hasUpdated = true
|
||||
}
|
||||
}
|
||||
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('playlist', playlist)
|
||||
SocketAuthority.emitter('playlist_updated', jsonExpanded)
|
||||
}
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
// POST: api/playlists/:id/batch/remove
|
||||
async removeBatch(req, res) {
|
||||
const playlist = req.playlist
|
||||
if (!req.body.items || !req.body.items.length) {
|
||||
return res.status(500).send('Invalid request body')
|
||||
}
|
||||
const itemsToRemove = req.body.items
|
||||
let hasUpdated = false
|
||||
for (const item of itemsToRemove) {
|
||||
if (!item.libraryItemId) {
|
||||
return res.status(400).send('Item does not have libraryItemId')
|
||||
}
|
||||
if (playlist.containsItem(item)) {
|
||||
playlist.removeItem(item)
|
||||
hasUpdated = true
|
||||
}
|
||||
}
|
||||
|
||||
const jsonExpanded = playlist.toJSONExpanded(this.db.libraryItems)
|
||||
if (hasUpdated) {
|
||||
await this.db.updateEntity('playlist', playlist)
|
||||
SocketAuthority.emitter('playlist_updated', jsonExpanded)
|
||||
}
|
||||
res.json(jsonExpanded)
|
||||
}
|
||||
|
||||
middleware(req, res, next) {
|
||||
if (req.params.id) {
|
||||
var playlist = this.db.playlists.find(p => p.id === req.params.id)
|
||||
if (!playlist) {
|
||||
return res.status(404).send('Playlist not found')
|
||||
}
|
||||
if (playlist.userId !== req.user.id) {
|
||||
Logger.warn(`[PlaylistController] Playlist ${req.params.id} requested by user ${req.user.id} that is not the owner`)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
req.playlist = playlist
|
||||
}
|
||||
|
||||
if (req.method == 'DELETE' && !req.user.canDelete) {
|
||||
Logger.warn(`[PlaylistController] User attempted to delete without permission`, req.user.username)
|
||||
return res.sendStatus(403)
|
||||
} else if ((req.method == 'PATCH' || req.method == 'POST') && !req.user.canUpdate) {
|
||||
Logger.warn('[PlaylistController] User attempted to update without permission', req.user.username)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
}
|
||||
module.exports = new PlaylistController()
|
@ -12,8 +12,7 @@ class Playlist {
|
||||
|
||||
this.coverPath = null
|
||||
|
||||
// Array of objects like { libraryItemId: "", episodeId: "" }
|
||||
// episodeId optional
|
||||
// Array of objects like { libraryItemId: "", episodeId: "" } (episodeId optional)
|
||||
this.items = []
|
||||
|
||||
this.lastUpdate = null
|
||||
@ -128,5 +127,10 @@ class Playlist {
|
||||
}
|
||||
return hasUpdates
|
||||
}
|
||||
|
||||
containsItem(item) {
|
||||
if (item.episodeId) return this.items.some(i => i.libraryItemId === item.libraryItemId && i.episodeId === item.episodeId)
|
||||
return this.items.some(i => i.libraryItemId === item.libraryItemId)
|
||||
}
|
||||
}
|
||||
module.exports = Playlist
|
@ -10,6 +10,7 @@ const date = require('../libs/dateAndTime')
|
||||
const LibraryController = require('../controllers/LibraryController')
|
||||
const UserController = require('../controllers/UserController')
|
||||
const CollectionController = require('../controllers/CollectionController')
|
||||
const PlaylistController = require('../controllers/PlaylistController')
|
||||
const MeController = require('../controllers/MeController')
|
||||
const BackupController = require('../controllers/BackupController')
|
||||
const LibraryItemController = require('../controllers/LibraryItemController')
|
||||
@ -133,12 +134,24 @@ class ApiRouter {
|
||||
this.router.get('/collections/:id', CollectionController.middleware.bind(this), CollectionController.findOne.bind(this))
|
||||
this.router.patch('/collections/:id', CollectionController.middleware.bind(this), CollectionController.update.bind(this))
|
||||
this.router.delete('/collections/:id', CollectionController.middleware.bind(this), CollectionController.delete.bind(this))
|
||||
|
||||
this.router.post('/collections/:id/book', CollectionController.middleware.bind(this), CollectionController.addBook.bind(this))
|
||||
this.router.delete('/collections/:id/book/:bookId', CollectionController.middleware.bind(this), CollectionController.removeBook.bind(this))
|
||||
this.router.post('/collections/:id/batch/add', CollectionController.middleware.bind(this), CollectionController.addBatch.bind(this))
|
||||
this.router.post('/collections/:id/batch/remove', CollectionController.middleware.bind(this), CollectionController.removeBatch.bind(this))
|
||||
|
||||
//
|
||||
// Playlist Routes
|
||||
//
|
||||
this.router.post('/playlists', PlaylistController.middleware.bind(this), PlaylistController.create.bind(this))
|
||||
this.router.get('/playlists', PlaylistController.findAllForUser.bind(this))
|
||||
this.router.get('/playlists/:id', PlaylistController.middleware.bind(this), PlaylistController.findOne.bind(this))
|
||||
this.router.patch('/playlists/:id', PlaylistController.middleware.bind(this), PlaylistController.update.bind(this))
|
||||
this.router.delete('/playlists/:id', PlaylistController.middleware.bind(this), PlaylistController.delete.bind(this))
|
||||
this.router.post('/playlists/:id/item', PlaylistController.middleware.bind(this), PlaylistController.addItem.bind(this))
|
||||
this.router.delete('/playlists/:id/item/:libraryItemId/:episodeId?', PlaylistController.middleware.bind(this), PlaylistController.removeItem.bind(this))
|
||||
this.router.post('/playlists/:id/batch/add', PlaylistController.middleware.bind(this), PlaylistController.addBatch.bind(this))
|
||||
this.router.post('/playlists/:id/batch/remove', PlaylistController.middleware.bind(this), PlaylistController.removeBatch.bind(this))
|
||||
|
||||
//
|
||||
// Current User Routes (Me)
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user