mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Fix:Podcast episodes duplicated when a scan runs while the episode is downloading #2785
This commit is contained in:
parent
a5ebd89817
commit
850ed48955
@ -149,6 +149,9 @@ class Server {
|
|||||||
Watcher.disabled = true
|
Watcher.disabled = true
|
||||||
} else {
|
} else {
|
||||||
Watcher.initWatcher(libraries)
|
Watcher.initWatcher(libraries)
|
||||||
|
Watcher.on('scanFilesChanged', (pendingFileUpdates, pendingTask) => {
|
||||||
|
LibraryScanner.scanFilesChanged(pendingFileUpdates, pendingTask)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ const Path = require('path')
|
|||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const Watcher = require('./libs/watcher/watcher')
|
const Watcher = require('./libs/watcher/watcher')
|
||||||
const Logger = require('./Logger')
|
const Logger = require('./Logger')
|
||||||
const LibraryScanner = require('./scanner/LibraryScanner')
|
|
||||||
const Task = require('./objects/Task')
|
const Task = require('./objects/Task')
|
||||||
const TaskManager = require('./managers/TaskManager')
|
const TaskManager = require('./managers/TaskManager')
|
||||||
|
|
||||||
@ -31,6 +30,8 @@ class FolderWatcher extends EventEmitter {
|
|||||||
|
|
||||||
this.filesBeingAdded = new Set()
|
this.filesBeingAdded = new Set()
|
||||||
|
|
||||||
|
/** @type {Set<string>} */
|
||||||
|
this.ignoreFilePathsDownloading = new Set()
|
||||||
/** @type {string[]} */
|
/** @type {string[]} */
|
||||||
this.ignoreDirs = []
|
this.ignoreDirs = []
|
||||||
/** @type {string[]} */
|
/** @type {string[]} */
|
||||||
@ -333,7 +334,7 @@ class FolderWatcher extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.pendingFileUpdates.length) {
|
if (this.pendingFileUpdates.length) {
|
||||||
LibraryScanner.scanFilesChanged(this.pendingFileUpdates, this.pendingTask)
|
this.emit('scanFilesChanged', this.pendingFileUpdates, this.pendingTask)
|
||||||
} else {
|
} else {
|
||||||
const taskFinishedString = {
|
const taskFinishedString = {
|
||||||
text: 'No files to scan',
|
text: 'No files to scan',
|
||||||
@ -348,12 +349,29 @@ class FolderWatcher extends EventEmitter {
|
|||||||
}, this.pendingDelay)
|
}, this.pendingDelay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
checkShouldIgnorePath(path) {
|
checkShouldIgnorePath(path) {
|
||||||
return !!this.ignoreDirs.find((dirpath) => {
|
return !!this.ignoreDirs.find((dirpath) => {
|
||||||
return isSameOrSubPath(dirpath, path)
|
return isSameOrSubPath(dirpath, path)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When scanning a library item folder these files should be ignored
|
||||||
|
* Either a podcast episode downloading or a file that is pending by the watcher
|
||||||
|
*
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
checkShouldIgnoreFilePath(path) {
|
||||||
|
if (this.pendingFilePaths.includes(path)) return true
|
||||||
|
return this.ignoreFilePathsDownloading.has(path)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to POSIX and remove trailing slash
|
* Convert to POSIX and remove trailing slash
|
||||||
* @param {string} path
|
* @param {string} path
|
||||||
|
@ -97,6 +97,7 @@ class PodcastManager {
|
|||||||
|
|
||||||
// Ignores all added files to this dir
|
// Ignores all added files to this dir
|
||||||
Watcher.addIgnoreDir(this.currentDownload.libraryItem.path)
|
Watcher.addIgnoreDir(this.currentDownload.libraryItem.path)
|
||||||
|
Watcher.ignoreFilePathsDownloading.add(this.currentDownload.targetPath)
|
||||||
|
|
||||||
// Make sure podcast library item folder exists
|
// Make sure podcast library item folder exists
|
||||||
if (!(await fs.pathExists(this.currentDownload.libraryItem.path))) {
|
if (!(await fs.pathExists(this.currentDownload.libraryItem.path))) {
|
||||||
@ -151,6 +152,8 @@ class PodcastManager {
|
|||||||
SocketAuthority.emitter('episode_download_queue_updated', this.getDownloadQueueDetails())
|
SocketAuthority.emitter('episode_download_queue_updated', this.getDownloadQueueDetails())
|
||||||
|
|
||||||
Watcher.removeIgnoreDir(this.currentDownload.libraryItem.path)
|
Watcher.removeIgnoreDir(this.currentDownload.libraryItem.path)
|
||||||
|
|
||||||
|
Watcher.ignoreFilePathsDownloading.delete(this.currentDownload.targetPath)
|
||||||
this.currentDownload = null
|
this.currentDownload = null
|
||||||
if (this.downloadQueue.length) {
|
if (this.downloadQueue.length) {
|
||||||
this.startPodcastEpisodeDownload(this.downloadQueue.shift())
|
this.startPodcastEpisodeDownload(this.downloadQueue.shift())
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const Path = require('path')
|
const Path = require('path')
|
||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require('uuid').v4
|
||||||
const { sanitizeFilename } = require('../utils/fileUtils')
|
const { sanitizeFilename, filePathToPOSIX } = require('../utils/fileUtils')
|
||||||
const globals = require('../utils/globals')
|
const globals = require('../utils/globals')
|
||||||
|
|
||||||
class PodcastEpisodeDownload {
|
class PodcastEpisodeDownload {
|
||||||
@ -60,7 +60,7 @@ class PodcastEpisodeDownload {
|
|||||||
return sanitizeFilename(filename)
|
return sanitizeFilename(filename)
|
||||||
}
|
}
|
||||||
get targetPath() {
|
get targetPath() {
|
||||||
return Path.join(this.libraryItem.path, this.targetFilename)
|
return filePathToPOSIX(Path.join(this.libraryItem.path, this.targetFilename))
|
||||||
}
|
}
|
||||||
get targetRelPath() {
|
get targetRelPath() {
|
||||||
return this.targetFilename
|
return this.targetFilename
|
||||||
@ -74,7 +74,8 @@ class PodcastEpisodeDownload {
|
|||||||
this.podcastEpisode = podcastEpisode
|
this.podcastEpisode = podcastEpisode
|
||||||
|
|
||||||
const url = podcastEpisode.enclosure.url
|
const url = podcastEpisode.enclosure.url
|
||||||
if (decodeURIComponent(url) !== url) { // Already encoded
|
if (decodeURIComponent(url) !== url) {
|
||||||
|
// Already encoded
|
||||||
this.url = url
|
this.url = url
|
||||||
} else {
|
} else {
|
||||||
this.url = encodeURI(url)
|
this.url = encodeURI(url)
|
||||||
|
@ -4,7 +4,9 @@ const { LogLevel, ScanResult } = require('../utils/constants')
|
|||||||
const fileUtils = require('../utils/fileUtils')
|
const fileUtils = require('../utils/fileUtils')
|
||||||
const scanUtils = require('../utils/scandir')
|
const scanUtils = require('../utils/scandir')
|
||||||
const libraryFilters = require('../utils/queries/libraryFilters')
|
const libraryFilters = require('../utils/queries/libraryFilters')
|
||||||
|
const Logger = require('../Logger')
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
|
const Watcher = require('../Watcher')
|
||||||
const LibraryScan = require('./LibraryScan')
|
const LibraryScan = require('./LibraryScan')
|
||||||
const LibraryItemScanData = require('./LibraryItemScanData')
|
const LibraryItemScanData = require('./LibraryItemScanData')
|
||||||
const BookScanner = require('./BookScanner')
|
const BookScanner = require('./BookScanner')
|
||||||
@ -128,6 +130,13 @@ class LibraryItemScanner {
|
|||||||
const libraryFiles = []
|
const libraryFiles = []
|
||||||
for (let i = 0; i < fileItems.length; i++) {
|
for (let i = 0; i < fileItems.length; i++) {
|
||||||
const fileItem = fileItems[i]
|
const fileItem = fileItems[i]
|
||||||
|
|
||||||
|
if (Watcher.checkShouldIgnoreFilePath(fileItem.fullpath)) {
|
||||||
|
// Skip file if it's pending
|
||||||
|
Logger.info(`[LibraryItemScanner] Skipping watcher pending file "${fileItem.fullpath}" during scan of library item path "${libraryItemPath}"`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const newLibraryFile = new LibraryFile()
|
const newLibraryFile = new LibraryFile()
|
||||||
// fileItem.path is the relative path
|
// fileItem.path is the relative path
|
||||||
await newLibraryFile.setDataFromPath(fileItem.fullpath, fileItem.path)
|
await newLibraryFile.setDataFromPath(fileItem.fullpath, fileItem.path)
|
||||||
|
Loading…
Reference in New Issue
Block a user