mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
Remove legacy recommendations router import/mount (now in ApiRouter)
This commit is contained in:
parent
42c062c611
commit
41e67e20f6
7 changed files with 63 additions and 59 deletions
|
|
@ -27,11 +27,17 @@
|
|||
<option value="recipient-only">recipient-only</option>
|
||||
</select>
|
||||
|
||||
<div v-if="form.visibility === 'recipient-only'">
|
||||
<label class="block text-sm mb-1">Recipient (username)</label>
|
||||
<input v-model.trim="form.recipient" class="w-full mb-3 rounded border px-2 py-1 bg-[#111827] text-gray-100 border-gray-600" placeholder="Type the recipient’s username" autocomplete="off" />
|
||||
<p class="text-xs text-gray-400 -mt-2 mb-2">Enter the user’s <strong>username</strong>. We’ll resolve it on the server.</p>
|
||||
</div>
|
||||
|
||||
<label class="block text-sm mb-1">Note <span class="opacity-60">(optional)</span></label>
|
||||
<textarea v-model="form.note" rows="3" maxlength="1000" class="w-full rounded border border-gray-600 bg-transparent px-2 py-1" placeholder="Why should someone read/listen to this?"></textarea>
|
||||
|
||||
<div class="mt-4 flex items-center gap-2">
|
||||
<button :disabled="submitting || !form.tagId" class="rounded px-3 py-1 text-sm bg-primary text-white border border-primary hover:bg-primary/90 disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-primary/40" @click="submit">
|
||||
<button :disabled="submitting || !form.tagId || (form.visibility === 'recipient-only' && !form.recipient)" class="rounded px-3 py-1 text-sm bg-primary text-white border border-primary hover:bg-primary/90 disabled:opacity-50 focus:outline-none focus:ring-2 focus:ring-primary/40" @click="submit">
|
||||
{{ submitting ? 'Posting…' : 'Post recommendation' }}
|
||||
</button>
|
||||
<span v-if="error" class="text-sm text-error">{{ error }}</span>
|
||||
|
|
@ -56,7 +62,7 @@ export default {
|
|||
submitting: false,
|
||||
ok: false,
|
||||
error: '',
|
||||
form: { tagId: '', visibility: 'public', note: '' }
|
||||
form: { tagId: '', visibility: 'public', recipient: '', note: '' }
|
||||
}),
|
||||
mounted() {
|
||||
const flag = this.$store.getters['getServerSetting']?.('recommendationsEnabled')
|
||||
|
|
@ -104,6 +110,10 @@ export default {
|
|||
},
|
||||
async submit() {
|
||||
if (!this.form.tagId) return
|
||||
if (this.form.visibility === 'recipient-only' && !this.form.recipient) {
|
||||
this.error = 'Recipient is required'
|
||||
return
|
||||
}
|
||||
this.submitting = true
|
||||
this.error = ''
|
||||
this.ok = false
|
||||
|
|
@ -112,7 +122,8 @@ export default {
|
|||
bookId: this.bookId,
|
||||
tagId: this.form.tagId,
|
||||
note: this.form.note || '',
|
||||
visibility: this.form.visibility
|
||||
visibility: this.form.visibility,
|
||||
recipientUsername: this.form.visibility === 'recipient-only' ? this.form.recipient : null
|
||||
}
|
||||
const created = await this.$axios.$post('/api/recommendations', payload)
|
||||
this.$emit('recommended', created)
|
||||
|
|
|
|||
|
|
@ -162,7 +162,6 @@ class Database {
|
|||
return this.models.device
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
get recommendationTagModel() {
|
||||
return this.models.recommendationTag
|
||||
}
|
||||
|
|
@ -170,8 +169,6 @@ class Database {
|
|||
return this.models.bookRecommendation
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> parent of ae4bd94b (add database changes for recommandation sent and inbox)
|
||||
/**
|
||||
* Check if db file exists
|
||||
* @returns {boolean}
|
||||
|
|
@ -355,7 +352,7 @@ class Database {
|
|||
require('./models/Setting').init(this.sequelize)
|
||||
require('./models/CustomMetadataProvider').init(this.sequelize)
|
||||
require('./models/MediaItemShare').init(this.sequelize)
|
||||
<<<<<<< HEAD
|
||||
|
||||
require('./models/RecommendationTag').init(this.sequelize)
|
||||
require('./models/BookRecommendation').init(this.sequelize)
|
||||
// One association pass BEFORE sync
|
||||
|
|
@ -363,8 +360,6 @@ class Database {
|
|||
Object.values(models).forEach((m) => {
|
||||
if (typeof m?.associate === 'function') m.associate(models)
|
||||
})
|
||||
=======
|
||||
>>>>>>> parent of ae4bd94b (add database changes for recommandation sent and inbox)
|
||||
|
||||
return this.sequelize.sync({ force, alter: false })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ const ApiCacheManager = require('./managers/ApiCacheManager')
|
|||
const BinaryManager = require('./managers/BinaryManager')
|
||||
const ShareManager = require('./managers/ShareManager')
|
||||
const LibraryScanner = require('./scanner/LibraryScanner')
|
||||
const buildRecommendationsRouter = require('./routers/recommendations')
|
||||
const RecommendationManager = require('./managers/RecommendationManager')
|
||||
|
||||
//Import the main Passport and Express-Session library
|
||||
|
|
@ -325,15 +324,6 @@ class Server {
|
|||
// Static folder
|
||||
router.use(express.static(Path.join(global.appRoot, 'static')))
|
||||
|
||||
router.use(
|
||||
'/api/recommendations',
|
||||
this.auth.ifAuthNeeded(this.authMiddleware.bind(this)),
|
||||
buildRecommendationsRouter({
|
||||
manager: RecommendationManager,
|
||||
featureFlag: () => String(process.env.RECOMMENDATIONS_ENABLED) === 'true'
|
||||
})
|
||||
)
|
||||
|
||||
// RSS Feed temp route
|
||||
router.get('/feed/:slug', (req, res) => {
|
||||
Logger.info(`[Server] Requesting rss feed ${req.params.slug}`)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module.exports = (injectedManager) => {
|
|||
const userId = req.user?.id
|
||||
if (!userId) return res.status(401).send('Unauthorized')
|
||||
|
||||
const { bookId, tagId, tagSlug, recipientUserId, note, visibility } = req.body || {}
|
||||
const { bookId, tagId, tagSlug, recipientUserId, recipientUsername, note, visibility } = req.body || {}
|
||||
if (!bookId) return res.status(400).json({ message: 'bookId is required' })
|
||||
if (!tagId && !tagSlug) return res.status(400).json({ message: 'tagId or tagSlug is required' })
|
||||
|
||||
|
|
@ -24,6 +24,7 @@ module.exports = (injectedManager) => {
|
|||
tagId,
|
||||
tagSlug,
|
||||
recipientUserId,
|
||||
recipientUsername,
|
||||
note,
|
||||
visibility
|
||||
})
|
||||
|
|
|
|||
|
|
@ -86,19 +86,30 @@ const RecommendationManager = {
|
|||
return null
|
||||
},
|
||||
|
||||
async resolveRecipient(recipientUserId) {
|
||||
if (!recipientUserId) return null
|
||||
const user = await Database.userModel.findByPk(recipientUserId)
|
||||
return user || null
|
||||
async resolveRecipient({ recipientUserId, recipientUsername }) {
|
||||
const User = Database.userModel
|
||||
if (recipientUserId) {
|
||||
const u = await User.findByPk(recipientUserId)
|
||||
return u || null
|
||||
}
|
||||
if (recipientUsername) {
|
||||
const u = await User.findOne({ where: { username: String(recipientUsername) } })
|
||||
return u || null
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
async createRecommendation({ userId, bookId, tagId, tagSlug, recipientUserId, note, visibility }) {
|
||||
async createRecommendation({ userId, bookId, tagId, tagSlug, recipientUserId, recipientUsername, note, visibility }) {
|
||||
const tag = await this.resolveTag({ tagId, tagSlug })
|
||||
if (!tag) return { error: { status: 400, message: 'Invalid tag' } }
|
||||
|
||||
const recip = await this.resolveRecipient(recipientUserId)
|
||||
if (recipientUserId && !recip) return { error: { status: 400, message: 'Recipient not found' } }
|
||||
|
||||
if (visibility === 'recipient-only' && !recipientUserId && !recipientUsername) {
|
||||
return { error: { status: 400, message: 'Recipient is required for recipient-only visibility' } }
|
||||
}
|
||||
const recip = await this.resolveRecipient({ recipientUserId, recipientUsername })
|
||||
if (visibility === 'recipient-only' && !recip) {
|
||||
return { error: { status: 400, message: 'Recipient not found' } }
|
||||
}
|
||||
const created = await Database.bookRecommendationModel.create({
|
||||
bookId: String(bookId),
|
||||
tagId: tag.id,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ const MiscController = require('../controllers/MiscController')
|
|||
const ShareController = require('../controllers/ShareController')
|
||||
const StatsController = require('../controllers/StatsController')
|
||||
const ApiKeyController = require('../controllers/ApiKeyController')
|
||||
const RecommendationManager = require('../managers/RecommendationManager')
|
||||
const buildRecommendationsController = require('../controllers/recommendationsController')
|
||||
|
||||
class ApiRouter {
|
||||
constructor(Server) {
|
||||
|
|
@ -96,6 +98,31 @@ class ApiRouter {
|
|||
this.router.get('/libraries/:id/podcast-titles', LibraryController.middleware.bind(this), LibraryController.getPodcastTitles.bind(this))
|
||||
this.router.get('/libraries/:id/download', LibraryController.middleware.bind(this), LibraryController.downloadMultiple.bind(this))
|
||||
|
||||
//
|
||||
// Recommendations Routes (feature-flagged)
|
||||
//
|
||||
const RecommendationsController = buildRecommendationsController(RecommendationManager)
|
||||
const recommendationsEnabled = () => String(process.env.RECOMMENDATIONS_ENABLED) === 'true'
|
||||
const recommendationsGate = (req, res, next) => {
|
||||
if (!recommendationsEnabled()) return res.status(501).json({ message: 'Recommendations disabled' })
|
||||
next()
|
||||
}
|
||||
const requireAuth = (req, res, next) => {
|
||||
if (req.user && req.user.id) return next()
|
||||
return res.status(401).send('Unauthorized')
|
||||
}
|
||||
|
||||
// Apply the feature gate to all /recommendations paths
|
||||
this.router.use('/recommendations', recommendationsGate)
|
||||
|
||||
// Endpoints
|
||||
this.router.get('/recommendations/tags', RecommendationsController.listTags)
|
||||
this.router.post('/recommendations', requireAuth, RecommendationsController.create)
|
||||
this.router.get('/recommendations/book/:bookId', RecommendationsController.byBook)
|
||||
this.router.get('/recommendations/inbox', requireAuth, RecommendationsController.inbox)
|
||||
this.router.get('/recommendations/sent', requireAuth, RecommendationsController.sent)
|
||||
this.router.put('/recommendations/:id', requireAuth, RecommendationsController.update)
|
||||
this.router.delete('/recommendations/:id', requireAuth, RecommendationsController.destroy)
|
||||
//
|
||||
// Item Routes
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const express = require('express')
|
||||
|
||||
const requireAuth = (req, res, next) => {
|
||||
if (req.user && req.user.id) return next()
|
||||
return res.status(401).send('Unauthorized')
|
||||
}
|
||||
|
||||
module.exports = ({ manager, featureFlag } = {}) => {
|
||||
const router = express.Router()
|
||||
|
||||
const isEnabled = typeof featureFlag === 'function' ? featureFlag : () => String(process.env.RECOMMENDATIONS_ENABLED) === 'true'
|
||||
|
||||
router.use((req, res, next) => {
|
||||
if (!isEnabled()) return res.status(501).json({ message: 'Recommendations disabled' })
|
||||
next()
|
||||
})
|
||||
|
||||
const Controller = require('../controllers/recommendationsController')(manager)
|
||||
|
||||
router.get('/tags', Controller.listTags)
|
||||
router.post('/', requireAuth, Controller.create)
|
||||
router.get('/book/:bookId', Controller.byBook)
|
||||
router.get('/inbox', requireAuth, Controller.inbox)
|
||||
router.get('/sent', requireAuth, Controller.sent)
|
||||
router.put('/:id', requireAuth, Controller.update)
|
||||
router.delete('/:id', requireAuth, Controller.destroy)
|
||||
|
||||
return router
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue