Add MusicBrainz provider

This commit is contained in:
advplyr 2023-01-07 13:05:33 -06:00
parent 3e4b1652fc
commit 2cd9079692
4 changed files with 73 additions and 0 deletions

View File

@ -49,5 +49,12 @@ class SearchController {
} }
res.json(chapterData) res.json(chapterData)
} }
async findMusicTrack(req, res) {
const tracks = await this.musicFinder.searchTrack(req.query || {})
res.json({
tracks
})
}
} }
module.exports = new SearchController() module.exports = new SearchController()

View File

@ -0,0 +1,12 @@
const MusicBrainz = require('../providers/MusicBrainz')
class MusicFinder {
constructor() {
this.musicBrainz = new MusicBrainz()
}
searchTrack(options) {
return this.musicBrainz.searchTrack(options)
}
}
module.exports = MusicFinder

View File

@ -0,0 +1,51 @@
const axios = require('axios')
const packageJson = require('../../package.json')
const Logger = require('../Logger')
const { isNullOrNaN } = require('../utils/index')
class MusicBrainz {
constructor() { }
get userAgentString() {
return `audiobookshelf/${packageJson.version} (https://audiobookshelf.org)`
}
// https://musicbrainz.org/doc/MusicBrainz_API/Search
searchTrack(options) {
let luceneParts = []
if (options.artist) {
luceneParts.push(`artist:${options.artist}`)
}
if (options.isrc) {
luceneParts.push(`isrc:${options.isrc}`)
}
if (options.title) {
luceneParts.push(`recording:${options.title}`)
}
if (options.album) {
luceneParts.push(`release:${options.album}`)
}
if (!luceneParts.length) {
Logger.error(`[MusicBrainz] Invalid search options - must have at least one of artist, isrc, title, album`)
return []
}
const query = {
query: luceneParts.join(' AND '),
limit: isNullOrNaN(options.limit) ? 15 : Number(options.limit),
fmt: 'json'
}
const config = {
headers: {
'User-Agent': this.userAgentString
}
}
return axios.get('https://musicbrainz.org/ws/2/recording', { params: query }, config).then((response) => {
return response.data.recordings || []
}).catch((error) => {
Logger.error(`[MusicBrainz] search request error`, error)
return []
})
}
}
module.exports = MusicBrainz

View File

@ -30,6 +30,7 @@ const MiscController = require('../controllers/MiscController')
const BookFinder = require('../finders/BookFinder') const BookFinder = require('../finders/BookFinder')
const AuthorFinder = require('../finders/AuthorFinder') const AuthorFinder = require('../finders/AuthorFinder')
const PodcastFinder = require('../finders/PodcastFinder') const PodcastFinder = require('../finders/PodcastFinder')
const MusicFinder = require('../finders/MusicFinder')
const Author = require('../objects/entities/Author') const Author = require('../objects/entities/Author')
const Series = require('../objects/entities/Series') const Series = require('../objects/entities/Series')
@ -56,6 +57,7 @@ class ApiRouter {
this.bookFinder = new BookFinder() this.bookFinder = new BookFinder()
this.authorFinder = new AuthorFinder() this.authorFinder = new AuthorFinder()
this.podcastFinder = new PodcastFinder() this.podcastFinder = new PodcastFinder()
this.musicFinder = new MusicFinder()
this.router = express() this.router = express()
this.init() this.init()
@ -253,6 +255,7 @@ class ApiRouter {
this.router.get('/search/podcast', SearchController.findPodcasts.bind(this)) this.router.get('/search/podcast', SearchController.findPodcasts.bind(this))
this.router.get('/search/authors', SearchController.findAuthor.bind(this)) this.router.get('/search/authors', SearchController.findAuthor.bind(this))
this.router.get('/search/chapters', SearchController.findChapters.bind(this)) this.router.get('/search/chapters', SearchController.findChapters.bind(this))
this.router.get('/search/tracks', SearchController.findMusicTrack.bind(this))
// //
// Cache Routes (Admin and up) // Cache Routes (Admin and up)