mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Change:Server setting for coverDestination to storeCoverWithBook boolean, Add:abmetadata generator
This commit is contained in:
		
							parent
							
								
									4e7d2ddc58
								
							
						
					
					
						commit
						eb109c398f
					
				| @ -57,16 +57,6 @@ export default { | |||||||
|       this.$store.commit('setDeveloperMode', value) |       this.$store.commit('setDeveloperMode', value) | ||||||
|       this.$toast.info(`Developer Mode ${value ? 'Enabled' : 'Disabled'}`) |       this.$toast.info(`Developer Mode ${value ? 'Enabled' : 'Disabled'}`) | ||||||
|     } |     } | ||||||
|     // saveMetadataComplete(result) { |  | ||||||
|     //   this.savingMetadata = false |  | ||||||
|     //   if (!result) return |  | ||||||
|     //   this.$toast.success(`Metadata saved for ${result.success} audiobooks`) |  | ||||||
|     // }, |  | ||||||
|     // saveMetadataFiles() { |  | ||||||
|     //   this.savingMetadata = true |  | ||||||
|     //   this.$root.socket.once('save_metadata_complete', this.saveMetadataComplete) |  | ||||||
|     //   this.$root.socket.emit('save_metadata') |  | ||||||
|     // } |  | ||||||
|   }, |   }, | ||||||
|   mounted() {} |   mounted() {} | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,8 +8,8 @@ | |||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|       <div class="flex items-center py-2"> |       <div class="flex items-center py-2"> | ||||||
|         <ui-toggle-switch v-model="storeCoversInAudiobookDir" :disabled="updatingServerSettings" @input="updateCoverStorageDestination" /> |         <ui-toggle-switch v-model="newServerSettings.storeCoverWithBook" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('storeCoverWithBook', val)" /> | ||||||
|         <ui-tooltip :text="tooltips.coverDestination"> |         <ui-tooltip :text="tooltips.storeCoverWithBook"> | ||||||
|           <p class="pl-4 text-lg"> |           <p class="pl-4 text-lg"> | ||||||
|             Store covers with audiobook |             Store covers with audiobook | ||||||
|             <span class="material-icons icon-text">info_outlined</span> |             <span class="material-icons icon-text">info_outlined</span> | ||||||
| @ -172,7 +172,6 @@ export default { | |||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       isResettingAudiobooks: false, |       isResettingAudiobooks: false, | ||||||
|       storeCoversInAudiobookDir: false, |  | ||||||
|       updatingServerSettings: false, |       updatingServerSettings: false, | ||||||
|       useSquareBookCovers: false, |       useSquareBookCovers: false, | ||||||
|       useAlternativeBookshelfView: false, |       useAlternativeBookshelfView: false, | ||||||
| @ -185,7 +184,7 @@ export default { | |||||||
|         scannerParseSubtitle: 'Extract subtitles from audiobook directory names.<br>Subtitle must be seperated by " - "<br>i.e. "Book Title - A Subtitle Here" has the subtitle "A Subtitle Here"', |         scannerParseSubtitle: 'Extract subtitles from audiobook directory names.<br>Subtitle must be seperated by " - "<br>i.e. "Book Title - A Subtitle Here" has the subtitle "A Subtitle Here"', | ||||||
|         scannerFindCovers: 'If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time', |         scannerFindCovers: 'If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time', | ||||||
|         bookshelfView: 'Alternative bookshelf view that shows title & author under book covers', |         bookshelfView: 'Alternative bookshelf view that shows title & author under book covers', | ||||||
|         coverDestination: 'By default covers are stored in /metadata/books, enabling this setting will store covers inside your audiobooks directory. Only one file named "cover" will be kept.', |         storeCoverWithBook: 'By default covers are stored in /metadata/books, enabling this setting will store covers inside your audiobooks directory. Only one file named "cover" will be kept.', | ||||||
|         coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers' |         coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers' | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -226,12 +225,6 @@ export default { | |||||||
|         scannerCoverProvider: val |         scannerCoverProvider: val | ||||||
|       }) |       }) | ||||||
|     }, |     }, | ||||||
|     updateCoverStorageDestination(val) { |  | ||||||
|       this.newServerSettings.coverDestination = val ? this.$constants.CoverDestination.AUDIOBOOK : this.$constants.CoverDestination.METADATA |  | ||||||
|       this.updateServerSettings({ |  | ||||||
|         coverDestination: this.newServerSettings.coverDestination |  | ||||||
|       }) |  | ||||||
|     }, |  | ||||||
|     updateBookCoverAspectRatio(val) { |     updateBookCoverAspectRatio(val) { | ||||||
|       this.updateServerSettings({ |       this.updateServerSettings({ | ||||||
|         coverAspectRatio: val ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD |         coverAspectRatio: val ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD | ||||||
| @ -263,8 +256,6 @@ export default { | |||||||
|     initServerSettings() { |     initServerSettings() { | ||||||
|       this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {} |       this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {} | ||||||
| 
 | 
 | ||||||
|       this.storeCoversInAudiobookDir = this.newServerSettings.coverDestination === this.$constants.CoverDestination.AUDIOBOOK |  | ||||||
| 
 |  | ||||||
|       this.useSquareBookCovers = this.newServerSettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE |       this.useSquareBookCovers = this.newServerSettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE | ||||||
| 
 | 
 | ||||||
|       this.useAlternativeBookshelfView = this.newServerSettings.bookshelfView === this.$constants.BookshelfView.TITLES |       this.useAlternativeBookshelfView = this.newServerSettings.bookshelfView === this.$constants.BookshelfView.TITLES | ||||||
|  | |||||||
| @ -14,11 +14,6 @@ const DownloadStatus = { | |||||||
|   FAILED: 3 |   FAILED: 3 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const CoverDestination = { |  | ||||||
|   METADATA: 0, |  | ||||||
|   AUDIOBOOK: 1 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const BookCoverAspectRatio = { | const BookCoverAspectRatio = { | ||||||
|   STANDARD: 0, |   STANDARD: 0, | ||||||
|   SQUARE: 1 |   SQUARE: 1 | ||||||
| @ -32,7 +27,6 @@ const BookshelfView = { | |||||||
| const Constants = { | const Constants = { | ||||||
|   SupportedFileTypes, |   SupportedFileTypes, | ||||||
|   DownloadStatus, |   DownloadStatus, | ||||||
|   CoverDestination, |  | ||||||
|   BookCoverAspectRatio, |   BookCoverAspectRatio, | ||||||
|   BookshelfView |   BookshelfView | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,7 +6,6 @@ const readChunk = require('read-chunk') | |||||||
| const imageType = require('image-type') | const imageType = require('image-type') | ||||||
| 
 | 
 | ||||||
| const globals = require('./utils/globals') | const globals = require('./utils/globals') | ||||||
| const { CoverDestination } = require('./utils/constants') |  | ||||||
| const { downloadFile } = require('./utils/fileUtils') | const { downloadFile } = require('./utils/fileUtils') | ||||||
| 
 | 
 | ||||||
| class CoverController { | class CoverController { | ||||||
| @ -20,7 +19,7 @@ class CoverController { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getCoverDirectory(audiobook) { |   getCoverDirectory(audiobook) { | ||||||
|     if (this.db.serverSettings.coverDestination === CoverDestination.AUDIOBOOK) { |     if (this.db.serverSettings.storeCoverWithBook) { | ||||||
|       return { |       return { | ||||||
|         fullPath: audiobook.fullPath, |         fullPath: audiobook.fullPath, | ||||||
|         relPath: '/s/book/' + audiobook.id |         relPath: '/s/book/' + audiobook.id | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| const { CoverDestination, BookCoverAspectRatio, BookshelfView } = require('../utils/constants') | const { BookCoverAspectRatio, BookshelfView } = require('../utils/constants') | ||||||
| const Logger = require('../Logger') | const Logger = require('../Logger') | ||||||
| 
 | 
 | ||||||
| class ServerSettings { | class ServerSettings { | ||||||
| @ -18,8 +18,8 @@ class ServerSettings { | |||||||
|     this.scannerDisableWatcher = false |     this.scannerDisableWatcher = false | ||||||
| 
 | 
 | ||||||
|     // Metadata
 |     // Metadata
 | ||||||
|     this.coverDestination = CoverDestination.METADATA |     this.storeCoverWithBook = false | ||||||
|     this.saveMetadataFile = false |     this.storeMetadataWithBook = false | ||||||
| 
 | 
 | ||||||
|     // Security/Rate limits
 |     // Security/Rate limits
 | ||||||
|     this.rateLimitLoginRequests = 10 |     this.rateLimitLoginRequests = 10 | ||||||
| @ -59,8 +59,12 @@ class ServerSettings { | |||||||
|     this.scannerPreferOpfMetadata = !!settings.scannerPreferOpfMetadata |     this.scannerPreferOpfMetadata = !!settings.scannerPreferOpfMetadata | ||||||
|     this.scannerDisableWatcher = !!settings.scannerDisableWatcher |     this.scannerDisableWatcher = !!settings.scannerDisableWatcher | ||||||
| 
 | 
 | ||||||
|     this.coverDestination = settings.coverDestination || CoverDestination.METADATA |     this.storeCoverWithBook = settings.storeCoverWithBook | ||||||
|     this.saveMetadataFile = !!settings.saveMetadataFile |     if (this.storeCoverWithBook == undefined) { // storeCoverWithBook added in 1.7.1 to replace coverDestination
 | ||||||
|  |       this.storeCoverWithBook = !!settings.coverDestination | ||||||
|  |     } | ||||||
|  |     this.storeMetadataWithBook = !!settings.storeCoverWithBook | ||||||
|  | 
 | ||||||
|     this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10 |     this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10 | ||||||
|     this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes
 |     this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes
 | ||||||
| 
 | 
 | ||||||
| @ -95,8 +99,8 @@ class ServerSettings { | |||||||
|       scannerPreferAudioMetadata: this.scannerPreferAudioMetadata, |       scannerPreferAudioMetadata: this.scannerPreferAudioMetadata, | ||||||
|       scannerPreferOpfMetadata: this.scannerPreferOpfMetadata, |       scannerPreferOpfMetadata: this.scannerPreferOpfMetadata, | ||||||
|       scannerDisableWatcher: this.scannerDisableWatcher, |       scannerDisableWatcher: this.scannerDisableWatcher, | ||||||
|       coverDestination: this.coverDestination, |       storeCoverWithBook: this.storeCoverWithBook, | ||||||
|       saveMetadataFile: !!this.saveMetadataFile, |       storeMetadataWithBook: this.storeMetadataWithBook, | ||||||
|       rateLimitLoginRequests: this.rateLimitLoginRequests, |       rateLimitLoginRequests: this.rateLimitLoginRequests, | ||||||
|       rateLimitLoginWindow: this.rateLimitLoginWindow, |       rateLimitLoginWindow: this.rateLimitLoginWindow, | ||||||
|       backupSchedule: this.backupSchedule, |       backupSchedule: this.backupSchedule, | ||||||
|  | |||||||
| @ -1,5 +1,3 @@ | |||||||
| const { CoverDestination } = require('../utils/constants') |  | ||||||
| 
 |  | ||||||
| class ScanOptions { | class ScanOptions { | ||||||
|   constructor(options) { |   constructor(options) { | ||||||
|     this.forceRescan = false |     this.forceRescan = false | ||||||
| @ -7,7 +5,7 @@ class ScanOptions { | |||||||
|     // Server settings
 |     // Server settings
 | ||||||
|     this.parseSubtitles = false |     this.parseSubtitles = false | ||||||
|     this.findCovers = false |     this.findCovers = false | ||||||
|     this.coverDestination = CoverDestination.METADATA |     this.storeCoverWithBook = false | ||||||
|     this.preferAudioMetadata = false |     this.preferAudioMetadata = false | ||||||
|     this.preferOpfMetadata = false |     this.preferOpfMetadata = false | ||||||
| 
 | 
 | ||||||
| @ -32,7 +30,7 @@ class ScanOptions { | |||||||
|       metadataPrecedence: this.metadataPrecedence, |       metadataPrecedence: this.metadataPrecedence, | ||||||
|       parseSubtitles: this.parseSubtitles, |       parseSubtitles: this.parseSubtitles, | ||||||
|       findCovers: this.findCovers, |       findCovers: this.findCovers, | ||||||
|       coverDestination: this.coverDestination, |       storeCoverWithBook: this.storeCoverWithBook, | ||||||
|       preferAudioMetadata: this.preferAudioMetadata, |       preferAudioMetadata: this.preferAudioMetadata, | ||||||
|       preferOpfMetadata: this.preferOpfMetadata |       preferOpfMetadata: this.preferOpfMetadata | ||||||
|     } |     } | ||||||
| @ -43,7 +41,7 @@ class ScanOptions { | |||||||
| 
 | 
 | ||||||
|     this.parseSubtitles = !!serverSettings.scannerParseSubtitle |     this.parseSubtitles = !!serverSettings.scannerParseSubtitle | ||||||
|     this.findCovers = !!serverSettings.scannerFindCovers |     this.findCovers = !!serverSettings.scannerFindCovers | ||||||
|     this.coverDestination = serverSettings.coverDestination |     this.storeCoverWithBook = serverSettings.storeCoverWithBook | ||||||
|     this.preferAudioMetadata = serverSettings.scannerPreferAudioMetadata |     this.preferAudioMetadata = serverSettings.scannerPreferAudioMetadata | ||||||
|     this.preferOpfMetadata = serverSettings.scannerPreferOpfMetadata |     this.preferOpfMetadata = serverSettings.scannerPreferOpfMetadata | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ const Path = require('path') | |||||||
| const Logger = require('../Logger') | const Logger = require('../Logger') | ||||||
| const { version } = require('../../package.json') | const { version } = require('../../package.json') | ||||||
| const { groupFilesIntoAudiobookPaths, getAudiobookFileData, scanRootDir } = require('../utils/scandir') | const { groupFilesIntoAudiobookPaths, getAudiobookFileData, scanRootDir } = require('../utils/scandir') | ||||||
| const { comparePaths, getIno, getId, msToTimestamp } = require('../utils/index') | const { comparePaths, getId } = require('../utils/index') | ||||||
| const { ScanResult, CoverDestination, LogLevel } = require('../utils/constants') | const { ScanResult, LogLevel } = require('../utils/constants') | ||||||
| 
 | 
 | ||||||
| const AudioFileScanner = require('./AudioFileScanner') | const AudioFileScanner = require('./AudioFileScanner') | ||||||
| const BookFinder = require('../BookFinder') | const BookFinder = require('../BookFinder') | ||||||
| @ -33,7 +33,7 @@ class Scanner { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getCoverDirectory(audiobook) { |   getCoverDirectory(audiobook) { | ||||||
|     if (this.db.serverSettings.coverDestination === CoverDestination.AUDIOBOOK) { |     if (this.db.serverSettings.storeCoverWithBook) { | ||||||
|       return { |       return { | ||||||
|         fullPath: audiobook.fullPath, |         fullPath: audiobook.fullPath, | ||||||
|         relPath: '/s/book/' + audiobook.id |         relPath: '/s/book/' + audiobook.id | ||||||
|  | |||||||
| @ -20,13 +20,24 @@ const bookKeyMap = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function generate(audiobook, outputPath, uid, gid) { | function generate(audiobook, outputPath, uid, gid) { | ||||||
|   var fileString = `[audiobookshelf v${package.version}]\n` |   var fileString = ';ABMETADATA1\n' | ||||||
|  |   fileString += `#audiobookshelf v${package.version}\n\n` | ||||||
| 
 | 
 | ||||||
|   for (const key in bookKeyMap) { |   for (const key in bookKeyMap) { | ||||||
|     const value = audiobook.book[bookKeyMap[key]] || '' |     const value = audiobook.book[bookKeyMap[key]] || '' | ||||||
|     fileString += `${key}=${value}\n` |     fileString += `${key}=${value}\n` | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   if (audiobook.chapters.length) { | ||||||
|  |     fileString += '\n' | ||||||
|  |     audiobook.chapters.forEach((chapter) => { | ||||||
|  |       fileString += `[CHAPTER]\n` | ||||||
|  |       fileString += `start=${chapter.start}\n` | ||||||
|  |       fileString += `end=${chapter.end}\n` | ||||||
|  |       fileString += `title=${chapter.title}\n` | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return fs.writeFile(outputPath, fileString).then(() => { |   return fs.writeFile(outputPath, fileString).then(() => { | ||||||
|     return filePerms(outputPath, 0o774, uid, gid).then(() => true) |     return filePerms(outputPath, 0o774, uid, gid).then(() => true) | ||||||
|   }).catch((error) => { |   }).catch((error) => { | ||||||
| @ -6,11 +6,6 @@ module.exports.ScanResult = { | |||||||
|   UPTODATE: 4 |   UPTODATE: 4 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module.exports.CoverDestination = { |  | ||||||
|   METADATA: 0, |  | ||||||
|   AUDIOBOOK: 1 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| module.exports.BookCoverAspectRatio = { | module.exports.BookCoverAspectRatio = { | ||||||
|   STANDARD: 0, // 1.6:1
 |   STANDARD: 0, // 1.6:1
 | ||||||
|   SQUARE: 1 |   SQUARE: 1 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user