mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-22 00:07:52 +01:00
New data model authors routes
This commit is contained in:
parent
65df377a49
commit
dad12537b6
@ -20,6 +20,10 @@
|
||||
<p class="text-center font-semibold truncate" :style="{ fontSize: sizeMultiplier + 'rem' }">{{ name }}</p>
|
||||
<p class="text-center text-gray-200" :style="{ fontSize: sizeMultiplier * 0.85 + 'rem' }">{{ numBooks }} Book{{ numBooks === 1 ? '' : 's' }}</p>
|
||||
</div>
|
||||
|
||||
<div class="absolute top-0 right-0 p-2 cursor-pointer hover:text-white text-gray-200" @click.stop="searchAuthor">
|
||||
<span class="material-icons">search</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -74,7 +78,15 @@ export default {
|
||||
return url.href + `?token=${this.userToken}&ts=${this.lastUpdate}`
|
||||
}
|
||||
},
|
||||
methods: {},
|
||||
methods: {
|
||||
async searchAuthor() {
|
||||
var author = await this.$axios.$post(`/api/authors/${this.authorId}/match`, { q: this.name }).catch((error) => {
|
||||
console.error('Failed', error)
|
||||
return null
|
||||
})
|
||||
console.log('Got author', author)
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
@ -16,6 +16,7 @@ const MeController = require('./controllers/MeController')
|
||||
const BackupController = require('./controllers/BackupController')
|
||||
const LibraryItemController = require('./controllers/LibraryItemController')
|
||||
const SeriesController = require('./controllers/SeriesController')
|
||||
const AuthorController = require('./controllers/AuthorController')
|
||||
|
||||
const BookFinder = require('./finders/BookFinder')
|
||||
const AuthorFinder = require('./finders/AuthorFinder')
|
||||
@ -161,12 +162,9 @@ class ApiController {
|
||||
//
|
||||
// Author Routes
|
||||
//
|
||||
this.router.get('/authors', this.getAuthors.bind(this))
|
||||
this.router.get('/authors/search', this.searchAuthors.bind(this))
|
||||
this.router.get('/authors/:id', this.getAuthor.bind(this))
|
||||
this.router.post('/authors', this.createAuthor.bind(this))
|
||||
this.router.patch('/authors/:id', this.updateAuthor.bind(this))
|
||||
this.router.delete('/authors/:id', this.deleteAuthor.bind(this))
|
||||
this.router.get('/authors/:id', AuthorController.middleware.bind(this), AuthorController.findOne.bind(this))
|
||||
this.router.post('/authors/:id/match', AuthorController.middleware.bind(this), AuthorController.match.bind(this))
|
||||
this.router.get('/authors/search', AuthorController.search.bind(this))
|
||||
|
||||
//
|
||||
// Series Routes
|
||||
@ -230,64 +228,6 @@ class ApiController {
|
||||
res.json({ user: req.user })
|
||||
}
|
||||
|
||||
async getAuthors(req, res) {
|
||||
res.json(this.db.authors)
|
||||
}
|
||||
|
||||
searchAuthors(req, res) {
|
||||
var query = req.query.q || ''
|
||||
var limit = req.query.limit && !isNaN(req.query.limit) ? Number(req.query.limit) : 100
|
||||
var authors = this.db.authors.filter(au => au.name.toLowerCase().includes(query.toLowerCase()))
|
||||
authors = authors.slice(0, limit)
|
||||
res.json(authors)
|
||||
}
|
||||
|
||||
async getAuthor(req, res) {
|
||||
var author = this.db.authors.find(p => p.id === req.params.id)
|
||||
if (!author) {
|
||||
return res.status(404).send('Author not found')
|
||||
}
|
||||
res.json(author.toJSON())
|
||||
}
|
||||
|
||||
async createAuthor(req, res) {
|
||||
var author = await this.authorFinder.createAuthor(req.body)
|
||||
if (!author) {
|
||||
return res.status(500).send('Failed to create author')
|
||||
}
|
||||
|
||||
await this.db.insertEntity('author', author)
|
||||
this.emitter('author_added', author.toJSON())
|
||||
res.json(author)
|
||||
}
|
||||
|
||||
async updateAuthor(req, res) {
|
||||
var author = this.db.authors.find(p => p.id === req.params.id)
|
||||
if (!author) {
|
||||
return res.status(404).send('Author not found')
|
||||
}
|
||||
|
||||
var wasUpdated = author.update(req.body)
|
||||
if (wasUpdated) {
|
||||
await this.db.updateEntity('author', author)
|
||||
this.emitter('author_updated', author.toJSON())
|
||||
}
|
||||
res.json(author)
|
||||
}
|
||||
|
||||
async deleteAuthor(req, res) {
|
||||
var author = this.db.authors.find(p => p.id === req.params.id)
|
||||
if (!author) {
|
||||
return res.status(404).send('Author not found')
|
||||
}
|
||||
|
||||
var authorJson = author.toJSON()
|
||||
|
||||
await this.db.removeEntity('author', author.id)
|
||||
this.emitter('author_removed', authorJson)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
async updateServerSettings(req, res) {
|
||||
if (!req.user.isRoot) {
|
||||
Logger.error('User other than root attempting to update server settings', req.user)
|
||||
|
56
server/controllers/AuthorController.js
Normal file
56
server/controllers/AuthorController.js
Normal file
@ -0,0 +1,56 @@
|
||||
const Logger = require('../Logger')
|
||||
|
||||
class AuthorController {
|
||||
constructor() { }
|
||||
|
||||
async findOne(req, res) {
|
||||
return res.json(req.author)
|
||||
}
|
||||
|
||||
async search(req, res) {
|
||||
var q = (req.query.q || '').toLowerCase()
|
||||
if (!q) return res.json([])
|
||||
var limit = (req.query.limit && !isNaN(req.query.limit)) ? Number(req.query.limit) : 25
|
||||
var authors = this.db.authors.filter(au => au.name.toLowerCase().includes(q))
|
||||
authors = authors.slice(0, limit)
|
||||
res.json(authors)
|
||||
}
|
||||
|
||||
async match(req, res) {
|
||||
var authorData = await this.authorFinder.findAuthorByName(req.body.q)
|
||||
if (!authorData) {
|
||||
return res.status(404).send('Author not found')
|
||||
}
|
||||
req.author.asin = authorData.asin
|
||||
if (authorData.image) {
|
||||
var imageData = await this.authorFinder.saveAuthorImage(req.author.id, authorData.image)
|
||||
if (imageData) {
|
||||
req.author.imagePath = imageData.path
|
||||
req.author.relImagePath = imageData.relPath
|
||||
}
|
||||
}
|
||||
if (authorData.description) {
|
||||
req.author.description = authorData.description
|
||||
}
|
||||
await this.db.updateEntity('author', req.author)
|
||||
this.emitter('author_updated', req.author)
|
||||
res.json(req.author)
|
||||
}
|
||||
|
||||
middleware(req, res, next) {
|
||||
var author = this.db.authors.find(au => au.id === req.params.id)
|
||||
if (!author) return res.sendStatus(404)
|
||||
|
||||
if (req.method == 'DELETE' && !req.user.canDelete) {
|
||||
Logger.warn(`[AuthorController] User attempted to delete without permission`, req.user)
|
||||
return res.sendStatus(403)
|
||||
} else if ((req.method == 'PATCH' || req.method == 'POST') && !req.user.canUpdate) {
|
||||
Logger.warn('[AuthorController] User attempted to update without permission', req.user)
|
||||
return res.sendStatus(403)
|
||||
}
|
||||
|
||||
req.author = author
|
||||
next()
|
||||
}
|
||||
}
|
||||
module.exports = new AuthorController()
|
@ -31,6 +31,27 @@ class AuthorFinder {
|
||||
return author
|
||||
}
|
||||
|
||||
async saveAuthorImage(authorId, url) {
|
||||
var authorDir = this.AuthorPath
|
||||
var relAuthorDir = Path.posix.join('/metadata', 'authors')
|
||||
await fs.ensureDir(authorDir)
|
||||
|
||||
var imageExtension = url.toLowerCase().split('.').pop()
|
||||
var ext = imageExtension === 'png' ? 'png' : 'jpg'
|
||||
var filename = authorId + '.' + ext
|
||||
var outputPath = Path.posix.join(authorDir, filename)
|
||||
var relPath = Path.posix.join(relAuthorDir, filename)
|
||||
|
||||
var success = await this.downloadImage(url, outputPath)
|
||||
if (!success) {
|
||||
return null
|
||||
}
|
||||
return {
|
||||
path: outputPath,
|
||||
relPath
|
||||
}
|
||||
}
|
||||
|
||||
async createAuthor(payload) {
|
||||
if (!payload || !payload.name) return null
|
||||
|
||||
|
@ -5,6 +5,7 @@ class Author {
|
||||
this.id = null
|
||||
this.asin = null
|
||||
this.name = null
|
||||
this.description = null
|
||||
this.imagePath = null
|
||||
this.relImagePath = null
|
||||
this.addedAt = null
|
||||
@ -19,6 +20,7 @@ class Author {
|
||||
this.id = author.id
|
||||
this.asin = author.asin
|
||||
this.name = author.name
|
||||
this.description = author.description || null
|
||||
this.imagePath = author.imagePath
|
||||
this.relImagePath = author.relImagePath
|
||||
this.addedAt = author.addedAt
|
||||
@ -30,6 +32,7 @@ class Author {
|
||||
id: this.id,
|
||||
asin: this.asin,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
imagePath: this.imagePath,
|
||||
relImagePath: this.relImagePath,
|
||||
addedAt: this.addedAt,
|
||||
@ -47,6 +50,7 @@ class Author {
|
||||
setData(data) {
|
||||
this.id = getId('aut')
|
||||
this.name = data.name
|
||||
this.description = data.description || null
|
||||
this.asin = data.asin || null
|
||||
this.imagePath = data.imagePath || null
|
||||
this.relImagePath = data.relImagePath || null
|
||||
|
@ -4,6 +4,7 @@ class Series {
|
||||
constructor(series) {
|
||||
this.id = null
|
||||
this.name = null
|
||||
this.description = null
|
||||
this.addedAt = null
|
||||
this.updatedAt = null
|
||||
|
||||
@ -15,6 +16,7 @@ class Series {
|
||||
construct(series) {
|
||||
this.id = series.id
|
||||
this.name = series.name
|
||||
this.description = series.description || null
|
||||
this.addedAt = series.addedAt
|
||||
this.updatedAt = series.updatedAt
|
||||
}
|
||||
@ -23,6 +25,7 @@ class Series {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
addedAt: this.addedAt,
|
||||
updatedAt: this.updatedAt
|
||||
}
|
||||
@ -39,6 +42,7 @@ class Series {
|
||||
setData(data) {
|
||||
this.id = getId('ser')
|
||||
this.name = data.name
|
||||
this.description = data.description || null
|
||||
this.addedAt = Date.now()
|
||||
this.updatedAt = Date.now()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user