mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Add:Multi-region audible & audnexus support #731
This commit is contained in:
		
							parent
							
								
									1fa94cbfad
								
							
						
					
					
						commit
						3900db14d3
					
				| @ -125,7 +125,7 @@ export default { | |||||||
|       return this.$store.state.scanners.providers |       return this.$store.state.scanners.providers | ||||||
|     }, |     }, | ||||||
|     searchTitleLabel() { |     searchTitleLabel() { | ||||||
|       if (this.provider == 'audible') return 'Search Title or ASIN' |       if (this.provider.startsWith('audible')) return 'Search Title or ASIN' | ||||||
|       else if (this.provider == 'itunes') return 'Search Term' |       else if (this.provider == 'itunes') return 'Search Term' | ||||||
|       return 'Search Title' |       return 'Search Title' | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -258,7 +258,7 @@ export default { | |||||||
|       return this.$store.state.scanners.providers |       return this.$store.state.scanners.providers | ||||||
|     }, |     }, | ||||||
|     searchTitleLabel() { |     searchTitleLabel() { | ||||||
|       if (this.provider == 'audible') return 'Search Title or ASIN' |       if (this.provider.startsWith('audible')) return 'Search Title or ASIN' | ||||||
|       else if (this.provider == 'itunes') return 'Search Term' |       else if (this.provider == 'itunes') return 'Search Term' | ||||||
|       return 'Search Title' |       return 'Search Title' | ||||||
|     }, |     }, | ||||||
| @ -312,7 +312,7 @@ export default { | |||||||
|       this.isProcessing = true |       this.isProcessing = true | ||||||
|       this.lastSearch = searchQuery |       this.lastSearch = searchQuery | ||||||
|       var searchEntity = this.isPodcast ? 'podcast' : 'books' |       var searchEntity = this.isPodcast ? 'podcast' : 'books' | ||||||
|       var results = await this.$axios.$get(`/api/search/${searchEntity}?${searchQuery}`, { timeout: 10000 }).catch((error) => { |       var results = await this.$axios.$get(`/api/search/${searchEntity}?${searchQuery}`, { timeout: 20000 }).catch((error) => { | ||||||
|         console.error('Failed', error) |         console.error('Failed', error) | ||||||
|         return [] |         return [] | ||||||
|       }) |       }) | ||||||
|  | |||||||
| @ -10,12 +10,48 @@ export const state = () => ({ | |||||||
|       value: 'openlibrary' |       value: 'openlibrary' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       text: 'Audible', |       text: 'iTunes', | ||||||
|  |       value: 'itunes' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.com', | ||||||
|       value: 'audible' |       value: 'audible' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       text: 'iTunes', |       text: 'Audible.ca', | ||||||
|       value: 'itunes' |       value: 'audible.ca' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.co.uk', | ||||||
|  |       value: 'audible.uk' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.co.au', | ||||||
|  |       value: 'audible.au' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.fr', | ||||||
|  |       value: 'audible.fr' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.de', | ||||||
|  |       value: 'audible.de' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.co.jp', | ||||||
|  |       value: 'audible.jp' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.it', | ||||||
|  |       value: 'audible.it' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.co.in', | ||||||
|  |       value: 'audible.in' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       text: 'Audible.es', | ||||||
|  |       value: 'audible.es' | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   podcastProviders: [ |   podcastProviders: [ | ||||||
|  | |||||||
| @ -150,8 +150,9 @@ class BookFinder { | |||||||
|     return this.iTunesApi.searchAudiobooks(title) |     return this.iTunesApi.searchAudiobooks(title) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async getAudibleResults(title, author, asin) { |   async getAudibleResults(title, author, asin, provider) { | ||||||
|     var books = await this.audible.search(title, author, asin); |     const region = provider.includes('.') ? provider.split('.').pop() : '' | ||||||
|  |     const books = await this.audible.search(title, author, asin, region) | ||||||
|     if (this.verbose) Logger.debug(`Audible Book Search Results: ${books.length || 0}`) |     if (this.verbose) Logger.debug(`Audible Book Search Results: ${books.length || 0}`) | ||||||
|     if (!books) return [] |     if (!books) return [] | ||||||
|     return books |     return books | ||||||
| @ -165,8 +166,8 @@ class BookFinder { | |||||||
| 
 | 
 | ||||||
|     if (provider === 'google') { |     if (provider === 'google') { | ||||||
|       books = await this.getGoogleBooksResults(title, author) |       books = await this.getGoogleBooksResults(title, author) | ||||||
|     } else if (provider === 'audible') { |     } else if (provider.startsWith('audible')) { | ||||||
|       books = await this.getAudibleResults(title, author, asin) |       books = await this.getAudibleResults(title, author, asin, provider) | ||||||
|     } else if (provider === 'itunes') { |     } else if (provider === 'itunes') { | ||||||
|       books = await this.getiTunesAudiobooksResults(title, author) |       books = await this.getiTunesAudiobooksResults(title, author) | ||||||
|     } else if (provider === 'openlibrary') { |     } else if (provider === 'openlibrary') { | ||||||
|  | |||||||
| @ -3,7 +3,20 @@ const htmlSanitizer = require('../utils/htmlSanitizer') | |||||||
| const Logger = require('../Logger') | const Logger = require('../Logger') | ||||||
| 
 | 
 | ||||||
| class Audible { | class Audible { | ||||||
|     constructor() { } |     constructor() { | ||||||
|  |         this.regionMap = { | ||||||
|  |             'us': '.com', | ||||||
|  |             'ca': '.ca', | ||||||
|  |             'uk': '.co.uk', | ||||||
|  |             'au': '.co.au', | ||||||
|  |             'fr': '.fr', | ||||||
|  |             'de': '.de', | ||||||
|  |             'jp': '.co.jp', | ||||||
|  |             'it': '.it', | ||||||
|  |             'in': '.co.in', | ||||||
|  |             'es': '.es' | ||||||
|  |         } | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     cleanResult(item) { |     cleanResult(item) { | ||||||
|         var { title, subtitle, asin, authors, narrators, publisherName, summary, releaseDate, image, genres, seriesPrimary, seriesSecondary, language, runtimeLengthMin } = item |         var { title, subtitle, asin, authors, narrators, publisherName, summary, releaseDate, image, genres, seriesPrimary, seriesSecondary, language, runtimeLengthMin } = item | ||||||
| @ -29,7 +42,9 @@ class Audible { | |||||||
|             tags: tagsFiltered.length ? tagsFiltered.join(', ') : null, |             tags: tagsFiltered.length ? tagsFiltered.join(', ') : null, | ||||||
|             series: series != [] ? series.map(({ name, position }) => ({ series: name, sequence: position })) : null, |             series: series != [] ? series.map(({ name, position }) => ({ series: name, sequence: position })) : null, | ||||||
|             language: language ? language.charAt(0).toUpperCase() + language.slice(1) : null, |             language: language ? language.charAt(0).toUpperCase() + language.slice(1) : null, | ||||||
|             duration: runtimeLengthMin && !isNaN(runtimeLengthMin) ? Number(runtimeLengthMin) : 0 |             duration: runtimeLengthMin && !isNaN(runtimeLengthMin) ? Number(runtimeLengthMin) : 0, | ||||||
|  |             region: item.region || null, | ||||||
|  |             rating: item.rating || null | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -37,9 +52,10 @@ class Audible { | |||||||
|         return /^[0-9A-Z]{10}$/.test(title) |         return /^[0-9A-Z]{10}$/.test(title) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     asinSearch(asin) { |     asinSearch(asin, region) { | ||||||
|         asin = encodeURIComponent(asin); |         asin = encodeURIComponent(asin); | ||||||
|         var url = `https://api.audnex.us/books/${asin}` |         var regionQuery = region ? `?region=${region}` : '' | ||||||
|  |         var url = `https://api.audnex.us/books/${asin}${regionQuery}` | ||||||
|         Logger.debug(`[Audible] ASIN url: ${url}`) |         Logger.debug(`[Audible] ASIN url: ${url}`) | ||||||
|         return axios.get(url).then((res) => { |         return axios.get(url).then((res) => { | ||||||
|             if (!res || !res.data || !res.data.asin) return null |             if (!res || !res.data || !res.data.asin) return null | ||||||
| @ -50,14 +66,19 @@ class Audible { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async search(title, author, asin) { |     async search(title, author, asin, region) { | ||||||
|  |         if (region && !this.regionMap[region]) { | ||||||
|  |             Logger.error(`[Audible] search: Invalid region ${region}`) | ||||||
|  |             region = '' | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         var items |         var items | ||||||
|         if (asin) { |         if (asin) { | ||||||
|             items = [await this.asinSearch(asin)] |             items = [await this.asinSearch(asin, region)] | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!items && this.isProbablyAsin(title)) { |         if (!items && this.isProbablyAsin(title)) { | ||||||
|             items = [await this.asinSearch(title)] |             items = [await this.asinSearch(title, region)] | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!items) { |         if (!items) { | ||||||
| @ -65,14 +86,15 @@ class Audible { | |||||||
|                 num_results: '10', |                 num_results: '10', | ||||||
|                 products_sort_by: 'Relevance', |                 products_sort_by: 'Relevance', | ||||||
|                 title: title |                 title: title | ||||||
|             }; |             } | ||||||
|             if (author) queryObj.author = author |             if (author) queryObj.author = author | ||||||
|             var queryString = (new URLSearchParams(queryObj)).toString(); |             const queryString = (new URLSearchParams(queryObj)).toString() | ||||||
|             var url = `https://api.audible.com/1.0/catalog/products?${queryString}` |             const tld = region ? this.regionMap[region] : '.com' | ||||||
|  |             const url = `https://api.audible${tld}/1.0/catalog/products?${queryString}` | ||||||
|             Logger.debug(`[Audible] Search url: ${url}`) |             Logger.debug(`[Audible] Search url: ${url}`) | ||||||
|             items = await axios.get(url).then((res) => { |             items = await axios.get(url).then((res) => { | ||||||
|                 if (!res || !res.data || !res.data.products) return null |                 if (!res || !res.data || !res.data.products) return null | ||||||
|                 return Promise.all(res.data.products.map(result => this.asinSearch(result.asin))) |                 return Promise.all(res.data.products.map(result => this.asinSearch(result.asin, region))) | ||||||
|             }).catch(error => { |             }).catch(error => { | ||||||
|                 Logger.error('[Audible] query search error', error) |                 Logger.error('[Audible] query search error', error) | ||||||
|                 return [] |                 return [] | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ class Audnexus { | |||||||
|     return { |     return { | ||||||
|       asin: author.asin, |       asin: author.asin, | ||||||
|       description: author.description, |       description: author.description, | ||||||
|       image: author.image, |       image: author.image || null, | ||||||
|       name: author.name |       name: author.name | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -54,7 +54,7 @@ class Audnexus { | |||||||
|     return { |     return { | ||||||
|       asin: author.asin, |       asin: author.asin, | ||||||
|       description: author.description, |       description: author.description, | ||||||
|       image: author.image, |       image: author.image || null, | ||||||
|       name: author.name |       name: author.name | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user