mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
Merge 5df6dfeec0 into a87ea32715
This commit is contained in:
commit
fa97dd8ae9
3 changed files with 996 additions and 36 deletions
|
|
@ -55,6 +55,10 @@ export const state = () => ({
|
||||||
{
|
{
|
||||||
text: 'FantLab.ru',
|
text: 'FantLab.ru',
|
||||||
value: 'fantlab'
|
value: 'fantlab'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'MusicBrainz',
|
||||||
|
value: 'musicbrainz'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
podcastProviders: [
|
podcastProviders: [
|
||||||
|
|
@ -123,4 +127,4 @@ export const mutations = {
|
||||||
// Podcast providers not supported yet
|
// Podcast providers not supported yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ const CustomProviderAdapter = require('../providers/CustomProviderAdapter')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
const { levenshteinDistance, levenshteinSimilarity, escapeRegExp, isValidASIN } = require('../utils/index')
|
const { levenshteinDistance, levenshteinSimilarity, escapeRegExp, isValidASIN } = require('../utils/index')
|
||||||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||||
|
const MusicBrainz = require('../providers/MusicBrainz')
|
||||||
|
|
||||||
class BookFinder {
|
class BookFinder {
|
||||||
#providerResponseTimeout = 10000
|
#providerResponseTimeout = 10000
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.musicbrainz = new MusicBrainz()
|
||||||
this.openLibrary = new OpenLibrary()
|
this.openLibrary = new OpenLibrary()
|
||||||
this.googleBooks = new GoogleBooks()
|
this.googleBooks = new GoogleBooks()
|
||||||
this.audible = new Audible()
|
this.audible = new Audible()
|
||||||
|
|
@ -23,11 +25,12 @@ class BookFinder {
|
||||||
this.audiobookCovers = new AudiobookCovers()
|
this.audiobookCovers = new AudiobookCovers()
|
||||||
this.customProviderAdapter = new CustomProviderAdapter()
|
this.customProviderAdapter = new CustomProviderAdapter()
|
||||||
|
|
||||||
this.providers = ['google', 'itunes', 'openlibrary', 'fantlab', 'audiobookcovers', 'audible', 'audible.ca', 'audible.uk', 'audible.au', 'audible.fr', 'audible.de', 'audible.jp', 'audible.it', 'audible.in', 'audible.es']
|
this.providers = ['google', 'itunes', 'musicbrainz', 'openlibrary', 'fantlab', 'audiobookcovers', 'audible', 'audible.ca', 'audible.uk', 'audible.au', 'audible.fr', 'audible.de', 'audible.jp', 'audible.it', 'audible.in', 'audible.es']
|
||||||
|
|
||||||
this.verbose = false
|
this.verbose = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo Not sure what this is for, but MusicBrainz can also be used to perform ISBN lookups.
|
||||||
async findByISBN(isbn) {
|
async findByISBN(isbn) {
|
||||||
var book = await this.openLibrary.isbnLookup(isbn)
|
var book = await this.openLibrary.isbnLookup(isbn)
|
||||||
if (book.errorCode) {
|
if (book.errorCode) {
|
||||||
|
|
@ -194,6 +197,22 @@ class BookFinder {
|
||||||
return books
|
return books
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} title
|
||||||
|
* @param {string} author
|
||||||
|
* @param {string} asin
|
||||||
|
* @param {string} isbn
|
||||||
|
* @returns {Promise<Object[]>}
|
||||||
|
*/
|
||||||
|
async getMusicBrainzResults(title, author, asin, isbn) {
|
||||||
|
const books = await this.musicbrainz.search(title, author, asin, isbn)
|
||||||
|
// todo Sort by closest score and then duration?
|
||||||
|
if (this.verbose) Logger.debug(`MusicBrainz Book Search Results: ${books.length || 0}`)
|
||||||
|
if (!books) return []
|
||||||
|
return books
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} title
|
* @param {string} title
|
||||||
|
|
@ -389,7 +408,7 @@ class BookFinder {
|
||||||
|
|
||||||
let actualTitleQuery = title
|
let actualTitleQuery = title
|
||||||
let actualAuthorQuery = author
|
let actualAuthorQuery = author
|
||||||
books = await this.runSearch(actualTitleQuery, actualAuthorQuery, provider, asin, maxTitleDistance, maxAuthorDistance)
|
books = await this.runSearch(actualTitleQuery, actualAuthorQuery, provider, asin, isbn, maxTitleDistance, maxAuthorDistance)
|
||||||
|
|
||||||
if (!books.length && maxFuzzySearches > 0) {
|
if (!books.length && maxFuzzySearches > 0) {
|
||||||
// Normalize title and author
|
// Normalize title and author
|
||||||
|
|
@ -416,7 +435,7 @@ class BookFinder {
|
||||||
if (++numFuzzySearches > maxFuzzySearches) break loop_author
|
if (++numFuzzySearches > maxFuzzySearches) break loop_author
|
||||||
actualTitleQuery = titleCandidate
|
actualTitleQuery = titleCandidate
|
||||||
actualAuthorQuery = authorCandidate
|
actualAuthorQuery = authorCandidate
|
||||||
books = await this.runSearch(actualTitleQuery, actualAuthorQuery, provider, asin, maxTitleDistance, maxAuthorDistance)
|
books = await this.runSearch(actualTitleQuery, actualAuthorQuery, provider, asin, isbn, maxTitleDistance, maxAuthorDistance)
|
||||||
if (books.length) break loop_author
|
if (books.length) break loop_author
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -431,13 +450,17 @@ class BookFinder {
|
||||||
book.matchConfidence = this.calculateMatchConfidence(book, libraryItemDurationMinutes, actualTitleQuery, actualAuthorQuery, isTitleAsin)
|
book.matchConfidence = this.calculateMatchConfidence(book, libraryItemDurationMinutes, actualTitleQuery, actualAuthorQuery, isTitleAsin)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isAudibleProvider && libraryItemDurationMinutes) {
|
if ((isAudibleProvider || provider === "musicbrainz") && libraryItemDurationMinutes) {
|
||||||
books.sort((a, b) => {
|
books.sort((a, b) => {
|
||||||
const aDuration = a.duration || Number.POSITIVE_INFINITY
|
if (a.matchConfidence == b.matchConfidence) {
|
||||||
const bDuration = b.duration || Number.POSITIVE_INFINITY
|
const aDuration = a.duration || Number.POSITIVE_INFINITY
|
||||||
const aDurationDiff = Math.abs(aDuration - libraryItemDurationMinutes)
|
const bDuration = b.duration || Number.POSITIVE_INFINITY
|
||||||
const bDurationDiff = Math.abs(bDuration - libraryItemDurationMinutes)
|
const aDurationDiff = Math.abs(aDuration - libraryItemDurationMinutes)
|
||||||
return aDurationDiff - bDurationDiff
|
const bDurationDiff = Math.abs(bDuration - libraryItemDurationMinutes)
|
||||||
|
return aDurationDiff - bDurationDiff
|
||||||
|
} else {
|
||||||
|
return b.matchConfidence - a.matchConfidence
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -564,12 +587,13 @@ class BookFinder {
|
||||||
* @param {string} title
|
* @param {string} title
|
||||||
* @param {string} author
|
* @param {string} author
|
||||||
* @param {string} provider
|
* @param {string} provider
|
||||||
* @param {string} asin only used for audible providers
|
* @param {string} asin only used for Audible and MusicBrainz providers
|
||||||
|
* @param {string} isbn
|
||||||
* @param {number} maxTitleDistance only used for openlibrary provider
|
* @param {number} maxTitleDistance only used for openlibrary provider
|
||||||
* @param {number} maxAuthorDistance only used for openlibrary provider
|
* @param {number} maxAuthorDistance only used for openlibrary provider
|
||||||
* @returns {Promise<Object[]>}
|
* @returns {Promise<Object[]>}
|
||||||
*/
|
*/
|
||||||
async runSearch(title, author, provider, asin, maxTitleDistance, maxAuthorDistance) {
|
async runSearch(title, author, provider, asin, isbn, maxTitleDistance, maxAuthorDistance) {
|
||||||
Logger.debug(`Book Search: title: "${title}", author: "${author || ''}", provider: ${provider}`)
|
Logger.debug(`Book Search: title: "${title}", author: "${author || ''}", provider: ${provider}`)
|
||||||
|
|
||||||
let books = []
|
let books = []
|
||||||
|
|
@ -586,6 +610,8 @@ class BookFinder {
|
||||||
books = await this.getFantLabResults(title, author)
|
books = await this.getFantLabResults(title, author)
|
||||||
} else if (provider === 'audiobookcovers') {
|
} else if (provider === 'audiobookcovers') {
|
||||||
books = await this.getAudiobookCoversResults(title)
|
books = await this.getAudiobookCoversResults(title)
|
||||||
|
} else if (provider === 'musicbrainz') {
|
||||||
|
books = await this.getMusicBrainzResults(title, author, asin, isbn)
|
||||||
} else {
|
} else {
|
||||||
books = await this.getGoogleBooksResults(title, author)
|
books = await this.getGoogleBooksResults(title, author)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue